Compare commits

...
964 Commits
Author SHA1 Message Date
Roberto De Ioris e8aa0e1e26 fixed a typecasting 2013-03-11 20:51:08 +01:00
Unbit 46a8aae908 added CacheGet to mono 2013-03-11 16:10:39 +01:00
Unbit a9f90464e6 fixed routing condition bug 2013-03-11 12:44:22 +01:00
Unbit 4bcdba2334 removed Changelog, we maintain them online 2013-03-11 12:16:44 +01:00
Unbit 64a8f3464a fixed routing goto 2013-03-11 10:37:10 +01:00
Unbit e640bd6f9b completed legion scroll 2013-03-11 09:44:50 +01:00
Unbit 71a6726bcf finally removed --app and static-offload-to-thread 2013-03-11 07:13:05 +01:00
Unbit fe13774b4b internal routing optimization 2013-03-11 07:05:58 +01:00
Unbit ecc3a5e8e2 another routing fix 2013-03-11 06:46:52 +01:00
Unbit dd1881576a removed grunt support 2013-03-10 22:22:16 +01:00
Unbit 322a2d2365 improved routing + static management 2013-03-10 21:30:54 +01:00
Unbit a76d7a1c66 first part of legion scroll implementation 2013-03-10 17:55:58 +01:00
Unbit 5631dcabf8 fixed --static-index when methods different from GET/HEAD are in place 2013-03-10 12:05:25 +01:00
Unbit 3f731e2577 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-10 08:55:05 +01:00
Unbit 7a1b7f299b added --whitelist and --blacklist context 2013-03-10 08:54:45 +01:00
unbit 322673215e Merge pull request #178 from xrmx/coverity-buildconf
Add build profile for coverity scan
2013-03-09 15:28:44 -08:00
Riccardo Magliocchetti b58a0c4969 Add build profile for coverity scan
Add all the language plugins i can actually compile on my machine
so that we have a bit more plugin coverage instead of the plain make.
31 more bugs reported by Coverity scan.
2013-03-09 18:32:15 +01:00
Unbit c5fe8c6d30 reverted flock fd anti-leak 2013-03-09 18:13:18 +01:00
Unbit 7f54f5075d fixed a leak in routing api 2013-03-09 18:10:23 +01:00
unbit 95d4cea3bb Merge pull request #177 from xrmx/coverity10
More issues reported by Coverity
2013-03-09 09:03:55 -08:00
Riccardo Magliocchetti d6ff3ac018 core/legion: fix memory leak in wsgi_opt_legion_quorum
Reported by Coverity as CID #971024.
2013-03-09 17:04:57 +01:00
Riccardo Magliocchetti 1f4099c874 core/mule: fix a memory leak in uwsgi_setup_mules_and_farms
Reported by Coverity as CID #971028.
2013-03-09 17:01:18 +01:00
Riccardo Magliocchetti 8cd298de34 core/protocol: fix leak in send_udp_message
By moving the allocation after some early returns in case of error.

Reported by Coverity as CID #971033.
2013-03-09 16:52:20 +01:00
Riccardo Magliocchetti 851df33977 core/queue: close queue store after mmap()
Reported by Coverity as CID #971035.
2013-03-09 16:49:58 +01:00
Riccardo Magliocchetti 17f3f3d9a0 core/stats: fix memory leak in uwsgi_stats_pusher_setup
Reported by Coverity as CID #971039.
2013-03-09 16:46:49 +01:00
Riccardo Magliocchetti 4273489e42 core/uwsgi: fix memory leak in signal_pidfile
Reportd by Coverity as CID #971046.
2013-03-09 16:37:19 +01:00
Riccardo Magliocchetti 57077ac68c core/uwsgi: don't leak fd in flock related function
Reported by Coverity as CID #971047, #971048.
2013-03-09 16:34:32 +01:00
Riccardo Magliocchetti 45f61435a1 core: fix a couple of leaks in uwsgi_opt_load_dl
Reported by Coverity as CID #971049, #971050.
2013-03-09 16:27:57 +01:00
Riccardo Magliocchetti 28153af4ad plugin/python: fix leak in uwsgi_file_loader
Reported by Coverity as CID #971055.
2013-03-09 16:21:16 +01:00
Riccardo Magliocchetti 341cfd90b6 plugin/python: fix a leak in symimporter_load_module
Reported by Coverity as CID #971058.
2013-03-09 16:17:18 +01:00
Riccardo Magliocchetti 82342577a4 plugins/zergpool: fix a couple of memory leaks in add_zergpool_socket
Reported by Coverity as CID #971071, #971070.
2013-03-09 16:02:04 +01:00
Riccardo Magliocchetti 9d735fdbea plugins/python: don't copy router_name in py_uwsgi_route
No need to create a news string since uwsgi_route_api_func use it
for just a strcmp.

Reported by Coverity as CID #989251.
2013-03-09 15:50:02 +01:00
Unbit 1775526b89 improved asp.net support 2013-03-09 15:11:42 +01:00
Unbit c84f205c74 improved mono build 2013-03-09 12:56:40 +01:00
Unbit 591faabc00 fixed spooler plugin 2013-03-09 11:48:56 +01:00
Unbit e945003d07 fixed jwsgi plugin name 2013-03-09 11:27:25 +01:00
Unbit 26c6ec4283 fixed admin and echo plugins 2013-03-09 11:03:46 +01:00
Unbit b64884961d removed unused functions 2013-03-09 09:24:15 +01:00
Unbit 619e853a19 cache sync is working again 2013-03-09 06:34:48 +01:00
Unbit 050908a65e added a test for clojure rpc 2013-03-08 21:11:28 +01:00
Unbit bcb1e623d9 implemented uwsgi.rpc jvm function [test] 2013-03-08 20:59:05 +01:00
Unbit 57105c1bc7 implemented uwsgi.rpc jvm function 2013-03-08 20:58:52 +01:00
Unbit 8bb5b8a9f3 removed old java test 2013-03-08 20:30:26 +01:00
Unbit fba0d196ff fixed php body read 2013-03-08 20:23:09 +01:00
Unbit e29c50c9a5 prepare for JVM uwsgi.rpc() api function 2013-03-08 20:02:21 +01:00
Unbit 4ad9c8d034 fixed default cache set 2013-03-08 20:00:25 +01:00
Unbit 059b4c6ba3 ported cache magic api to go 2013-03-08 19:35:27 +01:00
Unbit 3ab96621db ported magic cache api to lua 2013-03-08 19:06:36 +01:00
Unbit 9bbe148112 ported magic cache api to php 2013-03-08 18:51:31 +01:00
Unbit e32de9b892 ported magic cache api to ruby 2013-03-08 18:12:12 +01:00
Unbit dea7f0fbb8 ported the new magic cache api to perl/psgi 2013-03-08 17:39:55 +01:00
Unbit a684bc6124 completed magic cache clear 2013-03-08 17:21:08 +01:00
Unbit 849ba0856f implemented cache magic exists and del 2013-03-08 17:04:36 +01:00
Unbit f728e277e2 fixed the cache router 2013-03-08 16:40:59 +01:00
Unbit d11fed3511 prepare for exists del and clear 2013-03-08 16:32:46 +01:00
Unbit f3b1acc55e completed cache magic update 2013-03-08 16:26:16 +01:00
Unbit 61722a7876 other improvements in the cache api 2013-03-08 16:16:49 +01:00
Unbit e418a35159 added cache check for max item size 2013-03-08 14:18:49 +01:00
Unbit cd29b033f0 reimplementation of the cache networking protocol to be fully non-blocking 2013-03-08 13:45:27 +01:00
Unbit f3f191558a removed the threaded cache server, it has been superseeded by the new async architecture 2013-03-08 11:29:56 +01:00
Unbit c728471b94 another update to the cache magic api 2013-03-08 11:23:26 +01:00
Unbit 4383578795 prepare for magic cache functions 2013-03-08 10:04:13 +01:00
Unbit b2f127a798 do not start the alarm thread if not needed 2013-03-08 09:19:40 +01:00
Unbit f8212f9e4b fixed alarm subsystem and added uwsgi.alarm to the JVM 2013-03-08 09:18:20 +01:00
Unbit 5e70986bc9 added JVM cache_get and lock/unlock 2013-03-08 08:12:51 +01:00
Unbit d61dff3c26 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-03-08 06:42:04 +01:00
Unbit 2b2da8b7f4 fixed #172 2013-03-08 06:41:46 +01:00
unbit 827b142577 Merge pull request #175 from gber/master
Add optional logging to notfound plugin
2013-03-07 10:40:26 -08:00
Guido Berhoerster d753e1aeef add option for enabling logging in notfound plugin 2013-03-07 19:27:13 +01:00
Unbit 8f7e5fc1bc fixed cache_update for lua 2013-03-07 13:23:24 +01:00
Unbit 650c251236 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-07 13:14:51 +01:00
Unbit 3acb67bd2a try again semop() on interrupt 2013-03-07 13:14:31 +01:00
unbit f9f0eb45e5 Merge pull request #174 from kunkku/lua
Lua binding for cache update function
2013-03-07 01:52:39 -08:00
Kaarle Ritvanen fe0c1a4bb3 Lua binding for cache update function 2013-03-07 09:17:58 +00:00
Unbit eb90b773fa ported JWSGI to the new stable api and refactored ring plugin 2013-03-07 07:01:28 +01:00
Unbit 4f9369aa3a fork() friendly signal management 2013-03-06 20:16:09 +01:00
Unbit 2ae323feee better broodlord num computation 2013-03-06 19:55:20 +01:00
Unbit 56a79ae09c improved broodlord mode [2] 2013-03-06 19:11:49 +01:00
Unbit 48f6d5a240 improved broodlord mode 2013-03-06 19:05:38 +01:00
Unbit 49f717b616 fork() safe rpc subsystem 2013-03-06 18:21:39 +01:00
Unbit 77bae96c34 the ring support is complete 2013-03-06 16:09:06 +01:00
Unbit cbbaa24d6e completetd uwsgi.RequestBody jvm implementation 2013-03-06 14:44:49 +01:00
Unbit 37010c04ca implemented read() method for jvm input stream 2013-03-06 14:26:52 +01:00
Unbit 5902749f9d started implementing jvm body input stream 2013-03-06 13:51:42 +01:00
Unbit b1db1ae651 maintain python2.4 and centos5 compatibility 2013-03-06 13:24:51 +01:00
Unbit d96e394947 implemented ring content-length 2013-03-06 12:25:09 +01:00
Unbit 89891c80ae added ssl error clear even in the ssl router 2013-03-06 11:43:09 +01:00
Unbit edabc3cc6e fixed jvm build on python3 2013-03-06 11:15:16 +01:00
Unbit 9d4300d514 call ERR_clear_error after each https session close 2013-03-06 10:35:32 +01:00
Unbit af1eac9fcc correctly report REMOTE_ADDR and REMOTE_PORT in the fastrouter 2013-03-06 08:55:04 +01:00
Unbit fd50b1e054 allows loading custom classes 2013-03-05 19:23:17 +01:00
Unbit 1239e740ab better jvm class loading 2013-03-05 18:37:20 +01:00
Unbit f6535488e5 more tolerant ring support 2013-03-05 18:00:42 +01:00
Unbit c1c4dd01d2 ring + input_stream completed 2013-03-05 14:01:22 +01:00
Unbit 5cc9c8405a completed uwsgi_jvm_consume_input_stream 2013-03-05 13:56:30 +01:00
Unbit 990028697b Merge branch 'master' of github.com:unbit/uwsgi 2013-03-05 13:44:37 +01:00
Unbit 666c7c5b3f improved OSX jvm auto-detection 2013-03-05 13:40:35 +01:00
Unbit 1ccf9335dd prepare for managing InputStream 2013-03-05 07:58:01 +01:00
Unbit f90bb6b53c better iSeq detection in ring 2013-03-05 07:20:38 +01:00
Unbit 0ad74e282c better jvm paths detection 2013-03-04 21:40:47 +01:00
Unbit 34d6c0ad16 added some doc on top of the ring plugin 2013-03-04 21:36:06 +01:00
Unbit 4ceeb3b789 added more request item to the ring request map 2013-03-04 21:24:45 +01:00
Unbit 259c6c493f huge amount of jvm memory leak fixes 2013-03-04 21:18:59 +01:00
Unbit a3dd2e6efd added support ring clojure.io.file response 2013-03-04 16:50:37 +01:00
Unbit af3860dbd7 completed status and headers management for the ring plugin 2013-03-04 15:43:52 +01:00
Unbit 980b4f3c9a fixed type in yaml/ini parsers 2013-03-04 14:09:13 +01:00
Unbit efa0e0b27b added jvm api for iterations 2013-03-04 14:07:52 +01:00
Unbit d8d60e9a24 signals can now be registered even by non-fork friendly plugins 2013-03-04 06:48:25 +01:00
Unbit 6f5a521692 ported post_build hooks to the new build system 2013-03-04 06:14:22 +01:00
Unbit 522cbfe855 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-04 06:11:27 +01:00
Unbit ed4425ee86 prepare for clojure/ring support 2013-03-04 06:11:07 +01:00
Unbit cb271e9a05 use exec/execfile instead of import in the build system 2013-03-04 06:10:28 +01:00
unbit 621cb99684 Merge pull request #170 from xrmx/coverity9
A few more coverity fixes
2013-03-03 13:46:35 -08:00
unbit 8600060d79 Merge pull request #169 from xrmx/coverity8
More issues reported by Coverity
2013-03-03 13:46:03 -08:00
Riccardo Magliocchetti 511a0aca0b plugins/http: remove self assignment
Also while at it cleanup the handling of the if branch around
the ifdefery.

Reported by Coverity as CID #970999.
2013-03-03 19:51:40 +01:00
Riccardo Magliocchetti 0b0a0ccce1 core/yaml: use size_t for buffer lenght in yaml_get_line
As the only user pass a size_t value and they have different
storage size.

Reported by Coverity as CID #970987.
2013-03-03 19:47:45 +01:00
Riccardo Magliocchetti e4e346772a core/ini: change ini_get_line size type
The only user of ini_get_line uses a size_t as size. Since off_t
and size_t have different storage size just switch ini_get_line
to size_t.

Reported by Coverity as CID #970984.
2013-03-03 19:44:30 +01:00
Riccardo Magliocchetti f102ef64da core/static: Add missing break in switch
Reported by Coverity as CID #970990.
2013-03-03 19:37:49 +01:00
Riccardo Magliocchetti 192c73d53d plugins/router_http: Fix copy and paste bug in uwsgi_routing_func_http
Don't redeclare ub_url since it is already there.

Reported by Coverity as CID #989243, #989252.
2013-03-03 19:29:50 +01:00
Riccardo Magliocchetti 07bd3f5df0 core/exception: avoid null pointer dereference in uwsgi_exception_run_handlers
If wsgi_req is NULL and uwsgi.reload_on_exception is True

Reported by Coverity as CID #989244.
2013-03-03 19:06:59 +01:00
Riccardo Magliocchetti eae00a5c77 core/subscription: fix wrong check in uwsgi_subscribe2
It looks like both s2_server and s2_key are mandatory in
uwsgi_send_subscription so fail if any of them is missing not both.

Reported by coverity as CID #989245.
2013-03-03 18:56:46 +01:00
Riccardo Magliocchetti 133dff6b76 core/alarm: fix memory leak in uwsgi_alarm_thread_loop
Rpoerted by Coverity as CID #989247.
2013-03-03 18:51:46 +01:00
Riccardo Magliocchetti cf634e11a9 core/exceptions: fix leak in uwsgi_exception_handler_thread_loop
Reported by Coverity as CID #989248.
2013-03-03 18:48:59 +01:00
Riccardo Magliocchetti 18dfd10b71 core/exceptions: fix memory leak in wsgi_exception_setup_handlers
Reported by Coverity as CID #989249.
2013-03-03 18:44:33 +01:00
Unbit 54b4189ab9 added uwsgi.java as the base for JVM request plugins 2013-03-03 18:43:22 +01:00
Riccardo Magliocchetti 7e58d78bfe proto/base: fix copy and paste bug in uwsgi_proto_base_cgi_prepare_headers
Reported by Coverity as CID #989253
2013-03-03 18:36:03 +01:00
Unbit 6497c93e3e completeted JVM multithread support 2013-03-03 15:38:01 +01:00
Unbit 27d637a9b2 report useful initialization message for the jvm 2013-03-03 14:40:09 +01:00
Unbit 296f9304ba Merge branch 'master' of github.com:unbit/uwsgi 2013-03-03 14:28:35 +01:00
Unbit a04420e5ef fixed jvm multiple args rpc 2013-03-03 14:28:09 +01:00
Unbit 2e4bc3dc6b allows mixing shared RPC with unshared 2013-03-03 13:56:38 +01:00
Unbit 773d853bb4 the RPC subsystem is no more dependent on cow 2013-03-03 13:28:06 +01:00
Unbit 92e06b1078 another series of improvements for the jvm 2013-03-03 12:36:35 +01:00
Unbit 1e6dd22fd8 prepare for new generation JVM plugin 2013-03-02 21:22:20 +01:00
unbit e5eba6be46 Merge pull request #168 from prymitive/ignore_nagios_requests
don't count ping requests
2013-03-02 11:24:11 -08:00
Łukasz Mierzwa 456729f6e2 don't count ping requests 2013-03-02 20:12:52 +01:00
Unbit 5f191b6e7f allows building the ruby plugin on heroku [3] 2013-03-02 16:16:54 +01:00
Unbit 7435235502 allows building the ruby plugin on heroku [2] 2013-03-02 16:14:32 +01:00
Unbit 764af285d3 allows building the ruby plugin on heroku 2013-03-02 16:09:59 +01:00
Unbit 3ed597368d completetd gemspec 2013-03-02 14:59:34 +01:00
Unbit 2119e06e38 allows building uwsgi as a gem 2013-03-02 14:34:09 +01:00
Unbit 0770fd8815 better error reporting on failed uploads 2013-03-02 13:59:22 +01:00
Unbit 6a94d1f91c fixed base64 decoding 2013-03-01 14:58:51 +01:00
Unbit f53c79cce7 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-01 14:44:35 +01:00
Unbit a2e4c6e272 added isexec route condition 2013-03-01 14:44:15 +01:00
unbit ce898614a0 Merge pull request #165 from prymitive/carbon_hostname
add option for dot replacement in carbon hostname
2013-03-01 05:37:13 -08:00
Łukasz Mierzwa 0676c5e6a8 add option for dot replacement in carbon hostname 2013-03-01 14:13:48 +01:00
Unbit 1469e68a33 added --route-if and --route-if-not 2013-03-01 12:39:39 +01:00
Unbit f4ad33976d added --if-plugin and --if-not-plugin 2013-03-01 11:20:38 +01:00
Unbit c8e12a6be3 better to avoid RegisterSignal in Mono 2013-03-01 11:10:21 +01:00
Unbit 48af1b28d4 Mono RegisterSignal implementation 2013-03-01 09:43:33 +01:00
Unbit b8c115a127 better dummy plugin 2013-03-01 08:26:55 +01:00
Unbit c009ab82f5 sadly Mono is not fork() friendly 2013-03-01 08:19:44 +01:00
Unbit b0c421ff4b fixed Mono domains handling 2013-02-28 20:20:04 +01:00
Unbit a39ac59757 refactored cgi plugin 2013-02-28 14:42:43 +01:00
Unbit d3792cba72 fixed php build without pcre 2013-02-28 14:16:04 +01:00
Unbit 4aa17c40fc allows building without ssl 2013-02-28 14:08:15 +01:00
Unbit 38b1f52723 fixed static-index and apply_fast routes 2013-02-28 12:14:59 +01:00
Unbit 30e50df5d4 better header in mono plugin 2013-02-28 00:20:19 +01:00
Roberto De Ioris 22d9a2b831 fixed OpenBSD support 2013-02-28 10:02:56 +01:00
Unbit 6bccb62799 added for-glob 2013-02-27 23:48:56 +01:00
Unbit acd1215524 added asp.net dynamic applications 2013-02-27 23:36:01 +01:00
Unbit 4381e816ae fixed cache_del2 2013-02-27 23:00:50 +01:00
Unbit 5760338445 multi-app mode for mono 2013-02-27 09:19:50 +01:00
Unbit e517bcea7c implemented Mono send file from handle 2013-02-27 08:30:14 +01:00
Unbit b6bdafa669 another round of Mono methods implementation 2013-02-27 06:52:53 +01:00
Unbit 5bd10a99fb report unavailable lock engine 2013-02-27 04:28:11 +01:00
Unbit b8dfd1be85 fixed pthread locking ifdef bug 2013-02-27 04:10:20 +01:00
Unbit 3c810e5ca8 updated carbon plugin 2013-02-27 01:15:56 +01:00
Unbit 61a1ca4ca4 initialize alarm and exception thread ONLY in the master 2013-02-26 19:29:29 +01:00
Unbit a71d9953a1 fixed sign bug 2013-02-26 17:46:47 +01:00
Unbit b20fbf5fe8 re-added uwsgi.route() 2013-02-26 06:38:34 +01:00
Unbit c73490fc80 prepare for --mono-key 2013-02-26 02:09:38 +01:00
Unbit da6b052bef added --mono-gc-freq 2013-02-26 01:34:45 +01:00
Unbit 08ea52164c fixed BSD support for Mono 2013-02-26 09:58:17 +01:00
Unbit 4de3d534a8 first public release of the new Mono/ASP.NET plugin 2013-02-26 01:09:09 +01:00
Unbit 7be55d71a8 improved mono build system 2013-02-25 23:14:43 +01:00
Unbit 6e24730025 fixed mime type with static-index 2013-02-25 23:10:29 +01:00
Unbit 513380d5c9 first version of the new mono plugin 2013-02-25 17:50:19 +01:00
Unbit 2f474b2af4 added support for ruby 2 2013-02-25 07:33:05 +01:00
Unbit a062ef2ac2 added rb tmier in the PSGI plugin 2013-02-24 09:45:39 +01:00
Unbit b82566268a completeted the CoroAE plugin, added timers to the PSGI plugin 2013-02-24 09:41:33 +01:00
Unbit 8d16ce28b9 avoid async queue full log storming 2013-02-24 07:55:46 +01:00
Unbit 2a9835649e added --tcp-nodelay 2013-02-23 15:50:34 +01:00
unbit 9912ab6afb Merge pull request #157 from xrmx/coverity7
More issues reported by Coverity
2013-02-23 06:25:04 -08:00
Unbit 94f18e3508 allows --attach-daemon without workers 2013-02-23 14:45:20 +01:00
Unbit 25c812e4aa fixed --http-socket url decoding 2013-02-23 13:46:31 +01:00
Unbit bddf8fe5c9 completed --perl-arg and --perl-args 2013-02-23 13:24:59 +01:00
Unbit fbabb14c61 another heroku check [5] 2013-02-23 13:03:48 +01:00
Unbit fd62e2ebb7 another heroku check [4] 2013-02-23 12:59:13 +01:00
Unbit e96c43970d another heroku check [3] 2013-02-23 12:54:00 +01:00
Unbit 99eda6d084 another heroku check [2] 2013-02-23 12:51:20 +01:00
Unbit 91b2cc7570 another heroku check 2013-02-23 12:47:06 +01:00
Unbit 0ff6277f28 prepare for perl args 2013-02-23 12:46:14 +01:00
Unbit dee99b6535 try to understand how heroku installed python [9] 2013-02-23 11:57:48 +01:00
Unbit 39260ebac0 try to understand how heroku installed python [8] 2013-02-23 11:53:47 +01:00
Unbit ac3ec1781e try to understand how heroku installed python [7] 2013-02-23 11:46:33 +01:00
Unbit e8925ac7b7 try to understand how heroku installed python [6] 2013-02-23 11:42:55 +01:00
Unbit 2877a5a05d try to understand how heroku installed python [5] 2013-02-23 11:40:50 +01:00
Unbit 9e3bfd261a try to understand how heroku installed python [5] 2013-02-23 11:38:34 +01:00
Unbit 636cd261e0 try to understand how heroku installed python [4] 2013-02-23 11:26:21 +01:00
Unbit 5fff6467a8 try to understand how heroku installed python [4] 2013-02-23 11:24:42 +01:00
Unbit 647c972ffe try to understand how heroku installed python [3] 2013-02-23 11:21:12 +01:00
Unbit ed9ac16c78 try to understand how heroku installed python [2] 2013-02-23 11:14:01 +01:00
Unbit 4f1b610459 try to understand how heroku installed python 2013-02-23 11:11:25 +01:00
Unbit a68b9b9fa6 attempt to better build on non-share-library configs 2013-02-23 11:08:41 +01:00
Unbit cd8e9f62b2 fixed GIL in new body reading system 2013-02-23 08:28:27 +01:00
Unbit f3ee043246 fixed a refcnt bug in psgi plugin 2013-02-23 08:26:57 +01:00
Riccardo Magliocchetti 949fdb5f86 core/cache: fix memory leak
Reported by Coverity as CID #981514.
2013-02-22 08:42:49 +01:00
Riccardo Magliocchetti d1c8a02151 core/io: check realloc() return value
Reported by Coverity as CID #981513.
2013-02-22 08:42:33 +01:00
Riccardo Magliocchetti 7c0f002239 core/emperor: fix memory leak on error path
Reported by Coverity as CID #971011.
2013-02-22 08:15:55 +01:00
Riccardo Magliocchetti 4d236b9b74 core/cache: close() mmapped cache store
The file will actually get closed when unmapped but we should
remove our reference to it.

Reported by Coverity scan as CID #971009.
2013-02-22 07:54:51 +01:00
Riccardo Magliocchetti 8d39eabf9d core/alarm: fix memory leak
Reported by Coverity scan as CID #971007.
2013-02-22 07:49:42 +01:00
unbit 591cec9a2c Merge pull request #156 from prymitive/fix_travis
Make travis fail is test request had errors
2013-02-20 05:46:31 -08:00
Łukasz Mierzwa 057d0bc250 add -f switch to curl options so that it will exit with non-zero return code if request fails 2013-02-20 13:38:38 +01:00
Unbit 252731544b it is too early to automatically build the router_memcached plugin 2013-02-20 11:42:33 +01:00
Unbit cdb901c091 another series of routing porting to the new api 2013-02-20 11:41:30 +01:00
Unbit 00c5a77554 new routing translator functions 2013-02-20 11:33:33 +01:00
Unbit 0e5f8acde5 goto label can be build from regexp 2013-02-20 07:57:46 +01:00
Unbit d2ae982329 improved routing label 2013-02-20 06:51:38 +01:00
Unbit 5307de6974 added uwsgi_buffer json escaper 2013-02-19 19:09:27 +01:00
Unbit dc2f9f405d added redirect-301 internal router instruction 2013-02-19 12:39:42 +01:00
Unbit e610682b31 added exception_log plugin 2013-02-19 12:34:43 +01:00
Unbit 34b6bc5378 preliminary support for exception handlers 2013-02-19 10:59:48 +01:00
Unbit 3d171f52b3 report client address and client port on corerouter errors 2013-02-19 09:01:41 +01:00
Unbit cfa4d2a3ad added ipv6 in corerouters 2013-02-19 08:19:47 +01:00
Unbit 12bf2cd3af fixed exception management in python mules and improved uwsgidecorators 2013-02-19 07:11:45 +01:00
Unbit 5089123e5a prepare for ipv6 support in corerouters 2013-02-18 18:21:57 +01:00
Unbit 4d53d3a16a added more logvars 2013-02-18 13:05:43 +01:00
Unbit 941dd70e3b added additional infos in the exceptions catcher 2013-02-17 16:24:36 +01:00
Unbit 609b5aeb0a porte the ruby/rack plugin to the new exception api 2013-02-17 16:18:12 +01:00
Unbit 8e6b810df8 fixed lua plugin 2013-02-17 14:27:32 +01:00
Unbit f31186a0f9 completetd first part of the new exceptions framework 2013-02-17 14:26:31 +01:00
Unbit b5a6da5448 refactored catch_exceptions 2013-02-17 11:22:09 +01:00
Unbit 0a9b5f05b0 prepare for advanced exception management 2013-02-17 10:12:49 +01:00
Unbit 7c8ae1737a fixed reports in xmpp alarm 2013-02-17 09:33:03 +01:00
Unbit 0e502172c9 added websockets tolerance 2013-02-16 13:31:01 +01:00
Unbit 0dd2a34e22 improved websockets support 2013-02-16 13:13:04 +01:00
Unbit f4b8f3e49d fixed a stupid bug in websocket ruby example 2013-02-16 10:23:04 +01:00
Unbit 9610ec72ab openindiana fixes 2013-02-15 22:24:35 +01:00
Unbit 32bf82552e added SCGI support 2013-02-15 19:08:28 +01:00
Unbit d15f1a9e36 prepare for SCGI support 2013-02-15 17:53:06 +01:00
Unbit 5e02bc3c84 UWSGI_ALARM is no more required 2013-02-15 12:26:45 +01:00
Unbit d397036e29 improved the alarm subsystem 2013-02-15 12:17:29 +01:00
Unbit c92fde03b9 various micro-optmizations in async, caching and static file serving 2013-02-15 08:11:33 +01:00
Unbit e1598af32f fiber requiers async mode 2013-02-14 20:53:13 +01:00
Unbit fbfab14224 improved fiber support 2013-02-14 20:49:26 +01:00
Unbit 8ff56a694a added --http-socket-modifier1 and --http-socket-modifier2 2013-02-14 20:10:56 +01:00
Unbit 639f26ff26 improved fastcgi support 2013-02-14 20:08:35 +01:00
Unbit 7d8a2968d5 first part of the fastcgi porting to the new api 2013-02-14 17:30:23 +01:00
Unbit f70c7c1e17 report worker id during gevent requests waiting 2013-02-14 12:13:33 +01:00
Unbit a89eb5d8cb report go version on startup 2013-02-14 12:11:49 +01:00
Unbit 4c9d30cc1b ported Go to the new api 2013-02-14 11:34:33 +01:00
Unbit fd7d4fc944 greatly improved chain reload in gevent mode 2013-02-14 10:12:24 +01:00
Unbit 7106301d86 report write_errors in core statistics 2013-02-14 09:27:04 +01:00
Unbit f046d47eb2 worker's busy value is now dinamically computed 2013-02-14 09:17:59 +01:00
Unbit 0b8b6346be ported router_uwsgi to the new api 2013-02-13 16:20:40 +01:00
Unbit 104c8a8b90 fixed routing + ugreen 2013-02-13 12:23:46 +01:00
Unbit f25ab0fdd2 more improvements on the non-blocking api 2013-02-13 12:07:07 +01:00
Unbit bb789d1ac0 fixed cheaper 2013-02-13 08:56:43 +01:00
Unbit e94315ca75 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-02-12 18:12:17 +01:00
unbit dd2e07122a Merge pull request #151 from xrmx/ipleak
core: don't leak ip in uwsgi_open_and_read()
2013-02-12 10:19:52 -08:00
Unbit 375d446bf0 mules and gateways are correctly managed 2013-02-12 19:18:54 +01:00
Unbit 46eafeaa58 graceful reload is working again 2013-02-12 18:47:53 +01:00
Unbit 79dccaac9c first big (really bug) master refactoring 2013-02-12 18:42:36 +01:00
Unbit cdf05dcef2 make older compilers happy 2013-02-12 18:12:04 +01:00
unbit 7d8aa98766 Merge pull request #155 from prymitive/carbon_requests_fix
fixed carbon requests metric
2013-02-11 22:14:24 -08:00
Łukasz Mierzwa 115470837e fixed carbon requests metric 2013-02-11 20:51:58 +01:00
Unbit c226feaeca added --touch-chain-reload 2013-02-11 20:10:43 +01:00
Unbit 669c14ac71 fixed subscription reference count 2013-02-11 20:03:52 +01:00
Unbit 1c5347ac90 added router_memcached plugin 2013-02-11 18:57:58 +01:00
Unbit 83ce30a51e added an heavy test for new caching system 2013-02-11 16:57:03 +01:00
Unbit f75a637ef6 implemented cache bitmap blocks unmarking 2013-02-11 14:50:55 +01:00
Unbit 48d749f11b prepare for unmarking function 2013-02-11 14:20:10 +01:00
unbit 3f041350a2 Update README 2013-02-11 14:11:36 +01:00
Unbit 39613d466a other improvements for bitmap based caching 2013-02-11 14:09:40 +01:00
Unbit 3c32980fe3 forget to reset SIGCHLD to SIG_DFL 2013-02-10 20:13:32 +01:00
Unbit a1fbed315f reset sigmask on startup 2013-02-10 19:51:36 +01:00
Unbit c0083c5801 first commit for bitmap based cache 2013-02-10 12:11:47 +01:00
Unbit f86404f03f fixed FreeBSD sendfile 2013-02-09 18:16:37 +01:00
unbit 602f0385cb Merge pull request #153 from prymitive/cheaper_zero_fix
additional validation of the --cheaper value at startup
2013-02-09 07:22:34 -08:00
Łukasz Mierzwa c32da58a7c additional validation of the --cheaper value at startup 2013-02-09 14:15:35 +01:00
Riccardo Magliocchetti d64a734292 core: don't leak ip in uwsgi_open_and_read()
While at it convert malloc() to uwsgi_malloc() to cleanup error
handling.

Reported by Coverity Scan as CID #971018.
2013-02-09 12:49:35 +01:00
Unbit 65c047dca1 added timebomb concept and improved gevent reloading 2013-02-09 07:55:12 +01:00
Unbit 73b1887287 fixed #34 2013-02-08 21:06:42 +01:00
Unbit 8d41a77baa coro and gevent improvements 2013-02-08 07:01:04 +01:00
Unbit 0692bf45da fixed a stupid bug in protocol parser 2013-02-07 21:09:22 +01:00
Unbit 9d5d439191 rpc subsystem is now async/greenthreads friendly 2013-02-07 18:31:44 +01:00
Unbit 9f15345183 prepare dor async-friendly rpc 2013-02-07 17:23:59 +01:00
Unbit 7d84413038 added a note on cheap string 2013-02-07 16:49:42 +01:00
Unbit ecd4b9bc36 added notes for the new caching plugin 2013-02-07 16:15:26 +01:00
Unbit 47d66ab368 ported cache store system to the new api 2013-02-07 16:01:15 +01:00
Unbit 54227db3e4 cache syncing is working again 2013-02-07 15:42:14 +01:00
Unbit aecd9a7703 ported udp cache server to the new api 2013-02-07 15:33:01 +01:00
Unbit dd0551bf68 ported the cache sync client system to the new api 2013-02-07 15:21:32 +01:00
Unbit d649853a51 ported cache udp nodes to the new api 2013-02-07 15:12:58 +01:00
Unbit 05ad7bf07e fixed suspend when harakiri is in place 2013-02-07 14:10:13 +01:00
Unbit f29ac2117f refactored mod_proxy_uwsgi 2013-02-07 13:35:43 +01:00
Unbit 91be1f8929 really apply PATH_INFO fix in mod_proxy_uwsgi 2013-02-07 11:43:59 +01:00
Unbit 1e9c8c47bb add copyright notes in mod_proxy_uwsgi and correctly decode PATH_INFO/SCRIPT_NAME 2013-02-07 10:05:15 +01:00
Unbit 63c8ce3bf8 updated mod_uwsgi copyright notes 2013-02-07 09:43:01 +01:00
Unbit d13b58869d fiber fixes 2013-02-04 11:23:47 +01:00
Unbit 49740e99fb Merge branch 'master' of github.com:unbit/uwsgi 2013-02-04 11:02:43 +01:00
unbit 09b136ed2c Merge pull request #149 from prymitive/alarm_curl
ifdefed stuff only available in newer curl releases
2013-02-05 03:30:59 -08:00
Łukasz Mierzwa 5be46f0cb3 ifdefed stuff only available in newer curl releases 2013-02-05 11:50:06 +01:00
Unbit e5094e7efa ruby/rack websockets support 2013-02-04 11:02:24 +01:00
Unbit 60580a0195 prepare for ruby websockets + fibers support 2013-02-04 08:55:19 +01:00
Unbit 0a73039cfc improved ugreen support and cgi integration 2013-02-04 04:56:13 +01:00
Unbit 94aed13978 simplified --http-websockets 2013-02-03 20:52:42 +01:00
Unbit 9679645354 Coro::AnyEvent + websockets is working 2013-02-03 20:38:30 +01:00
Unbit 0c1a25b8a6 coroae fixes 2013-02-03 17:03:59 +01:00
Unbit 4a3c1e537b zmq need a bit more work... 2013-02-03 15:58:29 +01:00
Unbit c355c93f12 ported ping plugin to the new api 2013-02-03 14:17:39 +01:00
Unbit 5552e87087 generalized offload subsystem 2013-02-03 14:14:00 +01:00
Roberta Giordano 67544158d9 osx fixes 2013-02-04 13:08:16 +01:00
Unbit f117f404fc fixed a regression with sendfile() 2013-02-03 10:57:13 +01:00
Unbit d4130dbc4b first round of protocol parsers optimizations
preliminary api for language-independent body read

another step

completed body read language independent implementation

ported gevent to the new read/write api

ported websockets to the new read/write api

removed channels subsystem

removed channels subsystem

ported lua to the new read/write api

fixed post-buffering

readline is still broken

improved request body readline

very difficult test for readline()/read() combo passed

other improvements in postbuffering/read/readline

ported --http-socket to the new api

added X-Forwarded-SSL management

removed old api

more refactoring

ported the RACK plugin to the new api

ported psgi plugin to the new api

defintely removed clustering

simpified ifdel hell

simpified ifdef hell

removed useless configuration options
2013-02-03 10:38:13 +01:00
Unbit e50a7c518f improved alarm_xmpp plugin 2013-01-31 09:56:20 +01:00
Unbit 874b994e66 added --static-gzip-* options 2013-01-31 07:49:19 +01:00
Unbit cc93687476 better support for robust mutexes 2013-01-30 18:31:15 +01:00
Unbit e354f3b37a fixed PTHREAD_PRIO_INHERIT 2013-01-30 18:07:24 +01:00
Unbit d204e75c1c added --thunder-lock 2013-01-30 17:59:00 +01:00
Unbit 8c0e77b737 fixed SERVER_PORT in routers when shared sockets are in place 2013-01-30 16:31:11 +01:00
Unbit 70f12c4407 fixed backlog reporting on 32bit 2013-01-30 14:06:09 +01:00
Unbit ac78830a90 offloading by default, if available 2013-01-30 13:22:02 +01:00
Unbit 534f78acb3 improved sendfile management 2013-01-30 12:51:13 +01:00
Unbit 443c2c5a29 better route/sendfile/offload logging 2013-01-30 12:24:38 +01:00
Unbit feca5abc53 announce only spdy3 2013-01-30 08:30:33 +01:00
unbit c643c3069c Merge pull request #143 from xrmx/coverity6
Fix some leaks reported by Coverity scan
2013-01-30 10:57:36 -08:00
unbit 1cffe0dfe6 Merge pull request #142 from prymitive/router_delta
add last_request attribute to subscription node, it will hold the number...
2013-01-30 09:45:07 -08:00
Łukasz Mierzwa 3761709ec4 add last_request attribute to subscription node, it will hold the number of requests since last subscription ping
use node->last_requests instead of absolute request counter in (w)lrc
2013-01-30 18:32:06 +01:00
Riccardo Magliocchetti 956f54033c plugins/http: fixup some leaks in spdy
Reported by Coverity as CID #971245, #971246.
2013-01-30 18:05:42 +01:00
Riccardo Magliocchetti 7afd4e39eb proto/zeromq: Don't leak ub on write error in uwsgi_proto_zeromq_writev_header
Reported by Coverity as CID #971247.
2013-01-30 17:43:45 +01:00
Unbit 76866a05ba fixed realloc() usare in core/io.c as spotted by cppcheck [2] 2013-01-29 16:31:48 +01:00
Unbit 74eeee48ae fixed realloc() usare in core/io.c as spotted by cppcheck 2013-01-29 16:28:45 +01:00
Unbit 3babcbe2bb added --route-referer 2013-01-29 12:07:56 +01:00
Unbit 1a50463ed9 --sslrouter and --sslrouter2 to be more aligned with --https 2013-01-29 10:57:30 +01:00
Unbit a88244a700 fixed --sslrouter-sni 2013-01-29 10:51:04 +01:00
Unbit 7cf4cc788c added --sni-dir 2013-01-29 09:44:20 +01:00
Unbit 990e7241e6 added the sslrouter and various corerouters micro-optimizations 2013-01-29 09:08:41 +01:00
unbit 40d69f90d9 Merge pull request #141 from xrmx/coverity5
Check return value of library call Coverity issues
2013-01-28 13:52:56 -08:00
Unbit 194f4897e3 new rbtree implementation 2013-01-28 22:22:29 +01:00
Riccardo Magliocchetti d56e35651b core/cluster: log sendto() error
Reported by Coverity as CID #970958.
2013-01-28 19:41:41 +01:00
Riccardo Magliocchetti 58314c2800 core: log when sendmsg fails
Reported by Coverity as CID #970962, #970963.
2013-01-28 18:41:08 +01:00
Riccardo Magliocchetti 0af894df06 core: log when fcntl() fails
Reported by Coverity as CID #970967, #970966.
2013-01-28 18:37:28 +01:00
Riccardo Magliocchetti 9bfcec2999 lib/linux_ns: check mkdir() return value
Fail earlier if we can't create the dirs we need.
Reported by Coverity as CID #970969.
2013-01-28 18:31:15 +01:00
Unbit 65c513bec2 when the emperor has a master, allows it to respawn the dead emperor 2013-01-28 16:35:12 +01:00
Unbit ec3a95dafb fixed request log routing 2013-01-28 10:59:26 +01:00
Unbit 8386d7829d fixed fastrouter read body hook 2013-01-28 10:45:27 +01:00
Unbit bb9c3e0d6c logformat can now create apache compatible logs 2013-01-28 09:42:11 +01:00
Unbit bc5b71a5ec Merge branch 'master' of https://github.com/unbit/uwsgi 2013-01-28 09:34:22 +01:00
Unbit 2cdf1b7265 fill empty logvars 2013-01-28 09:34:09 +01:00
unbit 162c861e74 Merge pull request #137 from prymitive/reload_mercy_for_cheaped
reload/cheap mercy for invidual workers
2013-01-28 00:19:55 -08:00
unbit edb9c5f982 Merge pull request #138 from prymitive/php_new_cache
fixed php plugin to use new cache api
2013-01-28 00:01:22 -08:00
Łukasz Mierzwa c88be57dd9 refactored php plugin to use new cache api 2013-01-28 00:44:41 +01:00
Łukasz Mierzwa c1682f4ee4 reload/cheap mercy for invidual workers 2013-01-27 23:19:50 +01:00
Unbit 799ac9310f after years we can finally differentiate between stderr and request logging 2013-01-27 17:59:23 +01:00
unbit 2540e739c7 Merge pull request #136 from xrmx/coverity4
More issues reported by Coverity
2013-01-27 04:54:54 -08:00
Riccardo Magliocchetti 43ee6a305f plugin/python: fix some leaks on error paths in symimporter
Reported by Coverity as CID #971059, #971060.
2013-01-27 12:36:54 +01:00
Riccardo Magliocchetti 0cb2e6852b plugins/python: fix tracebaker resource leaks on import error
Reported by Coverity as CID #971061, #971062, #971063.
2013-01-27 12:19:45 +01:00
Riccardo Magliocchetti a559e9ea63 plugins/python: fix a couple of memory leaks
Reported by Coverity as CID #971065, #971066.
2013-01-27 12:10:19 +01:00
Riccardo Magliocchetti 89dfa7976a core/socket: fix a couple of memory leaks
Reported by Coverity as CID #971053, #971054.
2013-01-27 11:54:48 +01:00
Unbit 56a8d44cb0 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-01-27 11:37:41 +01:00
Unbit 7fc644d1a8 fixed uwsgi_cache_create definition 2013-01-27 11:37:23 +01:00
Riccardo Magliocchetti 74d6bac54b plugins/python: check return value of PyType_Ready in init_uwsgi_embedded_module
Reported by Coverity as CID #970972.
2013-01-27 10:33:17 +01:00
Riccardo Magliocchetti 5647aff995 plugins/python: remove double assignment to same variable
Which coverity reports as undefined behaviour in CID #970978.
2013-01-27 10:22:31 +01:00
Riccardo Magliocchetti cf67363164 core: prefer strncpy over strcpy in emperor
Coverity reports a possible buffer overrun which is not possible
at the momento because the only caller of uwsgi_emperor_blacklist_add
use another fixed buffer of the same size as te one we are writing
to. Still better safe than sorry. Reported as CID #971078.
2013-01-27 10:17:01 +01:00
Roberta Giordano 1bdec68fb7 added uagent to logvars 2013-01-27 09:34:55 +01:00
Unbit 5698955384 added ltime logformat 2013-01-27 08:59:05 +01:00
unbit 732466e4e4 Merge pull request #133 from xrmx/coverity3
Fix "argument cannot be negative" errors reported by Coverity
2013-01-26 22:21:44 -08:00
unbit 23165a1587 Merge pull request #132 from xrmx/coverity2a
More issues reported by Coverity
2013-01-26 22:20:15 -08:00
unbit d9a8e071e2 Merge pull request #131 from xrmx/coverity
Fix some issues spotted by coverity scan
2013-01-26 22:18:03 -08:00
Riccardo Magliocchetti e106a6ef61 plugins/python: check uwsgi_connect return code in uwsgi_python_harakiri
Reported by Coverity as CID #970996.
2013-01-26 21:23:17 +01:00
Riccardo Magliocchetti 297bd429a9 core: check return of uwsgi_connect in uwsgi_opt_connect_and_read
Reported by Coverity as CID #970995.
2013-01-26 21:18:55 +01:00
Riccardo Magliocchetti 838bdd27a6 core: check return of getgroups()
When we pass 0 as size to getgroups() the number of additional
groups is return. If it returns error or 0 don't even try to
poke for additional groups.

Reported by Coverity as CID #970944.
2013-01-26 21:10:33 +01:00
Riccardo Magliocchetti f50e179100 core: don't call dup2 on negative fd after open() error
Also call close() only if open was succesful.
Reported by Coverity as CID #970991.
2013-01-26 21:00:11 +01:00
Riccardo Magliocchetti c6ddaf6b8d core: add missing legion mutex unlock on error path
Reported by Coverity as CID #970988.
2013-01-26 19:45:46 +01:00
Riccardo Magliocchetti cbc06f92d0 core: add missing unlock in wsgi_req_accept
Reported by Coverity as CID #970989.
2013-01-26 19:29:46 +01:00
Riccardo Magliocchetti 386fac2421 core: fix copy & paste bug in uwsgi_manage_command_cron
It looks like tm_hour is used where tm_mon was intended.
Reported by Coverity as CID #970975.
2013-01-26 19:18:15 +01:00
Riccardo Magliocchetti 3138d0b6c3 plugins/carbon: add missing call to va_end()
Reported by Coverity as CID #971091.
2013-01-26 19:14:52 +01:00
Riccardo Magliocchetti 135a5a505c lib/linux_ns.c: fix some possible null pointer dereferences
In case we cannot open /self/proc/mounts or it is malformed.
Spotted by Coverity, CID #971002, #971003.
2013-01-26 19:06:49 +01:00
Riccardo Magliocchetti 1b47a8932e plugins/cache: fix resource leak
Reported by Coverity, CID #971053.
2013-01-26 18:44:08 +01:00
Riccardo Magliocchetti 01e4d07fb8 plugins/corerouter: use correct goto label
After cwd has been allocated we should exit through end0.
Spotted by Coverity, CID #971054.
2013-01-26 18:39:37 +01:00
Riccardo Magliocchetti ec1bfdeb2a plugins/router_http: fix leak if connection to host fails
Fix Coverity CID #971069.
2013-01-26 18:29:36 +01:00
Riccardo Magliocchetti ac3d617037 core: remove spurious call to dlsym
Fix use after free reported by Coverity, CID #971090
2013-01-26 18:13:11 +01:00
Roberta Giordano 253805daa6 added rsize,hsize and cl logvars, added logvar: routing instruction 2013-01-26 17:25:18 +01:00
unbit 63e4964808 Merge pull request #130 from prymitive/busyness_ifdef_fix
better backlog ifdef in cheaper_busyness
2013-01-26 05:41:00 -08:00
Łukasz Mierzwa 57962d2e6e better backlog ifdef in cheaper_busyness 2013-01-26 14:08:29 +01:00
unbit f81ea8e898 Merge pull request #109 from prymitive/busyness_backlog
spawn new workers if backlog is > 0 for some time
2013-01-26 05:04:24 -08:00
Łukasz Mierzwa 821af5d763 spawn new workers if backlog is > 0 for some time 2013-01-26 13:59:42 +01:00
unbit 2e923aaf9e Merge pull request #128 from prymitive/rsyslog_fixes
split messages > 995 bytes into chunks in rsyslog plugin
2013-01-26 03:46:12 -08:00
Łukasz Mierzwa 15b12983e1 * add buf to uwsgi_logger struct and use it when logger needs buffering (rsyslog + graylog2)
* allow to split big syslog messages into chunks
* allow to set maximum syslog packet size (some syslog deamons support that)
2013-01-26 12:37:23 +01:00
unbit 15f0f8d294 Merge pull request #125 from prymitive/worker_lifetime
new options to control worker minimum and maximum lifetime
2013-01-26 03:29:34 -08:00
unbit c6658fca72 Merge pull request #129 from prymitive/named_cache_stats
don't free lock name of a named cache
2013-01-26 03:22:13 -08:00
Łukasz Mierzwa 5bbc7ee673 don't free lock name of a named cache 2013-01-26 11:56:16 +01:00
Unbit 37927c6f5d ported sweepers to the new api and added more statistics 2013-01-26 07:43:12 +01:00
Unbit 1a6ee9a775 added --emperor-procname 2013-01-26 04:11:07 +01:00
Unbit d42649d80b implemented SPDYv3 WINDOW UPDATE 2013-01-25 18:58:11 +01:00
Unbit 2acd338429 SPDY improvements 2013-01-25 17:38:42 +01:00
Unbit 7adcb19d1a fixed --http-to-https 2013-01-25 12:51:26 +01:00
Unbit a2f776b487 fixed rawrouter allocation bug 2013-01-25 11:00:29 +01:00
Unbit 941ae2b5e3 better non-blocking support for protocols 2013-01-25 10:38:10 +01:00
Unbit e88d4bbb79 improved expect-continue management 2013-01-25 09:41:39 +01:00
Unbit db352999b8 --check-cache takes an optional parameter (the cache name) 2013-01-24 20:43:15 +01:00
Unbit 744fed60b9 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-01-24 20:41:00 +01:00
Unbit df85a8e6a9 added uwsgi_cache_safe_get2() commodity function 2013-01-24 20:40:43 +01:00
unbit 7ba7fd55d0 Merge pull request #126 from prymitive/master_init_fix
One more fix is needed for master branch
2013-01-24 11:32:47 -08:00
Łukasz Mierzwa 6fd2176b3e fixed new cache typo 2013-01-24 20:25:11 +01:00
Unbit 271ac33193 fixed a regression caused by new caching system 2013-01-24 20:20:14 +01:00
Unbit 8d33491211 added magix gzipper in http corerouter and added sessions counter in corerouters 2013-01-24 19:31:50 +01:00
Unbit 13a42599ea corerouters --*-use-cache option can take an optional cache name 2013-01-24 10:24:46 +01:00
Unbit cb8878dc81 --ssl-sessions-use-cache can take the cache name as parameter 2013-01-24 10:03:07 +01:00
Unbit 5e561c0d1e --cache2 is ready 2013-01-24 09:02:53 +01:00
Unbit fbfe58948b prepare for the --cache2 option 2013-01-23 20:38:55 +01:00
Unbit e839a9eb89 ported psgi and rack plugin to the new caching api 2013-01-23 20:32:52 +01:00
Unbit b90779aecf improved the caching subsystem to allows dynamic key 2013-01-23 20:16:49 +01:00
Unbit 2447f819cb first commit of the new caching infrastructure 2013-01-23 16:15:43 +01:00
Roberto De Ioris 6f956c6965 fixed gzip encoding 2013-01-22 18:28:40 +01:00
Roberto De Ioris 729fdd22c4 preliminary support for uWSGI-Encoding magic header 2013-01-21 19:24:27 +01:00
Łukasz Mierzwa 7b59668386 new options to control worker minimum and maximum lifetime 2013-01-21 16:44:43 +01:00
Roberto De Ioris 1e5739f8ea added core/strings.c 2013-01-21 16:41:33 +01:00
Roberto De Ioris 3ef7e9aee3 added --rem-header support 2013-01-21 16:13:20 +01:00
Roberto De Ioris 4854b3cbcf fixed rack plugin 2013-01-21 14:55:35 +01:00
Roberto De Ioris 5273dbba90 maintain after_hook test in welcome.py 2013-01-21 14:53:40 +01:00
Roberto De Ioris b59f3b254f fixed buf in python uwsgi.workers() 2013-01-21 14:50:27 +01:00
Roberto De Ioris dda6bb2a5f dump request vars in stats (if possibile and safe) 2013-01-21 14:24:42 +01:00
Roberto De Ioris 0daff2cfe2 multithread corner case fixes 2013-01-21 12:12:36 +01:00
Roberto De Ioris 61ee03a99e improved http keepalive 2013-01-21 10:15:26 +01:00
Roberto De Ioris 06b6704be3 tempoarily disable fastcgi support to continue building with clang 2013-01-21 09:07:15 +01:00
Roberto De Ioris ab2a8c90cd fixed http router 2013-01-20 20:51:48 +01:00
unbit 21ada10805 Merge pull request #123 from prymitive/busyness_backlog_fixes
Better backlog messages in cheaper_busyness
2013-01-20 10:22:51 -08:00
Łukasz Mierzwa 3d8467506a better log messages when backlog is over limit but we already started max number of workers 2013-01-20 18:52:27 +01:00
Roberto De Ioris 8f996bb68d fixed go plugin 2013-01-20 18:04:06 +01:00
Roberto De Ioris 9f55579b87 added support for automatic status codes 2013-01-20 17:29:03 +01:00
Roberto De Ioris 215e514385 tiny fixes in the psgi plugin 2013-01-20 17:06:29 +01:00
Roberto De Ioris 77bd73d597 psgi plugin improvements 2013-01-20 16:25:39 +01:00
Roberto De Ioris 3642198acd added gevent.h 2013-01-20 16:01:39 +01:00
Roberto De Ioris 810a1463d5 started porting the gevent plugin to the new api 2013-01-20 16:00:11 +01:00
Roberto De Ioris d3dfdbb0ba refactoring [2] 2013-01-20 15:34:24 +01:00
Roberto De Ioris f71f76c6e6 refactoring 2013-01-20 15:20:35 +01:00
Roberto De Ioris 287a8c8a24 improved notfound plugin 2013-01-20 14:46:39 +01:00
Roberto De Ioris 70d9dab5ef avoid wasting resources on failed writes... 2013-01-20 14:45:40 +01:00
Roberto De Ioris c9987aa721 ported http-socket to the new api 2013-01-20 14:35:06 +01:00
Roberto De Ioris 874e8b5621 completed port of the python plugin to the new writing api 2013-01-20 14:17:54 +01:00
Roberto De Ioris 4b3b3f9200 need to fix go support 2013-01-20 13:14:34 +01:00
Roberto De Ioris 994209ffb0 another bunch of portings 2013-01-20 13:08:10 +01:00
Roberto De Ioris 4cd5643c8f ported lua to the new api 2013-01-20 13:01:23 +01:00
Roberto De Ioris b7e2eaad0f ported the example plugin 2013-01-20 12:52:58 +01:00
Roberto De Ioris 71a5e8b768 ported php to the new api 2013-01-20 12:46:52 +01:00
Roberto De Ioris 6044af9e7a ported the cgi plugin to the new write api 2013-01-20 12:36:17 +01:00
Roberto De Ioris 4e2178ffab another WSGI optimization 2013-01-20 11:41:43 +01:00
Roberto De Ioris 37e153d5de need to find a way to better manage write errors... 2013-01-20 10:32:02 +01:00
Roberto De Ioris e1316153be another series of porting 2013-01-19 21:42:05 +01:00
Roberto De Ioris 876f775698 solid sendfile for the new api 2013-01-19 20:59:53 +01:00
Roberto De Ioris 2bd714c610 new writer api 2013-01-19 19:06:06 +01:00
Roberto De Ioris 1b0c5bea6c another destructive commit 2013-01-19 16:53:31 +01:00
Roberto De Ioris 1f8cadb15d psgi plugin was badly broken in async mode when threads are enabled 2013-01-19 13:23:12 +01:00
unbit 83d24bee99 Merge pull request #121 from prymitive/carbon_root
[carbon] allow setting empty carbon root node
2013-01-18 14:15:00 -08:00
Roberto De Ioris 297111f2b6 non-working prototype for Coro::AnyEvent loop engine 2013-01-18 21:50:21 +01:00
Łukasz Mierzwa 0f354cbf2c allow setting empty carbon root node 2013-01-18 21:39:14 +01:00
unbit 1303efb2a4 Merge pull request #120 from prymitive/carbon_fixes
push memory metrics only if --memory-report is enabled
2013-01-18 07:45:51 -08:00
Łukasz Mierzwa 234b09b17c push memory metrics only if --memory-report is enabled & fixed total harakiri counter to include cheaper workers 2013-01-18 16:38:56 +01:00
Roberto De Ioris fe4f621d79 added --http-auto-chunked 2013-01-18 14:51:16 +01:00
Roberto De Ioris 3f83e91fb2 added uwsgi_buffer_insert() 2013-01-18 09:57:19 +01:00
Roberto De Ioris 9aebb6c564 working --http-keepalive implementation 2013-01-17 17:13:13 +01:00
Roberto De Ioris c7da6b2d45 removed a useless log 2013-01-16 19:34:14 +01:00
Roberto De Ioris bbf35be595 fixed mule management 2013-01-16 16:58:30 +01:00
Roberto De Ioris 419875e6cf fixed unix signal usage in mules and spooler 2013-01-16 16:47:46 +01:00
Roberto De Ioris aa36a2ce5f Merge branch 'master' of https://github.com/unbit/uwsgi 2013-01-16 16:25:27 +01:00
Roberto De Ioris 4c669b17ef fixed http-socket body storage leak 2013-01-16 16:25:06 +01:00
unbit abb4c9b6da Merge pull request #119 from prymitive/carbon_namespace
allow setting root node in carbon stats
2013-01-16 05:54:32 -08:00
Roberto De Ioris fe244e16d9 Merge branch 'master' of https://github.com/unbit/uwsgi 2013-01-16 14:47:32 +01:00
Roberto De Ioris 499202e84f added uwsgi::postfork and uwsgi::atexit 2013-01-16 14:47:14 +01:00
Łukasz Mierzwa e33b56890f allow setting root node in carbon stats 2013-01-16 14:37:24 +01:00
unbit 63275e9ec7 Merge pull request #118 from prymitive/carbon_busyness_fixes
carbon - detect stuck workers
2013-01-16 05:24:31 -08:00
Łukasz Mierzwa c182f30e8d carbon - detect cases were no request is completed but worker was busy and set busyness to 100% 2013-01-16 14:13:11 +01:00
unbit e365211cd0 Merge pull request #117 from prymitive/busyness_fixes
cheaper busyness -  detecting stuck workers
2013-01-16 03:28:59 -08:00
unbit 4838baf01a Merge pull request #116 from nwalker/master
another size_t fix
2013-01-16 03:26:16 -08:00
Łukasz Mierzwa 7db8636da5 cheaper busyness - detect cases were no request is completed but worker was busy 2013-01-16 12:09:40 +01:00
Alex Bubnoff 74d84be587 yet another size_t fix 2013-01-16 15:45:57 +07:00
Roberto De Ioris 8dd74ced5d Merge branch 'master' of github.com:unbit/uwsgi 2013-01-14 16:41:07 +01:00
Roberto De Ioris 9cb97dd62d php-fallback 2013-01-14 16:40:43 +01:00
Roberto De Ioris cd91830d65 fixed websockets test 2013-01-14 15:17:21 +01:00
unbit 1cefceba10 Merge pull request #113 from prymitive/core_logs
fixed init log
2013-01-13 06:32:41 -08:00
Łukasz Mierzwa afc2e7dbe2 fixed init log 2013-01-13 15:21:43 +01:00
unbit b1a9d2d497 Update tests/websockets.py 2013-01-13 13:11:37 +01:00
Roberto De Ioris ee129f02bc support for websockets over https 2013-01-13 12:46:03 +01:00
Roberto De Ioris 7ac4282047 synchrnous websockets + channels implementation 2013-01-13 10:53:11 +01:00
Roberto De Ioris 50fe00d142 gevent-friendly channel hook 2013-01-13 09:32:58 +01:00
Roberto De Ioris 6dab462296 first workign channel commit 2013-01-13 09:06:28 +01:00
Roberto De Ioris d614eabeac fixed websocket on older compilers 2013-01-13 05:24:42 +01:00
Roberto De Ioris 7da87bdf9d added --load-file-in-cache 2013-01-12 20:00:43 +01:00
Roberto De Ioris cf682773fb various int->size_t fixes 2013-01-12 19:50:49 +01:00
Roberto De Ioris 78a05ef9e8 use size_t instead of int in io functions 2013-01-12 19:22:51 +01:00
Roberto De Ioris 17d9b5f58d improved cache router added send and send-crnl route instruction 2013-01-12 19:02:40 +01:00
Roberto De Ioris 385458b291 fixed gevent leak 2013-01-12 17:17:30 +01:00
Roberta Giordano 7a80ee49be osx fixes 2013-01-11 14:44:21 +01:00
Roberto De Ioris e31d0a8693 websocket gevent hooks 2013-01-11 14:40:23 +01:00
Roberto De Ioris 9d43d6c9d4 removed some debug info 2013-01-11 11:57:42 +01:00
Roberto De Ioris b03008d1a6 spdy ping/pong 2013-01-11 11:46:32 +01:00
Roberto De Ioris 94c29a396a added new files 2013-01-11 10:22:12 +01:00
Roberto De Ioris bba8e503c1 fixed spdy/http memory cooperation 2013-01-11 08:04:46 +01:00
Roberto De Ioris 9c2e9e42f9 ported https to the new api 2013-01-11 07:40:21 +01:00
Roberto De Ioris 82d5e0ead8 Merge branch 'master' of github.com:unbit/uwsgi 2013-01-10 22:15:38 +01:00
Roberto De Ioris 3d9a20953e allows building on debian etch 4 2013-01-10 22:11:51 +01:00
Roberto De Ioris 1004ad0edc added 'signal' internal router instruction 2013-01-10 19:43:22 +01:00
Roberto De Ioris 688a227886 preliminary Websockets and SPDY support, highly optimized corerouters 2013-01-10 19:28:21 +01:00
unbit 7541195a5f Merge pull request #111 from xtfxme/defect/sec-sub
defect/sec-sub: Incorrect offset + length used for pkt encryption
2013-01-07 04:36:39 -08:00
C Anthony Risinger db24fa7bd4 defect/sec-sub: Incorrect offset + length used for pkt encryption
Off-by-four bug included the (uninitialized) uwsgi protocol header as part of
the signed packet during encryption, but *not* decryption, effectively preventing successful subscriptions; omit the header from both sides.
2013-01-07 06:24:39 -06:00
Roberto De Ioris 339c49f560 fixed remote_user in spnego plugin 2013-01-05 18:01:32 +01:00
Roberto De Ioris 8dd943542e added a route rule for remote_user 2013-01-05 17:49:27 +01:00
Roberto De Ioris 0f156fc25e fixed spnego on auth errors 2013-01-05 17:45:16 +01:00
Roberto De Ioris 8f7e65c467 added spnego/kerberos router 2013-01-05 17:21:21 +01:00
Roberto De Ioris 08b2437146 added base64 functions 2013-01-05 17:19:23 +01:00
Roberto De Ioris 912098c4c1 added --legion-skew-tolerance 2013-01-05 12:14:41 +01:00
Roberto De Ioris 3d3b21afc9 improved break routing instruction and first round of uwsgi protocol parsing optimizations 2013-01-05 11:46:11 +01:00
Roberto De Ioris 3cd7a1163d added addheader routing instruction 2013-01-05 09:35:47 +01:00
Roberto De Ioris e335c611a3 added addvar routing instruction 2013-01-05 09:06:29 +01:00
Roberto De Ioris 3409ce86e7 added --perl-version 2013-01-05 08:38:07 +01:00
Roberto De Ioris 02a9d37c32 added --python-version 2013-01-05 08:33:00 +01:00
Roberto De Ioris 121124c3cd implemented advanced login in internal routing subsystem 2013-01-04 21:15:26 +01:00
Roberto De Ioris c6440ffa2d fixed broodlord mode stats 2013-01-04 20:41:00 +01:00
Roberto De Ioris 6bab2b2318 refactored routing 2013-01-04 20:25:31 +01:00
Roberto De Ioris 7ae7b3d715 added 'static' internal router 2013-01-03 10:38:13 +01:00
Roberto De Ioris 2a2c650bec improved routing subsystem with the GOON return code 2013-01-03 10:13:38 +01:00
Roberto De Ioris ed69d78a9b export HTTP_AUTHORIZARION in mod_proxy_uwsgi 2013-01-02 17:38:03 +01:00
Roberto De Ioris 50c2fde29e fixed cheaper-initial startup message 2013-01-02 16:41:48 +01:00
unbit 96b35a3fff Merge pull request #98 from nwalker/master
Broken pyerl build
2013-01-02 00:17:47 -08:00
unbit 09a5ffeffb Merge pull request #107 from kunkku/lua-lock
Lua bindings for lock/unlock functions
2013-01-02 00:15:03 -08:00
Kaarle Ritvanen e4642e5e56 Lua bindings for lock/unlock functions 2013-01-01 15:11:46 +02:00
Roberto De Ioris 8236233489 legion subsystem does not require workers 2013-01-01 11:46:19 +01:00
Roberto De Ioris 5bfad8a1c5 added check key to the subscribe2 new generation subscriber 2013-01-01 09:56:19 +01:00
Roberto De Ioris c0dcbb7bac refactored subscriptions 2012-12-31 13:00:05 +01:00
Roberto De Ioris 808216fbd2 rewritten subscription packet generation uwsgi uwsgi_buffer struct 2012-12-31 11:40:06 +01:00
Roberto De Ioris f9a91fad63 added --static-cache-paths <seconds> 2012-12-31 11:14:53 +01:00
Roberto De Ioris 7956bebb25 added --static-safe 2012-12-31 10:51:17 +01:00
Roberto De Ioris 30633b2c9f refactored static support 2012-12-31 10:33:11 +01:00
Roberto De Ioris c713c1013c exported uwsgi_legion_i_am_the_lord() api function 2012-12-31 10:16:38 +01:00
Roberto De Ioris becdd27467 fixed locing in legion stats 2012-12-31 09:59:59 +01:00
Roberto De Ioris 2216aafcf1 take checksum in account to recognize quorum changes 2012-12-31 09:23:04 +01:00
unbit 7b3859b484 Update core/master_utils.c 2012-12-30 19:08:05 +01:00
unbit b1ab162bd2 Merge pull request #104 from prymitive/legion_stats
basic legion stats
2012-12-30 10:05:19 -08:00
unbit a0dbcee7d5 Merge pull request #103 from prymitive/legion_quorum_warning
[legion] periodic warnings when no quorum is reached
2012-12-30 10:01:59 -08:00
unbit 5312a8a0f6 Merge pull request #102 from prymitive/travis_update
fixed travis tests after latests cleanups
2012-12-30 10:00:55 -08:00
Łukasz Mierzwa 9e9b28a9cd fixed travis tests after latests cleanups 2012-12-30 15:51:39 +01:00
Łukasz Mierzwa 572298e63d periodic warnings when no quorum is reached 2012-12-30 15:48:47 +01:00
Łukasz Mierzwa 32a47c91b7 basic legion stats 2012-12-30 15:47:43 +01:00
Roberto De Ioris 556905048e legions now supports nodes with the same valor, uuid will be the diff 2012-12-30 12:46:09 +01:00
Roberto De Ioris 219d77fc17 fixed uuid compare 2012-12-30 12:41:21 +01:00
Roberto De Ioris e34371a974 debug quorum 2012-12-30 12:29:17 +01:00
Roberto De Ioris c5099b6d38 faster uwsgi_uuid_cmp() 2012-12-30 12:17:22 +01:00
Roberto De Ioris d535c22723 do not rely on uuid_compare() [2] 2012-12-30 12:14:50 +01:00
Roberto De Ioris fa68d2cae3 do not rely on uuid_compare() 2012-12-30 12:13:11 +01:00
Roberto De Ioris 5a754e66fe implemented uuid compare for legion and added a warning for system not using libuuid 2012-12-30 11:55:50 +01:00
Roberto De Ioris 83f9920705 improved mod_proxy_uwsgi 2012-12-30 11:04:43 +01:00
Roberto De Ioris f3dd60d683 fixed socket naming 2012-12-30 08:52:43 +01:00
Roberto De Ioris e25e671104 removed excessive debugging info in legion 2012-12-30 08:34:21 +01:00
Roberto De Ioris c3b101baf4 improve legion reliability 2012-12-29 20:26:59 +01:00
Roberto De Ioris b60c9b24b3 added 'signal' and 'log' Lord action 2012-12-29 20:21:03 +01:00
Roberto De Ioris 8aba421a87 fixed iv usage 2012-12-29 20:08:58 +01:00
Roberto De Ioris 15c0b5f5e9 implemented iv for legion 2012-12-29 20:03:00 +01:00
Roberto De Ioris f6271b1893 fixed quorum math 2012-12-29 19:39:10 +01:00
Roberto De Ioris 374317cffd completed voting subsystem for legions 2012-12-29 19:13:43 +01:00
Roberto De Ioris 6f7b158942 report checksum in quorum 2012-12-29 18:45:51 +01:00
Roberto De Ioris 310eb53a37 added checksum and unix time check in legion packets 2012-12-29 18:44:58 +01:00
Roberto De Ioris badeafef59 reports quorum status at every legion changes 2012-12-29 18:18:39 +01:00
Roberto De Ioris 35557de982 improvements in the legion subsystem 2012-12-29 17:52:38 +01:00
Roberto De Ioris b0a7501212 first attempt of legion quorum implementation [step 2] 2012-12-29 17:36:36 +01:00
Roberto De Ioris f45db5456e first attempt of legion quorum implementation 2012-12-29 17:29:25 +01:00
Roberto De Ioris 2b58c79611 add uuid to legion packets 2012-12-29 16:11:19 +01:00
Roberto De Ioris b7499f22f5 do not report error if /proc file system is not mounted 2012-12-29 15:37:53 +01:00
Roberto De Ioris d55a5e1b8c added --cache-sync for initial synchronization with remote caches 2012-12-28 21:24:28 +01:00
Roberto De Ioris e4ec5b000e refactored utils.c and created io.c 2012-12-28 21:10:06 +01:00
Roberto De Ioris dd983135c6 another cleanup [2] 2012-12-28 14:33:12 +01:00
Roberto De Ioris 09fe2960b5 another cleanup 2012-12-28 14:32:27 +01:00
Roberto De Ioris cf5794e22c moved uwsgirouter*.py to examples 2012-12-28 14:31:29 +01:00
Alex Bubnoff 2f2876fe6b fixed build error of pyerl plugin 2012-12-24 17:36:04 +07:00
unbit 1f1008c415 Update CONTRIBUTORS 2012-12-24 10:46:26 +01:00
unbit c02a936b61 Merge pull request #97 from guokr/master
Fix the memory leak of jvm and jwsgi plugins
2012-12-24 00:04:20 -08:00
Mingli d28cdaabb3 release chars 2012-12-24 11:33:21 +08:00
Mingli ec78213819 fix compiler error 2012-12-24 11:06:27 +08:00
Mingli 2a2303e37f remove local ref in jvm and fix indent 2012-12-24 10:19:37 +08:00
Mingli 90bc859222 Merge remote-tracking branch 'upstream/master' 2012-12-24 10:00:52 +08:00
Mingli a3be8d36fe frame scoping in jwsgi 2012-12-24 09:57:35 +08:00
Roberto De Ioris de3e70c61f skel for storage subsystem 2012-12-22 10:12:59 +01:00
Roberto De Ioris c3bba30af5 improved listen_queue management in freebsd 2012-12-21 12:07:30 +01:00
Roberto De Ioris 35566a8533 start refactoring tcp_info usage 2012-12-21 11:50:05 +01:00
Roberto De Ioris dda86dbc9c fixed a https/corerouter corner-case bug 2012-12-21 11:30:46 +01:00
Roberto De Ioris 5f971812d1 set HTTPS to on when behind stud 2012-12-21 08:59:25 +01:00
Giovanni Scala 17c8fff794 fixed --php-app-bypass 2012-12-20 20:44:25 +01:00
Giovanni Scala e4d5ca9209 added --php-app-bypass 2012-12-20 20:42:27 +01:00
Roberto De Ioris 8536bc349a added --http-stud-prefix 2012-12-19 18:37:13 +01:00
Roberto De Ioris e4b34921e1 report pos in failed uploads 2012-12-16 12:56:55 +01:00
Roberto De Ioris f966ef8e69 fixed computation of post data 2012-12-16 12:17:06 +01:00
Roberto De Ioris df8efa31dd more debug for https 2012-12-16 10:57:56 +01:00
Roberto De Ioris ee6aff6665 added additional uwgsi-gevent error report 2012-12-15 20:34:25 +01:00
Roberto De Ioris 5f2abf9949 fixed uwsgi_str_num for 32bit 2012-12-15 14:30:22 +01:00
unbit ee9b4a70d4 Merge pull request #86 from scottkmaxwell/master
1.4.3 wouldn't build on my Mac due to a too-strict cast in the Yaml plug-in.
2012-12-13 22:48:40 -08:00
Roberto De Ioris d5632f7715 fixed net offloading and http internal router 2012-12-13 15:25:45 +01:00
Roberto De Ioris efd10599a6 oops alarm_xmpp should not be build by default 2012-12-13 11:06:23 +01:00
Roberto De Ioris f0a846927e allows embedding .cc and .m files 2012-12-13 11:03:17 +01:00
Scott Maxwell 5e876e4adc Loosen up cast so we can build on Mac
Cast to (const unsigned char*) caused error building on OS X Mountain Lion
2012-12-12 09:51:30 -08:00
Roberto De Ioris d968e9f39e dup2() returns < 0 on error 2012-12-12 15:02:37 +01:00
unbit 54fa0ab19f Merge pull request #84 from prymitive/travis_buildconf
travis buildconf
2012-12-11 21:52:05 -08:00
Łukasz Mierzwa d63a570230 travis buildconf 2012-12-11 22:32:23 +01:00
Roberto De Ioris 98e9822150 removed garbage from old versions 2012-12-10 17:37:13 +01:00
unbit 6a9809b301 Merge pull request #82 from prymitive/cheaper_initial
check if --cheaper-initial is valid
2012-12-10 08:07:54 -08:00
Łukasz Mierzwa 47590a2b0d check if --cheaper-initial is valid 2012-12-10 17:01:15 +01:00
Roberto De Ioris 1447ae01bd improved uwsgi_run_command 2012-12-10 15:10:52 +01:00
Roberto De Ioris d24ad0e61c close fds for external processes 2012-12-10 14:45:01 +01:00
Roberto De Ioris 0a0b27ad4c added offload-thread alias 2012-12-07 13:39:39 +01:00
Roberto De Ioris 504151b695 improved stdin management in cron 2012-12-07 12:40:29 +01:00
Roberto De Ioris 813074b010 fixed emperor 2012-12-07 12:06:49 +01:00
Roberto De Ioris 01cbcbad47 django dir will be in a dedicated repository 2012-12-07 11:39:15 +01:00
Roberto De Ioris 20b0dc0d1e removed uwsgicc, it should be on a separate repository 2012-12-07 11:33:50 +01:00
root 6e6dd65cef updated Changelog for 1.5 2012-12-07 11:30:17 +01:00
root e77f1d5069 %z is not portable 2012-12-07 11:25:14 +01:00
root 41af8e54bb fixed FIXME for #79 2012-12-07 11:18:33 +01:00
unbit d598a10013 Merge pull request #79 from prymitive/log_format_fixes
few log format fixes
2012-12-07 02:16:18 -08:00
root 9af9cd09f9 --not-alarm-log is the only condition that need to break 2012-12-07 11:13:44 +01:00
root b358c46413 added support for negative regexp in alarm-log 2012-12-07 10:58:58 +01:00
root 45ffa98b5e added preliminary support for TCP_FASTOPEN 2012-12-07 10:33:39 +01:00
root f458877e53 improved emperor reloading 2012-12-07 09:04:32 +01:00
root 544e598dcb improved emperor custom config management 2012-12-07 07:58:48 +01:00
root 360a94691d added --get for shell scripting 2012-12-06 14:51:34 +01:00
unbit a297b9b981 Merge pull request #78 from prymitive/cheaper_busyness_logging
fixed log format in cheaper_busyness
2012-12-06 05:28:05 -08:00
Łukasz Mierzwa 7bb424622c few log format fixes 2012-12-06 13:55:43 +01:00
Łukasz Mierzwa 0d382a846a fixed log format in cheaper_busyness 2012-12-06 12:44:37 +01:00
root e82430369e added --legion-death 2012-12-06 11:23:45 +01:00
unbit 647e1e0826 Merge pull request #77 from prymitive/x_forwarded_for
use client address if X-Forwarded-For is missing
2012-12-06 02:00:53 -08:00
Łukasz Mierzwa b5802b4793 fallback to REMOTE_ADDR if HTTP_X_FORWARDED_FOR is missing but --log-x-forwarded-for was used 2012-12-06 10:51:59 +01:00
root af5dbda00d fixed unlord 2012-12-06 10:35:11 +01:00
root 4b889c90bf completed legion subsystem, added cmd legion_action 2012-12-06 10:24:32 +01:00
unbit 1313841dd3 Merge pull request #76 from prymitive/carbon_newline
missing new line in carbon plugin logs
2012-12-05 23:56:34 -08:00
Łukasz Mierzwa b09c343627 missing new line in carbon plugin logs 2012-12-05 22:33:08 +01:00
root ca97c0653f added newline to legion log 2012-12-05 21:03:47 +01:00
Roberto De Ioris 76edb7374e support for zeromq3 in emperor_zeromq 2012-12-04 12:55:55 +01:00
Roberto De Ioris c8f53b9296 report name and pid for upcoming Lord 2012-12-04 12:44:02 +01:00
Roberto De Ioris 55a190312a a note about iv for encryption 2012-12-04 12:37:32 +01:00
Roberto De Ioris 7ebbac0dd8 completed legion management and logic 2012-12-04 12:35:17 +01:00
Roberto De Ioris 1662f58a09 added first lord check 2012-12-03 19:44:39 +01:00
Roberto De Ioris ac5ca4a002 added legion decrypter 2012-12-03 19:42:13 +01:00
Roberto De Ioris ebadaa73a8 bind to legion address 2012-12-03 18:09:28 +01:00
Roberto De Ioris 55fdc9d847 initialize encrypt/decrypt contexts for legions 2012-12-03 17:39:03 +01:00
Roberto De Ioris a409a82736 Merge branch 'master' of github.com:unbit/uwsgi 2012-12-03 15:58:18 +01:00
Roberto De Ioris 58e3b7166c added core/ssl.c for ssl utilities (moved from core/utils.c) and prepare for legion support 2012-12-03 15:57:54 +01:00
unbit cac413f725 Update core/legion.c 2012-12-03 09:43:45 +01:00
Roberto De Ioris 73e3938d9a added legions subsystem introduction 2012-12-03 09:41:54 +01:00
Roberto De Ioris 985114b7bd fixed #66 2012-12-01 15:44:52 +01:00
Roberto De Ioris fb4a594add SNI support 2012-12-01 15:34:28 +01:00
Roberto De Ioris 5d8f91c1ed added zeromq imperial monitor 2012-11-30 18:33:46 +01:00
Roberto De Ioris 759a9d4439 added emperor:// to the supported schemes, improved vassals config handling 2012-11-30 18:23:27 +01:00
unbit 25b29df65e core: make smart-attach-daemon smart enough
Avoid call storming of pidfile check that leads to multiple daemons
running instead of one. Fix #65.
2012-11-28 20:57:06 +01:00
unbit 9f396466bd Merge pull request #64 from prymitive/touch_logrotate
fixed --touch-logrotate after my patch
2012-11-27 12:07:24 -08:00
Łukasz Mierzwa c79b36a59d fixed --touch-logrotate after my patch 2012-11-27 20:47:55 +01:00
unbit de33a4a5a3 Merge pull request #61 from prymitive/touch_reload
enhanced file touch checker
2012-11-27 04:04:19 -08:00
Roberto De Ioris 88e108cacc fixed #20 2012-11-27 13:02:59 +01:00
unbit 163d71c5b8 Merge pull request #62 from xrmx/cpucount
uwsgiconfig: permit to override CPUCOUNT with environment variable
2012-11-27 03:37:59 -08:00
Riccardo Magliocchetti 936d4b19a5 uwsgiconfig: permit to override CPUCOUNT with environment variable
CPUCOUNT=X make

will force X cores instead of the autodetected ones
2012-11-27 12:23:06 +01:00
Łukasz Mierzwa 93cbd60f11 enhanced file touch checker 2012-11-27 11:54:13 +01:00
Roberto De Ioris 850cbea236 added --http-session-context 2012-11-25 21:21:08 +01:00
Roberto De Ioris 3ceda8993a removed some debug 2012-11-25 19:04:37 +01:00
Roberto De Ioris ccad290b78 added cache full counter 2012-11-25 18:51:01 +01:00
Roberto De Ioris 66d28aa958 added cache stats 2012-11-25 18:43:37 +01:00
Roberto De Ioris 3717b8cd13 implemented udp cache del 2012-11-25 17:48:18 +01:00
Roberto De Ioris 6e5fc85e54 uwsgi_cache_del now takes flags 2012-11-25 17:29:41 +01:00
Roberto De Ioris a3bbfde884 refactored cache threads 2012-11-25 17:22:44 +01:00
Roberto De Ioris fd86c6cafa implemented expires in cache udp server 2012-11-25 16:42:40 +01:00
Roberto De Ioris cb87f8f6d6 implemented udp cache update 2012-11-25 16:02:05 +01:00
Roberto De Ioris 4ccd20eb23 pre-build cache udp nodes addresses 2012-11-25 14:09:25 +01:00
Roberto De Ioris 9ced8f9bdd skeleton for --cache-udp-server and --cache-udp-node 2012-11-25 13:07:34 +01:00
Roberto De Ioris 4eb174e9cb first implementation of ssl sessions store in the shared cache 2012-11-25 10:46:58 +01:00
Roberto De Ioris 598250d469 added --php-var 2012-11-24 11:22:01 +01:00
Roberto De Ioris 6cc3faf14d improved QUERY_STRING management in router_rewrite 2012-11-24 11:14:44 +01:00
Roberto De Ioris 8864f3c53c fixed corner-case ssl body reading 2012-11-24 09:52:24 +01:00
unbit 49dd3366fc Merge pull request #60 from prymitive/travisci
removed python2.5 from build
2012-11-23 05:26:04 -08:00
Łukasz Mierzwa 5d253ab00f removed python2.5 2012-11-23 14:20:03 +01:00
Roberto De Ioris 25db778f32 Revert "uClibc compatibility for core"
This reverts commit c2d2f13bfb.
2012-11-23 10:10:26 +01:00
unbit 35fbd85fad Merge pull request #59 from kunkku/uclibc
uClibc compatibility for core
2012-11-23 00:26:00 -08:00
Kaarle Ritvanen c2d2f13bfb uClibc compatibility for core 2012-11-23 08:45:24 +02:00
Roberto De Ioris 7add254781 fixed typo in the php plugin 2012-11-22 16:38:22 +01:00
Giovanni Scala 970d899986 honour QSA style in php-app-qs 2012-11-22 07:39:01 +01:00
Giovanni Scala d719ed6a3b added php-app-qs 2012-11-22 06:26:36 +01:00
Giovanni Scala 7fcc8ba6ac fixed sendfile offload with bigger files 2012-11-22 05:28:56 +01:00
Roberto De Ioris 70e1bda986 refactored rewrite plugin 2012-11-21 18:01:39 +01:00
Roberto De Ioris 32789e62a5 fixed PATH_TRANSLATED in cgi and improved var appending 2012-11-21 17:54:47 +01:00
Roberto De Ioris 6297ed0455 do not crash on non-existent config files 2012-11-21 07:48:06 +01:00
unbit 1cbabf6296 Merge pull request #56 from xtfxme/feature/extract
feature/extract: dump the specified address to stdout and exit
2012-11-20 07:56:33 -08:00
C Anthony Risinger e7f694cdc5 feature/extract: dump the specified address to stdout and exit
similar to `--connect-and-read` except for file-like addresses; allows such
things as:

```
$ uwsgi --extract data://0
$ uwsgi --extract sym://embedded_json
$ uwsgi --extract http://me.local/config.xml
$ uwsgi --extract section://rootfs.tar.gz
$ uwsgi --ini exec://"uwsgi --extract section://rootfs.tar.gz | \
        tar xz && cat rootfs/config.ini"
```

...the latter of which embeds/extracts a complete rootfs for immediate use!
combined with embedded configs + declare-options, one can construct a self-
extracting -- single-file -- app that managed it's own plugins, configs,
databases, shared libs, [...]
2012-11-20 09:48:29 -06:00
Unbit 5f93d93cc1 added x magic var 2012-11-19 09:35:22 +01:00
Unbit 15fa7a9c09 improved section detection 2012-11-19 09:16:29 +01:00
Roberto De Ioris 2e9e5af686 added perl signal_wait and mule handler 2012-11-17 12:12:43 +00:00
Roberto De Ioris 54c1055f15 Merge branch 'master' of github.com:unbit/uwsgi 2012-11-16 19:58:05 +00:00
Roberto De Ioris 114d71af8d implemented register_signal in the psgi plugin 2012-11-16 19:57:54 +00:00
unbit 757c3e7d95 Merge pull request #52 from prymitive/travisci
More advanced travis config
2012-11-15 05:19:04 -08:00
unbit 0233f3e712 Merge pull request #54 from kunkku/lua-async
Support asynchronous requests in Lua plugin
2012-11-15 05:18:05 -08:00
Kaarle Ritvanen e23a7bfd80 support asynchronous requests in Lua plugin 2012-11-15 14:18:45 +02:00
Roberto De Ioris 6c67d205b8 fixed magic_table management 2012-11-15 10:01:24 +01:00
Łukasz Mierzwa aaaae5a602 * travis config with plugins for multiple python and ruby versions
* basic script with tests for each python and rack plugin
2012-11-13 21:27:15 +01:00
Roberto De Ioris 5ddd773680 fixed #51 2012-11-13 04:36:45 +01:00
Roberto De Ioris 34bb5de3aa fixed static_maps 2012-11-12 14:42:44 +01:00
Roberto De Ioris e23094e820 clear uwsgi_thread structure on setup 2012-11-12 14:11:15 +01:00
Roberto De Ioris 8d53e4aa54 fixed offload threading when the numbr of ocres is higher than 1 2012-11-12 13:49:10 +01:00
Roberto De Ioris ca1666789d Merge branch 'master' of github.com:unbit/uwsgi 2012-11-12 13:13:26 +01:00
Roberto De Ioris 211ed5c71c corerouter NOT courerouter 2012-11-12 13:09:06 +01:00
unbit 9f6a88d9d7 Merge pull request #48 from prymitive/travis
minimal travis.yml file
2012-11-12 03:35:38 -08:00
Roberto De Ioris 3d483f22ca 'wsgi' option is an alias for 'module' not 'wsgi-file' 2012-11-12 11:57:02 +01:00
Roberto De Ioris a6bbb0cfa4 starting 1.5 development cycle 2012-11-12 11:37:51 +01:00
Łukasz Mierzwa e6c9e53f14 minimal travis.yml file 2012-11-12 10:52:42 +01:00
Roberto De Ioris e13734ae6c uWSGI 1.4 2012-11-12 10:45:05 +01:00
Roberto De Ioris cf62b03e33 endiness fixes and added support for not waiting for thread cancellation 2012-11-12 10:36:18 +01:00
Roberto De Ioris b2f292c2da some Changelong improvement 2012-11-12 09:46:47 +01:00
Roberto De Ioris b96b6a24a6 support for rack official commit afc9b0313c 2012-11-12 09:40:38 +01:00
Roberto De Ioris b2a1237781 added --undeferred-shared-socket 2012-11-11 19:41:00 +01:00
Roberto De Ioris a48af2e226 workaround missing IP_FREEBIND 2012-11-11 19:07:28 +01:00
Roberto De Ioris 33446c3179 better cap management 2012-11-11 18:59:05 +01:00
Roberto De Ioris 242e01e37a added 'wsgi' alias option 2012-11-11 17:32:18 +01:00
Roberto De Ioris 41eba2b486 report static nodes in corerouters stats 2012-11-10 11:51:19 +01:00
Roberto De Ioris 24763fdbd2 fixed xclient 2012-11-10 11:23:39 +01:00
Roberto De Ioris 951cbf3eba implemented retries and fallback on the rawrouter 2012-11-10 10:25:40 +01:00
Roberto De Ioris 8759b66206 ported rawrouter to the new api with xclient support 2012-11-10 09:33:33 +01:00
Roberto De Ioris 93aacace5f ready for 1.4-rc2 2012-11-09 22:37:54 +01:00
Roberta Giordano 8406fb12be fixed OSX sendfile 2012-11-09 21:55:26 +01:00
Roberto De Ioris 6af3ea267e added offload sendfile to OSX 2012-11-09 21:54:05 +01:00
Roberto De Ioris 9ff37ce019 be more verbose about offload threads 2012-11-09 21:46:28 +01:00
Roberto De Ioris f4187680bd offload sendfile supported on FreeBSD and DragonFly 2012-11-09 21:36:39 +01:00
Roberto De Ioris 57b72ac17d allows multiple offload threads 2012-11-09 21:24:30 +01:00
Roberto De Ioris 5c64839734 even the router_uwsgi plugin can offload 2012-11-09 20:18:43 +01:00
Roberto De Ioris e4de9a8bc7 improved offload threads subsystem 2012-11-09 20:04:27 +01:00
Roberto De Ioris 689b4afb44 moved offload functions to a dedicated file 2012-11-09 16:48:30 +01:00
Roberto De Ioris ceebaa7d9d fixed indentation 2012-11-09 12:16:39 +01:00
Roberto De Ioris 0fa2c543ec added pcre jit support 2012-11-09 12:04:13 +01:00
Roberto De Ioris 519df88126 allows cross-domain JSON requests to stats subsystem 2012-11-08 17:38:57 +01:00
Roberto De Ioris 75b275591d count per-core static requests 2012-11-08 09:05:46 +01:00
Roberto De Ioris 2f901f08cb fixed magic vars for symlinks 2012-11-08 07:33:43 +01:00
Roberto De Ioris b041fe4473 fixed wrong error message 2012-11-08 06:50:31 +01:00
Roberto De Ioris f5d6cb65f9 added uwsgi.Handler(http.Handler) go func 2012-11-07 15:52:37 +01:00
Roberto De Ioris 9c94aedb29 added Changelog for 1.4 2012-11-07 14:20:08 +01:00
Roberto De Ioris d248b290f2 added --php--allowed-script 2012-11-07 12:24:12 +01:00
Roberto De Ioris cb48070db1 fixed systemd support 2012-11-07 11:40:56 +01:00
unbit cd34bac104 Merge pull request #45 from prymitive/static_methods
disable static files offloading for methods other than GET and HEAD
2012-11-06 11:23:01 -08:00
Łukasz Mierzwa c966fbb163 disable static files offloading for methods other than GET and HEAD 2012-11-06 14:00:04 +01:00
Roberto De Ioris feac596efc fixed SSL buffer usage 2012-11-06 06:26:41 +01:00
Roberto De Ioris 981ddfcefe do not segfault on go if master-requiring api is called 2012-11-05 19:42:39 +01:00
Roberto De Ioris 5e561b6578 simplified go interface 2012-11-05 18:18:48 +01:00
unbit fab495fadc added Stephen Pierce to CONTRIBUTORS 2012-11-05 17:24:59 +01:00
Unbit ecbda6dc26 refactored go symbol loaders 2012-11-05 11:16:42 +01:00
Roberto De Ioris e23766e4d0 added go complextest 2012-11-05 10:37:07 +01:00
Roberto De Ioris 6d9de4c618 completed caching support for go 2012-11-05 10:32:37 +01:00
Roberto De Ioris 4ca14f6046 added two tests for go web apps, and completed request body advanced management 2012-11-05 09:09:38 +01:00
Roberto De Ioris d856c9920d added comments in uwsgi.go package 2012-11-05 07:51:00 +01:00
Roberto De Ioris fd62440265 Merge branch 'master' of github.com:unbit/uwsgi 2012-11-04 19:52:59 +01:00
Roberto De Ioris d4041c9e1d fixed goroutines support 2012-11-04 19:52:46 +01:00
unbit dc9e1bd324 Merge pull request #44 from StephenPierce/new-snmp-functions
New snmp functions
2012-11-04 10:44:39 -08:00
Roberto De Ioris 89bbd967ed added --goroutines shortcut 2012-11-04 11:00:06 +01:00
Roberto De Ioris 276ada315d fallback to DefaultServeMux if no RequestHandler has been defined 2012-11-04 10:54:06 +01:00
Roberto De Ioris bdd0d408a0 go modifier1 is officially assigned as 11 2012-11-04 10:41:51 +01:00
Roberta Giordano 5ddaa2e436 fixed go build in OSX 2012-11-04 10:31:12 +01:00
Roberto De Ioris f9d0e75056 automatically build uwsgi.go 2012-11-04 10:17:23 +01:00
Roberto De Ioris 7776a1f0be added preliminary go support 2012-11-04 09:24:06 +01:00
Stephen Pierce a33a57d8af Removed unneeded import 2012-11-02 16:02:46 -07:00
Stephen Pierce 9371e2b8de Added SNMP incr/decr functions for counter32/counter64/gauge types. Wrapped all operations (set/get/incr/decr) with lock to prevent contention. 2012-11-02 16:00:31 -07:00
Roberto De Ioris 6c1a842f7d improved reloading robustness 2012-11-02 14:30:14 +01:00
Roberto De Ioris d746deaf02 Merge branch 'master' of github.com:unbit/uwsgi 2012-11-02 12:38:09 +01:00
Roberto De Ioris 09fca72b4c fixed spooler max tasks handling 2012-11-02 12:37:41 +01:00
unbit 2ffc31e578 Merge pull request #41 from prymitive/valgrind
valgrind suppression file generator
2012-11-02 04:14:56 -07:00
unbit 2a254d195a Merge pull request #42 from prymitive/head
set http status on head static request
2012-11-02 04:14:33 -07:00
Roberto De Ioris 95d3ee4e61 added mongodb stats pusher 2012-11-02 12:06:08 +01:00
Roberto De Ioris 4d56474511 implemented stats pushers 2012-11-02 11:23:12 +01:00
Łukasz Mierzwa 46a33b268a set http status on head static request 2012-11-02 11:21:52 +01:00
Łukasz Mierzwa b0829cc2e3 more suppressions 2012-11-02 10:56:56 +01:00
Łukasz Mierzwa 93a0913182 valgrind suppression file generator 2012-11-02 10:38:00 +01:00
Roberto De Ioris 0605148e21 report signal_queue size in stats, fixed linux timerfd and inotify 2012-11-02 09:44:49 +01:00
Roberto De Ioris e7b5c7c8e4 allows generating minified json 2012-11-02 08:43:55 +01:00
Roberto De Ioris b2a0fd1914 truncate malformed/huge log lines 2012-10-31 19:55:21 +01:00
Roberto De Ioris 9cc89a6052 emperor is now tolerant to extreme Linux-OOM situations 2012-10-31 11:11:39 +01:00
Roberto De Ioris 1606b8b775 remove obsolete ruby threading definitions 2012-10-31 10:54:57 +01:00
unbit cfac385f8e Merge pull request #39 from prymitive/cppcheck
missing close() call in utils/uwsgi_num_from_file()
2012-10-31 02:29:54 -07:00
Łukasz Mierzwa 99fd4572cb missing close() call in utils/uwsgi_num_from_file() 2012-10-30 23:57:48 +01:00
Roberto De Ioris d3194ca011 remove monitored fd from async queue when in async mode 2012-10-30 18:31:04 +01:00
Roberto De Ioris af61a9e33f re-indented core/async.c 2012-10-30 18:01:35 +01:00
Roberto De Ioris 4896e22a62 preventively read a page of data in stats http mode 2012-10-30 09:42:17 +01:00
Roberto De Ioris 7882d12a80 better sockets management in stats servers 2012-10-30 09:31:15 +01:00
Roberto De Ioris 9342acc500 allows exported json stats in http format 2012-10-30 08:45:32 +01:00
Roberto De Ioris 929a919c9d exports spoolers data in stats server 2012-10-30 08:19:42 +01:00
Roberto De Ioris d1f6e97dd7 do not transfer static files if method is HEAD 2012-10-30 07:22:25 +01:00
Roberto De Ioris f9d76f90eb better configfile path management 2012-10-29 19:48:43 +01:00
Unbit 2de5e8994f allows building without routing 2012-10-29 16:51:21 +01:00
unbit 7e935253a2 Merge pull request #36 from prymitive/fr
count requests in (fast|http)router
2012-10-29 04:07:50 -07:00
Łukasz Mierzwa 4c20d83573 count requests in (fast|http)router / with cs->un checks 2012-10-29 11:44:56 +01:00
Łukasz Mierzwa 7035a676a2 count requests in (fast|http)router 2012-10-29 10:58:03 +01:00
Roberto De Ioris 736f99d10b added router_cache plugin 2012-10-29 10:11:42 +01:00
Roberto De Ioris ea422a4576 fixed cache size reporting in 32bit 2012-10-29 09:29:43 +01:00
Roberto De Ioris e274f53286 a couple of fedora17-specific fixes 2012-10-28 19:58:25 +01:00
Roberto De Ioris c03dcf4617 added logfile commodity plugin 2012-10-28 19:27:42 +01:00
Roberto De Ioris d70c7ceb89 added --log-route 2012-10-28 18:15:09 +01:00
Roberto De Ioris 9ae1354d1a added the systemd journal logger 2012-10-28 08:02:18 +01:00
Roberto De Ioris b29f0b9436 reimplemented --http-to-https 2012-10-27 20:12:19 +02:00
Roberto De Ioris e01cd802d8 re-implemented http expect/continue 2012-10-27 19:39:01 +02:00
Roberto De Ioris c7b57c9776 added --log-filter 2012-10-27 15:59:48 +02:00
Roberto De Ioris 3a48b898ad refactored router_access plugin 2012-10-27 15:37:14 +02:00
unbit 4f4771b527 Merge pull request #31 from brainbitsca/master
router_access - plugin to implement hosts_access
2012-10-27 06:03:58 -07:00
Roberto De Ioris b43df60d7f added uwsgi_kvlist_parse api function 2012-10-27 14:58:19 +02:00
Roberto De Ioris 10a5661218 added C Anthony Risinger as contributor 2012-10-27 12:15:53 +02:00
Roberto De Ioris a99670cfb5 fixed an incredibly stupid bug in http/https router 2012-10-27 11:58:10 +02:00
unbit 7967e8ac3c Merge pull request #33 from prymitive/harakiri
More accurate harakiri counting
2012-10-26 01:31:12 -07:00
colinlbc e105ebe273 remove stray uwsgi_log() 2012-10-25 14:47:50 -07:00
colinlbc 11d2c004c2 moved critical scrncpy out of #ifdef UWSGI_DEBUG 2012-10-25 14:30:47 -07:00
colinlbc e8bfa12372 Reworked things to get rid of several pointer errors.
Implemented svcname paramater for hosts access mode to set daemon name in hosts.allow,hosts.deny.
New router config syntax:

svcname defaults to uwsgi

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

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

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

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

This and other variables are passed from nginx from the nginx code in
src/http/ngx_http_variables.c. This was tested with nginx 1.0.15.
2012-09-13 08:17:22 +00:00
roberto@quantal64 5cea1de1ba added master_cleanup hook and carbon flush on stop/reload 2012-09-12 19:03:22 +02:00
roberto@quantal64 e735b9e31f applied busyness_backlog.diff by Łukasz Mierzwa 2012-09-12 18:12:55 +02:00
roberto@quantal64 9ff8f8899f added --log-drain 2012-09-12 08:08:32 +02:00
roberto@quantal64 d908c4ef35 allows building without udp 2012-09-07 19:45:58 +02:00
roberto@quantal64 207f50726d oops, use classic perl syntax for push 2012-09-07 19:36:21 +02:00
roberto@quantal64 212559fcce put sleep() in each psgi cleanup hook to show its power :P 2012-09-07 19:13:34 +02:00
roberto@quantal64 cf480e499c implemented psgi cleanup handlers, and fixed a leak in rpc call 2012-09-07 19:09:22 +02:00
roberto@quantal64 f2e27f5154 improved process limit detection 2012-09-07 14:54:57 +02:00
roberto@quantal64 d932a4feae fixed typcasting 2012-09-07 14:40:06 +02:00
roberto@quantal64 da6e05072f explicit link with librt for alternatives clock 2012-09-07 06:58:26 +02:00
roberto@quantal64 13277d9d71 improved cheaper_busyness 2012-09-06 17:10:03 +02:00
roberto@quantal64 f17f8b337f fixed idle mode 2012-09-06 16:21:12 +02:00
roberto@quantal64 ffb454e414 headers must be sent before close() 2012-09-06 15:22:17 +02:00
roberto@quantal64 424f5a09e7 call close() always, even if client disconnect 2012-09-06 15:02:12 +02:00
roberto@quantal64 c29a6f6446 removed STOP/TSTP signal from gateways 2012-09-06 11:20:21 +02:00
roberto@quantal64 6f7edf0941 fixed uwsgi_buffer realloc len 2012-09-04 19:18:38 +02:00
roberto@quantal64 a4c4b7e8d2 fixed uwsgi_buffer realloc 2012-09-04 18:13:16 +02:00
roberto@quantal64 837f6f3a54 initialize spooler locks before app loading 2012-09-04 08:21:40 +02:00
roberto@quantal64 13041da6bf fixed piping 2012-09-04 08:13:02 +02:00
roberto@quantal64 046824dae7 fixed usage of mmap() 2012-09-03 14:11:42 +02:00
roberto@quantal64 269a588d9d uWSGI 1.3-rc2 2012-09-01 11:42:42 +02:00
roberto@quantal64 50ae12518a Added tag 1.3-rc2 for changeset 14524da00a8b 2012-09-01 11:42:31 +02:00
303 changed files with 37279 additions and 21884 deletions
+5
View File
@@ -0,0 +1,5 @@
*.o
*.py[co]
/uwsgi
/uwsgibuild.*
+4
View File
@@ -52,3 +52,7 @@ 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
+44
View File
@@ -0,0 +1,44 @@
language: c
compiler:
- gcc
- clang
script:
- echo -e "\n\n>>> Building uWSGI binary"
- /usr/bin/python uwsgiconfig.py --build travis
- echo -e "\n\n>>> Building python26 plugin"
- /usr/bin/python2.6 -V
- /usr/bin/python2.6 uwsgiconfig.py --plugin plugins/python base python26
- echo -e "\n\n>>> Building python27 plugin"
- /usr/bin/python2.7 -V
- /usr/bin/python2.7 uwsgiconfig.py --plugin plugins/python base python27
- echo -e "\n\n>>> Building python31 plugin"
- /usr/bin/python3.1 -V
- /usr/bin/python3.1 uwsgiconfig.py --plugin plugins/python base python31
- echo -e "\n\n>>> Building python32 plugin"
- /usr/bin/python3.2 -V
- /usr/bin/python3.2 uwsgiconfig.py --plugin plugins/python base python32
- echo -e "\n\n>>> Building python33 plugin"
- /usr/bin/python3.3 -V
- /usr/bin/python3.3 uwsgiconfig.py --plugin plugins/python base python33
- echo -e "\n\n>>> Building rack 1.8.7 plugin"
- /usr/bin/ruby1.8 -v
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.8 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack187
- echo -e "\n\n>>> Building rack 1.9.1 plugin"
- /usr/bin/ruby1.9.1 -v
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.9.1 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack191
- echo -e "\n\n>>> Building cgi plugin"
- /usr/bin/python uwsgiconfig.py --plugin plugins/cgi base
- echo -e "\n\n>>> Building dummy plugin"
- /usr/bin/python uwsgiconfig.py --plugin plugins/dummy base
- echo -e "\n\n>>> Building done, starting tests"
- ./tests/travis.sh
before_install:
- sudo add-apt-repository -y ppa:fkrull/deadsnakes
- sudo apt-get update -qq
- sudo apt-get install -qqyf python2.6-dev python2.7-dev python3.1-dev python3.2-dev python3.3-dev rubygems1.8 ruby1.8-dev ruby1.9.1-dev
- sudo apt-get install -qqyf libxml2-dev libpcre3-dev libcap2-dev
- sudo apt-get install -qqyf curl
+4
View File
@@ -18,3 +18,7 @@ Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
-636
View File
@@ -1,636 +0,0 @@
*** current ***
* 1.3
- python tracebacker
- user-governed harakiri
- simplified external plugin development
- Linux namespace mountpoint improvements
- secured subscription system
- merged routers codebase (fastrouter, http, rawrouter)
- https support in the http router
- config report at the end of uWSGI build process
- support for keepalive in the http router
- improved subscription system (multicast and unix socket)
- custom options
- graceful reloads on shared sockets
- configurable log-master buffer size
- extreme-optimizations for the stats subsystem
*** april 2012 ***
* 1.2 [20120430]
- PyPy support
- Improved gevent support with threads
- Python auto-reload subsystem
- added --spooler-max-tasks
- pthread robust mutexes support in Linux and Solaris
- posix semaphores support in FreeBSD9
- thread-safe ctime() reporting
- interval support in cron subsystem
- improved syslog support
- better management of disconnected clients
- static files serving improvements
- another set of multithreading optimizations
- minor fixes in the Rack plugin
- Upstart socket-activation support
*** march 2012 ***
* 1.1 [20120317]
- new options parser subsystem
- improved php support
- multiple spooler with multiprocessing
- segmentation fault and floating point exceptions manager
- never-swap option
- zergpool plugin
- perl/psgi multiple interpreters support
- deadlock detector
- pluggable cheaper algos
- new internal routing susbsystem
- preliminary support for config logic
- log rotation infrastructure
- support for paste loggers
- threading improvements
- plugins can now mapped to specific modifiers
- <app> tag is deprecated (use mount option)
- report startup time for apps
- reintroduced expat support
- reintroduced remote spooler plugin
- various fastrouter optimizations
- added ruby rvm support
*** december 2011 ***
* 1.0 [20111230]
- adaptive process spawning (--cheaper option)
- new control options --stop, --reload, --suspend, --resume, --pause
- stats framework
- new subscription system
- support for mime types in static file serving
- posix capablities support
- uWSGI mules and farms
- support for multiple --touch-reload options
- new logging subsystem
- new custom locking subsystem
- process name handling
- better (and faster) HTTP parser
- perl and python threading improvements
- new plugins: rrdtool, carbon, cgi, php
- various improvements in the Rack/ruby plugin
- Linux KSM support
- refactored ping and nagios plugins
- support for signals in lazy mode
- optimized static-file serving
- support for linux unshare()
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** july 2011 ***
* 0.9.8.3 [20110723]
- implemented uwsgi.SymZipImporter to load embedded zip files
- OSX Lion is officially supported
- fixed xinetd support (example file added in contrib)
- suppot for systemd socket activation
- added --freebind option (Linux only)
* 0.9.8.2 [20110719]
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
- spooler has been extremely improved
- new option --chown-socket
- added uwsgidecorators for elegant uwsgi api access from python
- the rack plugin is now stable
- support for embedding config and generic files in the server binary
- high-performance cache-server
- accept() is now locked on all threads in the same workers
- preliminary implementation of hooks in emperor
- support for C++ in server core
- tcp port auto-bind
- implemented workers, workerN and spooler signal target
- prefork/multithread uwsgi.signal_wait() implementation
- export uwsgi.node in WSGI vars
- new option --import (python plugin)
- support for unlimited number of Linux cgroups
- broodlord mode
*** june 2011 ***
* 0.9.8.1 [20110625]
- the build system has been improved
- various threading fixes
- fix python GIL status after reload
- new option --propagate-touch
- fixed uwsgi.sendfile
- fixed readline() support in wsgi.input
- fixed dynamic touch reload
- new option --logto2
- export %c in config files
- fixed libyaml support
- support passing modifiers in subscription system
- reset random seed in spooler
- subscribe from a list in a text file
- allow binding on port 0 (auto-assignment)
- reset random seed on grunt
- fix vhost mode for empty hostname
- fixed python3+virtualenv support
- tasks are now allowed to chdir() in spooler
- better zeromq+clustering support
- clustering has been refactored
- fixed rpc
- report correct worker id in cheap mode
- fixed a fd-leak in attach-daemon
- use setsid() in attach-daemon
- zerg mode
- added psgix.harakiri
- allows magic vars in sqlite3 config db
- added UWSGI_FASTROUTER_KEY var
- slowdown async-queue-is-full messages
- new option --cron
- --vassals-start-hook and --vassals-stop-hook
- the proxy plugin has been removed
* 0.9.8 [20110605]
- support for --callable in virtualhosting mode
- a NetBSD fix
- abstract unix socket can be prefixed with \0 (nginx-style)
- add /lib to the linker in sun-like systems
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
* 0.9.8-rc4 [20110602]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
- advanced build system with presets
- threading support
- emperor mode for massive auto-hosting
- caching subsystem
- message queue (even stacked) support
- improved server reloading system
- support for Linux Cgroups and Namespaces
- integrated upload progress
- Clustering infrastructure via multicast, broadcast or subscriptions
- support for attaching/monitoring external apps to the master process
- improved virtualhosting mode
- extremely improved Python support with better usage of multiple interpreters
- improved multiple apps support
- Production ready, evented HTTP router/proxy/load-balancer
- Production ready, evented uwsgi router/proxy/load-balancer
- new Erlang stack
- Internal signal subsystem
- support for RubyOnRails and Rack apps
- A huge series of fixes and optimizations
*** february 2011 ***
* 0.9.6.8 [20110207]
- fixed a bug when using --limit-as
- fixed a erlang buffer initialization
- added --ignore-sigpipe
- added --master-as-root
*** january 2011 ***
* 0.9.6.7 [20110130]
- a huge amount of async optimizations and fixes
- --logdate takes an optional strftime-like value
- follow $PATH on reloading
- uwsgi.core is exported in WSGI env
- uwsgi.log() respect for --logdate
- initial banner respect for --logdate
- fixed --post-buffering
- default listen backlog queue is now 100
- Python 3 support is no more marked as experimental
- Python 3.2 support
- new option --chroot-reload will force a reload of the uWSGI stack after a chroot
- fixed a typo in INI parsing
*** december 2010 ***
* 0.9.6.6 [20101230]
- support for YAML configuration files
- backported python module aliasing from 0.9.7-dev
- better apache2 module (support for SetEnv directive, fixed REQUEST_URI and improved connection handling)
- uwsgi.post_fork_hook implementation (to execute function after fork()) (thanks George Kollias)
- option --gid calls setgroups() after setgid() (thanks Jorge Cardona)
- fixed uGreen compilation (and uGreen is now built by default)
- fixed timeout and thundering herd problem in async modes (many thanks to Test157 for giving us a good async-test-app)
- disable TCP_INFO in older Linux kernels (thanks Bo Shi)
- enable TCP_INFO in FreeBSD (limited usage due to FreeBSD kernel support)
- fixed static virtualhosting mode using xml files (thanks Guido Notari of Link I.T. spa)
- new option --close-on-exec (thanks Jean-Baptiste Quenot)
- use HTTP_HOST var (and fallback to SERVER_NAME) in virtual hosting mode
- fixed a buffer overflow in automatic socket_name allocation (spotted by Riccardo Magliocchetti)
- Official support for Nexenta
*** september 2010 ***
* 0.9.6.5 [20100929]
- PEP 3333 support
- fix --pythonpath with --wsgi-file
- x-wsgiorg.uwsgi.version renamed to uwsgi.version
* 0.9.6.4 [20100925]
- fix a stupid bug in conditional logging backport
* 0.9.6.3 [20100925]
- fix a buffer overflow in .ini parsing (it throws a glibc error on malloc)
- backport of conditional logging from 0.9.7-dev
- backport of backlog queue monitor from 0.9.7-dev (only Linux)
* 0.9.6.2 [20100915]
- fix a regression in virtual hosting mode
- fix pythonpath usage in --ini and --ini-paste
- new uwsgi packet var: UWSGI_CHDIR
* 0.9.6.1 [20100912]
- print the request uri during SIGPIPE or HARAKIRI
- added SIGUSR2 support (it will print the current running request, if available)
- protocol parsing optimization
- fixed --logto support
- new --eval option allows inline definition of WSGI script
- support for defining WSGI script in xml using CDATA
- allow --pp as --pythonpath shortcut
- various spooler optimizations and fixes
- added -O2 optimization by default
- added uwsgi.is_a_reload commodity function
- .ini file support fix
- SNMP agent fix
- support for subprocesses generated by master
- fix a regression in SCRIPT_NAME handling
- Haiku official support
- gcc 2.95 support
- dynamic app management optimizations
- export x-wsgiorg.uwsgi.version in WSGI env
*** august 2010 ***
* 0.9.6 [20100829]
- better handling of SCRIPT_NAME
- vacuum option for deleting unix sockets and pidfiles after usage
- advanced XML configuration
- new configuration systems: INI files and LDAP
- embedded HTTP server for development/testing
- better signal handling
- PSGI plugin improved
- usability fixes and new commodities options for root startup
- grunt processes (detached workers)
- preliminary integrated virtualhosting mode
- new option catch-exceptions can redirect python exceptions to your browser
- logging improvements (--logto and --logdate options)
- Full PEP 333 compliant usage of wsgi.file_wrapper
- re-initialize random seed after every fork() [security fix]
- fix Spooler's usage of stdin
- export WSGI environment in uwsgi.env (for doing evil things)
- logsize tracking (uwsgi.logsize) for future embedded log rotation
*** july 2010 ***
* 0.9.5.4 [20100706]
*** june 2010 ***
* 0.9.5.3 [20100628]
- fixed linux x86_64 compilation (sorry)
* 0.9.5.2 [20100626] *
- fixed a request parsing bug
- applied debian fixes
- fixed multiple interpreter sys.argv
- improved --chmod-socket
- fixed uid 0 SIGHUP
- updated nginx and apache modules
- updated PSGI, lua and example plugin
- fixed --pyargv with python 3.x
- improved plugin build system
*** may 2010 ***
* 0.9.5.1 [20100519] *
- fixed paste support
- added a new modifier (22)
- full support for configuration via environment variables
- nginx_string option in nginx module
- fix for harakiri without master
- backported unladen swallow support for 0.9.6-dev
- fixed address space limit detection via getrlimit()
- http body buffering implementation
- added --prio option (to set priority)
- added --post-limit to limit the size of uploads
- added --logto option to allow udp logging without daemonizing
- applied Gentoo's packagers fixes for build system
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of the async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
- fix sendfile on 64bit
- include setup.py
*** february 2010 ***
* Maintenance release *
- better support for NetBSD
- threading fix for FreeBSD
- sendfile portability fixes
- new makefiles
- example app for testing static file serving
- fixes for ROCK_SOLID mode
*** january 2010 ***
- Integrated Spooler
- better error management
- long options
- clustering functions
- experimental lighttpd module
- official support for OpenBSD and OpenSolaris
- FastFuncs
- new functions for embedded module
- reliable harakiri
- better Makefiles
- python threads support in master process
- proper timeout handling in apache2 module
- endianess fixes all over the place
- paste support
- Django app for managing and monitoring the uWSGI server
- options for changin uid/gid and chrooting when run by root
- lot of bugfixes and optimizations
*** 20091129 Version 0.9.3 ***
- Nginx 0.7.x module
- configuration via python module
- support (non-standard) for Python 3.x
- Twisted client resource adapter
- graceful restart of worker processes and hot-plug substitution/upgrade of the uWSGI server
- shared memory area to share data between workers/processes
- Tomcat handler
- support for virtualenv
- tons of bugfixes and optimizations
*** 20090829 Version 0.9.2 ***
- TCP support
- configurable internal timeout (socket/poll)
- Cherokee handler
- code refactoring
- Makefiles
- customizable harakiri handler (put an harakiri(environ, start_response) function in your wsgi script)
- limit requests per worker
- a lot of bugfix and optimizations
+3
View File
@@ -3,3 +3,6 @@ all:
clean:
python uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
+1 -1
View File
@@ -1,3 +1,3 @@
surprise i am empty !
Look in the online documentation on http://projects.unbit.it/uwsgi/
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
+69 -45
View File
@@ -1,3 +1,38 @@
/*
*** mod_proxy_uwsgi ***
Copyright 2009-2013 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
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
To build:
apxs2 -i -c mod_proxy_uwsgi.c
To use:
LoadModule proxy_uwsgi_module /usr/lib/apache2/modules/mod_proxy_uwsgi.so
ProxyPass / uwsgi://127.0.0.1:3031/
Docs:
http://uwsgi-docs.readthedocs.org/en/latest/Apache.html#mod-proxy-uwsgi
*/
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_strings.h"
@@ -101,10 +136,26 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
ap_add_common_vars(r);
ap_add_cgi_vars(r);
// this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
// and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
// files you have higher problems...
const char *auth = apr_table_get(r->headers_in, "Authorization");
if (auth) {
apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
}
const char *script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
const char *path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
if (script_name && path_info) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
if (strcmp(path_info, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
}
else {
if (!strcmp(script_name, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", "");
}
}
}
env_table = apr_table_elts(r->subprocess_env);
@@ -135,7 +186,7 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
buf[0] = 0;
buf[1] = (uint8_t) (pktsize & 0xff);
buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
buf[0] = 0;
buf[3] = 0;
return uwsgi_send(conn, buf, headerlen, r);
}
@@ -166,28 +217,6 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
return OK;
}
static
apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r,
int fold, int *writen)
{
char *tmp_s = s;
apr_status_t rv;
apr_size_t len;
rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb);
apr_brigade_cleanup(bb);
if (rv == APR_SUCCESS) {
*writen = (int) len;
} else if (rv == APR_ENOSPC) {
*writen = n;
} else {
*writen = -1;
}
return rv;
}
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
{
@@ -207,11 +236,7 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
if (len == 0) {
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
}
len = ap_getline(buffer, sizeof(buffer), rp, 1);
if (len <= 0) {
// oops
@@ -220,25 +245,11 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
backend->worker->s->read += len;
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*") || len >= sizeof(buffer)-1) {
// oops
return HTTP_INTERNAL_SERVER_ERROR;
}
int major, minor;
major = buffer[5] - '0';
minor = buffer[7] - '0';
/* If not an HTTP/1 message or
* if the status line was > 8192 bytes
*/
if ((major != 1) || (len >= sizeof(buffer)-1)) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
apr_pstrcat(r->pool, "Corrupt status line returned by remote "
"server: ", buffer, NULL));
}
char keepchar = buffer[12];
buffer[12] = '\0';
r->status = atoi(&buffer[9]);
@@ -326,7 +337,20 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
apr_table_add(r->subprocess_env, "PATH_INFO", url+strlen(worker->name));
size_t w_len = strlen(worker->name);
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
delta = 1;
}
int decode_status = ap_unescape_url(url+w_len-delta);
if (decode_status) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"unable to decode uri: %s",
url+w_len-delta);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
/* Create space for state information */
+1 -1
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2013 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
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby
cmd = File.expand_path "#{File.dirname(__FILE__)}/../ext/uwsgi/uwsgi.ruby"
exec(cmd, *ARGV)
+2 -8
View File
@@ -6,18 +6,12 @@ json = auto
sqlite3 = auto
zeromq = auto
snmp = true
spooler = true
embedded = true
ssl = auto
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
@@ -29,7 +23,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, router_rewrite, router_http
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter
as_shared_library = false
locking = auto
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
inherit = base
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python
main_plugin = python,gevent
inherit = base
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
main_plugin = go
inherit = base
bin_name = libuwsgi.so
as_shared_library = true
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = jvm,jwsgi
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = mono
inherit = base
-30
View File
@@ -1,30 +0,0 @@
[uwsgi]
xml = true
ini = true
snmp = true
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
-29
View File
@@ -1,29 +0,0 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = jvm,ring
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin =
inherit = base
+1 -9
View File
@@ -5,18 +5,10 @@ yaml = true
json = false
sqlite3 = false
zeromq = false
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
ldap = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
-44
View File
@@ -1,44 +0,0 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+4 -1
View File
@@ -1,12 +1,15 @@
use POSIX;
use IO::Socket::INET;
use IO::Socket::INET6;
use IO::Socket::UNIX;
my $s = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 1717, Proto => 'tcp', Reuse => 1);
my $s2 = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 3022, Proto => 'tcp', Reuse => 1);
my $s3 = IO::Socket::INET6->new(LocalAddr => '::', LocalPort => 3017, Proto => 'tcp', Reuse => 1);
my $s4 = IO::Socket::UNIX->new(Local => '/tmp/u.sock', Listen => 1);
dup2($s->fileno, 17);
dup2($s2->fileno, 22);
dup2($s3->fileno, 30);
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30';
dup2($s4->fileno, 0);
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30','--stats',':5001';
View File
+342
View File
@@ -0,0 +1,342 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
// generate a uwsgi signal on alarm
void uwsgi_alarm_init_signal(struct uwsgi_alarm_instance *uai) {
uai->data8 = atoi(uai->arg);
}
void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
uwsgi_route_signal(uai->data8);
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
}
void uwsgi_alarm_func_cmd(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
int pipe[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe)) {
return;
}
uwsgi_socket_nb(pipe[0]);
uwsgi_socket_nb(pipe[1]);
if (write(pipe[1], msg, len) != (ssize_t) len) {
close(pipe[0]);
close(pipe[1]);
return;
}
uwsgi_run_command(uai->data_ptr, pipe, -1);
close(pipe[0]);
close(pipe[1]);
}
// pass the log line to a mule
void uwsgi_alarm_init_mule(struct uwsgi_alarm_instance *uai) {
uai->data32 = atoi(uai->arg);
if (uai->data32 > (uint32_t) uwsgi.mules_cnt) {
uwsgi_log_alarm("] invalid mule_id (%d mules available), fallback to 0\n", uwsgi.mules_cnt);
uai->data32 = 0;
}
}
void uwsgi_alarm_func_mule(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
// skip if mules are not available
if (uwsgi.mules_cnt == 0)
return;
int fd = uwsgi.shared->mule_queue_pipe[0];
if (uai->data32 > 0) {
int mule_id = uai->data32 - 1;
fd = uwsgi.mules[mule_id].queue_pipe[0];
}
mule_send_msg(fd, msg, len);
}
// register a new alarm
void uwsgi_register_alarm(char *name, void (*init) (struct uwsgi_alarm_instance *), void (*func) (struct uwsgi_alarm_instance *, char *, size_t)) {
struct uwsgi_alarm *old_ua = NULL, *ua = uwsgi.alarms;
while (ua) {
// skip already initialized alarms
if (!strcmp(ua->name, name)) {
return;
}
old_ua = ua;
ua = ua->next;
}
ua = uwsgi_calloc(sizeof(struct uwsgi_alarm));
ua->name = name;
ua->init = init;
ua->func = func;
if (old_ua) {
old_ua->next = ua;
}
else {
uwsgi.alarms = ua;
}
}
// register embedded alarms
void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
struct uwsgi_alarm *ua = uwsgi.alarms;
while (ua) {
if (!strcmp(ua->name, plugin)) {
break;
}
ua = ua->next;
}
if (!ua)
return -1;
struct uwsgi_alarm_instance *old_uai = NULL, *uai = uwsgi.alarm_instances;
while (uai) {
old_uai = uai;
uai = uai->next;
}
uai = uwsgi_calloc(sizeof(struct uwsgi_alarm_instance));
uai->name = name;
uai->alarm = ua;
uai->arg = arg;
uai->last_msg = uwsgi_malloc(uwsgi.log_master_bufsize);
if (old_uai) {
old_uai->next = uai;
}
else {
uwsgi.alarm_instances = uai;
}
ua->init(uai);
return 0;
}
// get an alarm instance by its name
static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
struct uwsgi_alarm_instance *uai = uwsgi.alarm_instances;
while (uai) {
if (!strcmp(name, uai->name)) {
return uai;
}
uai = uai->next;
}
return NULL;
}
#ifdef UWSGI_PCRE
static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
while (ual) {
old_ual = ual;
ual = ual->next;
}
ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
return -1;
}
ual->negate = negate;
if (old_ual) {
old_ual->next = ual;
}
else {
uwsgi.alarm_logs = ual;
}
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while (p) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) {
free(list);
return -1;
}
struct uwsgi_alarm_ll *old_uall = NULL, *uall = ual->alarms;
while (uall) {
old_uall = uall;
uall = uall->next;
}
uall = uwsgi_calloc(sizeof(struct uwsgi_alarm_ll));
uall->alarm = uai;
if (old_uall) {
old_uall->next = uall;
}
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
free(list);
return 0;
}
#endif
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
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);
}
}
}
free(buf);
}
// initialize alarms, instances and log regexps
void uwsgi_alarms_init() {
if (!uwsgi.master_process) return;
// first of all, create instance of alarms
struct uwsgi_string_list *usl = uwsgi.alarm_list;
while (usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *plugin = space + 1;
char *colon = strchr(plugin, ':');
if (!colon) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*colon = 0;
char *arg = colon + 1;
// here the alarm is mapped to a name and initialized
if (uwsgi_alarm_add(line, plugin, arg)) {
uwsgi_log("invalid alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
if (!uwsgi.alarm_instances) return;
#ifdef UWSGI_PCRE
// then map log-alarm
usl = uwsgi.alarm_logs_list;
while (usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid log-alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *regexp = space + 1;
// here the log-alarm is created
if (uwsgi_alarm_log_add(line, regexp, usl->custom)) {
uwsgi_log("invalid log-alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
#endif
}
void uwsgi_alarm_thread_start() {
if (!uwsgi.alarm_instances) return;
// start the alarm_thread
uwsgi.alarm_thread = uwsgi_thread_new(uwsgi_alarm_thread_loop);
if (!uwsgi.alarm_thread) {
uwsgi_log("unable to spawn alarm thread\n");
exit(1);
}
}
#ifdef UWSGI_PCRE
// check if a log should raise an alarm
void uwsgi_alarm_log_check(char *msg, size_t len) {
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12))
return;
struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
while (ual) {
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
if (!ual->negate) {
uwsgi_alarm_log_run(ual, msg, len);
}
else {
break;
}
}
ual = ual->next;
}
}
#endif
// call the alarm func
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
time_t now = uwsgi_now();
// avoid alarm storming/loop if last message is the same
if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) {
if (now - uai->last_run < uwsgi.alarm_freq)
return;
}
uai->alarm->func(uai, msg, len);
uai->last_run = uwsgi_now();
memcpy(uai->last_msg, msg, len);
uai->last_msg_size = len;
}
#ifdef UWSGI_PCRE
// call the alarms mapped to a log line
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
struct uwsgi_alarm_ll *uall = ual->alarms;
while (uall) {
uwsgi_alarm_run(uall->alarm, msg, len);
uall = uall->next;
}
}
#endif
// this is the api function workers,mules and whatever you want can call from code
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
if (!uwsgi.alarm_thread) return;
if (len > uwsgi.alarm_msg_size) return;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
if (!uai) return;
struct iovec iov[2];
iov[0].iov_base = &uai;
iov[0].iov_len = sizeof(long);
iov[1].iov_base = msg;
iov[1].iov_len = len;
// now send the message to the alarm thread
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
}
}
+174 -152
View File
@@ -1,27 +1,34 @@
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
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");
uwsgi.async_queue_is_full = now;
}
}
void uwsgi_async_init() {
int i;
uwsgi.async_queue = event_queue_init();
if (uwsgi.async_queue < 0) {
exit(1);
}
if (uwsgi.async_queue < 0) {
exit(1);
}
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
@@ -33,51 +40,51 @@ struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
void runqueue_remove(struct uwsgi_async_request *u_request) {
static void runqueue_remove(struct uwsgi_async_request *u_request) {
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (parent) {
parent->next = child;
}
if (child) {
child->prev = parent;
}
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
if (u_request == uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last = parent;
}
free(u_request);
free(u_request);
uwsgi.async_runqueue_cnt--;
}
void runqueue_push(struct wsgi_request *wsgi_req) {
static void runqueue_push(struct wsgi_request *wsgi_req) {
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
uwsgi.async_runqueue_cnt++;
@@ -96,30 +103,30 @@ struct wsgi_request *find_first_available_wsgi_req() {
return wsgi_req;
}
void async_expire_timeouts() {
static void async_expire_timeouts(uint64_t now) {
struct wsgi_request *wsgi_req;
time_t current_time = uwsgi_now();
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for(;;) {
for (;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (urbt == NULL) return;
if (urbt == NULL)
return;
if (urbt->key <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
if (urbt->value <= now) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while(uaf) {
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
@@ -129,22 +136,23 @@ void async_expire_timeouts() {
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
continue;
}
break;
}
break;
}
}
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
if (fd < 0)
return -1;
// find first slot
while(uad) {
while (uad) {
last_uad = uad;
uad = uad->next;
}
@@ -166,57 +174,93 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_read(uwsgi.async_queue, fd);
wsgi_req->async_force_again = 1;
return event_queue_add_fd_read(uwsgi.async_queue, fd);
}
static int async_wait_fd_read(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
if (async_add_fd_read(wsgi_req, fd, timeout)) {
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;
}
return 1;
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now()+timeout, wsgi_req);
}
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
}
}
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0) return ;
if (fd < 0)
return -1;
// find first slot
while(uad) {
last_uad = uad;
uad = uad->next;
}
// find first slot
while (uad) {
last_uad = uad;
uad = uad->next;
}
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
uad->fd = fd;
uad->event = event_queue_write();
uad->prev = last_uad;
uad->next = NULL;
uad->prev = last_uad;
uad->next = NULL;
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (last_uad) {
last_uad->next = uad;
}
else {
wsgi_req->waiting_fds = uad;
}
if (timeout > 0) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
event_queue_add_fd_write(uwsgi.async_queue, fd);
wsgi_req->async_force_again = 1;
return event_queue_add_fd_write(uwsgi.async_queue, fd);
}
static int async_wait_fd_write(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
if (async_add_fd_write(wsgi_req, fd, timeout)) {
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;
}
return 1;
}
void async_schedule_to_req(void) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
}
void *async_loop(void *arg1) {
void async_loop() {
if (uwsgi.async < 2) {
uwsgi_log("the async loop engine requires async mode (--async <n>)\n");
exit(1);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
@@ -225,7 +269,7 @@ void *async_loop(void *arg1) {
int is_a_new_connection;
int proto_parser_status;
time_t now, last_now = 0;
uint64_t now;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
@@ -235,52 +279,59 @@ void *async_loop(void *arg1) {
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;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.my_signal_socket);
}
// set a default request manager
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_req)
uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_main) {
uwsgi_log("*** WARNING *** 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) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - uwsgi_now();
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
}
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (min_timeout) {
timeout = min_timeout->value - now;
if (timeout <= 0) {
async_expire_timeouts(now);
timeout = 0;
}
}
else {
timeout = -1;
}
}
}
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
now = (uint64_t) uwsgi_now();
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts();
async_expire_timeouts(now);
}
for(i=0;i<uwsgi.async_nevents;i++) {
for (i = 0; i < uwsgi.async_nevents; i++) {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
continue;
}
}
is_a_new_connection = 0;
@@ -288,47 +339,24 @@ void *async_loop(void *arg1) {
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
is_a_new_connection = 1;
is_a_new_connection = 1;
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
now = uwsgi_now();
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
uwsgi_async_queue_is_full((time_t)now);
break;
}
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
/* re-set blocking socket */
int arg = uwsgi_sock->arg;
arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
uwsgi.async_queue_unused_ptr++;
@@ -352,16 +380,14 @@ void *async_loop(void *arg1) {
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
// remove fd from event poll and fd proto table
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
@@ -387,27 +413,27 @@ void *async_loop(void *arg1) {
}
// remove all the fd monitors and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
// avoid managing other enqueued events...
break;
}
}
@@ -426,20 +452,18 @@ void *async_loop(void *arg1) {
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove all the monitored fds and timeout
while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
@@ -453,7 +477,7 @@ void *async_loop(void *arg1) {
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from suspended list
// remove this request from suspended list
runqueue_remove(current_request);
}
@@ -464,6 +488,4 @@ void *async_loop(void *arg1) {
}
return NULL;
}
+269 -7
View File
@@ -10,7 +10,87 @@ struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
ub->len = len;
}
return ub;
}
int uwsgi_buffer_fix(struct uwsgi_buffer *ub, size_t len) {
if (ub->limit > 0 && len > ub->limit)
return -1;
if (ub->len < len) {
char *new_buf = realloc(ub->buf, len);
if (!new_buf) {
uwsgi_error("uwsgi_buffer_fix()");
return -1;
}
ub->buf = new_buf;
ub->len = len;
}
return 0;
}
int uwsgi_buffer_ensure(struct uwsgi_buffer *ub, size_t len) {
size_t remains = ub->len - ub->pos;
if (remains < len) {
size_t new_len = ub->len + (len - remains);
if (ub->limit > 0 && new_len > ub->limit) {
new_len = ub->limit;
if (new_len == ub->len)
return -1;
}
char *new_buf = realloc(ub->buf, new_len);
if (!new_buf) {
uwsgi_error("uwsgi_buffer_ensure()");
return -1;
}
ub->buf = new_buf;
ub->len = new_len;
}
return 0;
}
int uwsgi_buffer_insert(struct uwsgi_buffer *ub, size_t pos, char *buf, size_t len) {
size_t to_move = (ub->pos-pos);
if (uwsgi_buffer_ensure(ub, len)) return -1;
memmove(ub->buf+pos+len, ub->buf+pos, to_move);
memcpy(ub->buf+pos, buf, len);
ub->pos += len;
return 0;
}
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) {
return -1;
}
return uwsgi_buffer_insert(ub, pos, chunked, ret);
}
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) {
return -1;
}
return uwsgi_buffer_append(ub, chunked, ret);
}
int uwsgi_buffer_decapitate(struct uwsgi_buffer *ub, size_t len) {
if (len > ub->pos) return -1;
memmove(ub->buf, ub->buf + len, ub->pos-len);
ub->pos = ub->pos-len;
return 0;
}
int uwsgi_buffer_byte(struct uwsgi_buffer *ub, char byte) {
return uwsgi_buffer_append(ub, &byte, 1);
}
int uwsgi_buffer_u8(struct uwsgi_buffer *ub, uint8_t u8) {
return uwsgi_buffer_append(ub, (char *) &u8, 1);
}
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
@@ -18,11 +98,22 @@ int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
size_t remains = ub->len - ub->pos;
if (len > remains) {
char *new_buf = realloc(ub->buf, ub->len + UMAX(len, (size_t) uwsgi.page_size));
size_t chunk_size = UMAX(len, (size_t) uwsgi.page_size);
if (ub->limit > 0 && ub->len + chunk_size > ub->limit) {
// retry with another minimal size
if (len < (size_t) uwsgi.page_size) {
chunk_size = len;
}
if (ub->len + chunk_size > ub->limit)
return -1;
}
char *new_buf = realloc(ub->buf, ub->len + chunk_size);
if (!new_buf) {
uwsgi_error("realloc()");
uwsgi_error("uwsgi_buffer_append()");
return -1;
}
ub->buf = new_buf;
ub->len += chunk_size;
}
memcpy(ub->buf + ub->pos, buf, len);
@@ -30,28 +121,190 @@ int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
return 0;
}
int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
// need to escape \ and "
size_t i;
for(i=0;i<len;i++) {
if (buf[i] == '"') {
if (uwsgi_buffer_append(ub, "\\\"", 2)) return -1;
}
else if (buf[i] == '\\') {
if (uwsgi_buffer_append(ub, "\\\\", 2)) return -1;
}
else {
if (uwsgi_buffer_append(ub, buf+i, 1)) return -1;
}
}
return 0;
}
int uwsgi_buffer_u16le(struct uwsgi_buffer *ub, uint16_t num) {
uint8_t buf[2];
buf[0] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 2);
}
int uwsgi_buffer_u16be(struct uwsgi_buffer *ub, uint16_t num) {
uint8_t buf[2];
buf[1] = (uint8_t) (num & 0xff);
buf[0] = (uint8_t) ((num >> 8) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 2);
}
int uwsgi_buffer_u24be(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[3];
buf[2] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[0] = (uint8_t) ((num >> 16) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 3);
}
int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[4];
buf[3] = (uint8_t) (num & 0xff);
buf[2] = (uint8_t) ((num >> 8) & 0xff);
buf[1] = (uint8_t) ((num >> 16) & 0xff);
buf[0] = (uint8_t) ((num >> 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);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[2] = (uint8_t) ((num >> 16) & 0xff);
buf[3] = (uint8_t) ((num >> 24) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
uint8_t buf[8];
buf[7] = (uint8_t) (num & 0xff);
buf[6] = (uint8_t) ((num >> 8) & 0xff);
buf[5] = (uint8_t) ((num >> 16) & 0xff);
buf[4] = (uint8_t) ((num >> 24) & 0xff);
buf[3] = (uint8_t) ((num >> 32) & 0xff);
buf[2] = (uint8_t) ((num >> 40) & 0xff);
buf[1] = (uint8_t) ((num >> 48) & 0xff);
buf[0] = (uint8_t) ((num >> 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];
if (!inet_ntop(AF_INET, addr, ip, INET_ADDRSTRLEN)) {
uwsgi_error("uwsgi_buffer_append_ipv4() -> inet_ntop()");
return -1;
}
return uwsgi_buffer_append(ub, ip, strlen(ip));
}
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
}
int uwsgi_buffer_append_keyval(struct uwsgi_buffer *ub, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, vallen)) return -1;
return uwsgi_buffer_append(ub, val, vallen);
}
int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t keylen, char *val, uint32_t vallen) {
if (uwsgi_buffer_u32be(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u32be(ub, vallen)) return -1;
return uwsgi_buffer_append(ub, val, vallen);
}
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)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, ret)) return -1;
return uwsgi_buffer_append(ub, buf, ret);
}
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)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, ret)) return -1;
return uwsgi_buffer_append(ub, buf, ret);
}
int uwsgi_buffer_append_keyipv4(struct uwsgi_buffer *ub, char *key, uint16_t keylen, void *addr) {
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, 15)) return -1;
char *ptr = ub->buf + (ub->pos - 2);
if (uwsgi_buffer_append_ipv4(ub, addr)) return -1;
// fix the size
*ptr = ((ub->buf+ub->pos) - (ptr+2));
return 0;
}
int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
size_t b64_len = 0;
char *b64 = uwsgi_base64_encode(s, len, &b64_len);
if (!b64) return -1;
int ret = uwsgi_buffer_append(ub, b64, b64_len);
free(b64);
return ret;
}
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
if (ub->buf) free(ub->buf);
if (ub->buf)
free(ub->buf);
free(ub);
}
ssize_t uwsgi_buffer_write_simple(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
size_t remains = ub->pos;
while(remains) {
ssize_t len = write(wsgi_req->fd, ub->buf + (ub->pos - remains), remains);
if (len <= 0) {
return len;
}
remains -= len;
}
return ub->pos;
}
int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
size_t remains = ub->pos;
char *ptr = ub->buf;
while(remains > 0) {
while (remains > 0) {
int ret = uwsgi_waitfd_write(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len > 0) {
ptr += len;
remains -= len;
}
}
else if (len == 0) {
return -1;
}
else {
uwsgi_error("write()");
uwsgi_error("uwsgi_buffer_send()");
return -1;
}
}
@@ -66,3 +319,12 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
return 0;
}
int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modifier2) {
if (ub->pos < 4) return -1;
ub->buf[0] = modifier1;
ub->buf[1] = (uint8_t) ((ub->pos - 4) & 0xff);
ub->buf[2] = (uint8_t) (((ub->pos - 4) >> 8) & 0xff);
ub->buf[3] = modifier2;
return 0;
}
+1507 -253
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -4,11 +4,11 @@ extern struct uwsgi_server uwsgi;
// in the future we will need to use the best clock source for each os/system
time_t uwsgi_now() {
return uwsgi.clock->seconds();
return uwsgi.clock->seconds();
}
uint64_t uwsgi_micros() {
return uwsgi.clock->microseconds();
return uwsgi.clock->microseconds();
}
@@ -22,7 +22,7 @@ void uwsgi_register_clock(struct uwsgi_clock *clock) {
return;
}
while(clocks) {
while (clocks) {
if (!clocks->next) {
clocks->next = clock;
return;
@@ -33,7 +33,7 @@ void uwsgi_register_clock(struct uwsgi_clock *clock) {
void uwsgi_set_clock(char *name) {
struct uwsgi_clock *clocks = uwsgi.clocks;
while(clocks) {
while (clocks) {
if (!strcmp(name, clocks->name)) {
uwsgi.clock = clocks;
return;
-464
View File
@@ -1,464 +0,0 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = uwsgi_now();
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = uwsgi_now();
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
void manage_cluster_message(char *cluster_opt_buf, int cluster_opt_size) {
struct uwsgi_cluster_node nucn;
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
case 95:
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
#endif
uwsgi_hooked_parse(uwsgi.workers[0].cores[0].req.buffer, uwsgi.workers[0].cores[0].req.uh.pktsize, manage_cluster_announce, &nucn);
if (nucn.name[0] != 0) {
uwsgi_cluster_add_node(&nucn, CLUSTER_NODE_DYNAMIC);
}
break;
case 96:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.wsgi_requests[0]->uh.pktsize);
#endif
uwsgi_log_verbose("%.*s\n", uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
case 98:
if (kill(getpid(), SIGHUP)) {
uwsgi_error("kill()");
}
break;
case 99:
if (uwsgi.cluster_nodes)
break;
if (uwsgi.workers[0].cores[0].req.uh.modifier2 == 0) {
uwsgi_log("requested configuration data, sending %d bytes\n", cluster_opt_size);
sendto(uwsgi.cluster_fd, cluster_opt_buf, cluster_opt_size, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr));
}
break;
case 73:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
#endif
uwsgi_log_verbose("[uWSGI cluster %s] new node available: %.*s\n", uwsgi.cluster, uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
}
}
#endif
char *uwsgi_setup_clusterbuf(size_t *size) {
size_t cluster_opt_size = 4;
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->key);
if (uwsgi.exported_opts[i]->value) {
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->value);
}
else {
cluster_opt_size += 2 + 1;
}
}
//uwsgi_log("cluster opts size: %d\n", cluster_opt_size);
char *cluster_opt_buf = uwsgi_malloc(cluster_opt_size);
struct uwsgi_header *uh = (struct uwsgi_header *) cluster_opt_buf;
uh->modifier1 = 99;
uh->pktsize = cluster_opt_size - 4;
uh->modifier2 = 1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
char *cptrbuf = cluster_opt_buf + 4;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
uint16_t ustrlen = strlen(uwsgi.exported_opts[i]->key);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->key, ustrlen);
cptrbuf += ustrlen;
if (uwsgi.exported_opts[i]->value) {
ustrlen = strlen(uwsgi.exported_opts[i]->value);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->value, ustrlen);
}
else {
ustrlen = 1;
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
*cptrbuf = '1';
}
cptrbuf += ustrlen;
}
return cluster_opt_buf;
}
+312
View File
@@ -0,0 +1,312 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
/*
External uwsgi daemons
There are 3 kind of daemons (read: external applications) that can be managed
by uWSGI.
1) dumb daemons (attached with --attach-daemon)
they must not daemonize() and when they exit() the master is notified (via waitpid)
and the process is respawned
2) smart daemons with daemonization
you specify a pidfile and a command
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
the daemon is respawned
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
the daemon is respawned
3) smart daemons without daemonization
same as 2, but the daemonization and pidfile creation is managed by uWSGI
status:
0 -> never started
1 -> just started
2 -> started and monitored (only in pidfile based)
*/
void uwsgi_daemons_smart_check() {
static time_t last_run = 0;
time_t now = uwsgi_now();
if (now - last_run <= 0) {
return;
}
last_run = now;
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
// monitored instance
if (ud->status == 2) {
uwsgi_spawn_daemon(ud);
}
else {
ud->pidfile_checks++;
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
uwsgi_spawn_daemon(ud);
}
}
}
else if (checked_pid != ud->pid) {
uwsgi_log("[uwsgi-daemons] found changed pid for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
ud->pid = checked_pid;
}
// all ok, pidfile and process found
else {
ud->status = 2;
}
}
ud = ud->next;
}
}
// this function is called when a dumb daemon dies and we do not wat to respawn it
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
return -1;
}
ud = ud->next;
}
return 0;
}
// this function is called when a dumb daemon dies and we want to respawn it
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_spawn_daemon(ud);
return 1;
}
ud = ud->next;
}
return 0;
}
int uwsgi_check_pidfile(char *filename) {
struct stat st;
pid_t ret = -1;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
goto end;
}
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
goto end2;
}
char *pidstr = uwsgi_calloc(st.st_size + 1);
if (read(fd, pidstr, st.st_size) != st.st_size) {
uwsgi_error("read()");
goto end3;
}
pid_t pid = atoi(pidstr);
if (pid <= 0)
goto end3;
if (!kill(pid, 0)) {
ret = pid;
}
end3:
free(pidstr);
end2:
close(fd);
end:
return ret;
}
void uwsgi_daemons_spawn_all() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (!ud->registered) {
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
uwsgi_spawn_daemon(ud);
}
else {
ud->pid = checked_pid;
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
}
}
else {
uwsgi_spawn_daemon(ud);
}
ud->registered = 1;
}
ud = ud->next;
}
}
void uwsgi_detach_daemons() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid > 0 && !ud->pidfile)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
}
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
}
pid_t pid = uwsgi_fork("uWSGI external daemon");
if (pid < 0) {
uwsgi_error("fork()");
return;
}
if (pid > 0) {
ud->pid = pid;
ud->status = 1;
ud->pidfile_checks = 0;
if (ud->respawns == 0) {
ud->born = uwsgi_now();
}
ud->respawns++;
ud->last_spawn = uwsgi_now();
}
else {
// close uwsgi sockets
uwsgi_close_all_sockets();
uwsgi_close_all_fds();
if (ud->daemonize) {
/* refork... */
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid != 0) {
_exit(0);
}
uwsgi_write_pidfile(ud->pidfile);
}
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
if (setsid() < 0) {
uwsgi_error("setsid()");
exit(1);
}
if (!ud->pidfile) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
}
if (throttle) {
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
sleep(throttle);
}
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
uwsgi_exec_command_with_args(ud->command);
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
// never here;
exit(1);
}
return;
}
void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
char *pidfile = NULL;
int daemonize = 0;
int freq = 10;
char *command = uwsgi_str(value);
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
char *space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
exit(1);
}
*space = 0;
pidfile = command;
// check for freq
char *comma = strchr(pidfile, ',');
if (comma) {
*comma = 0;
freq = atoi(comma + 1);
}
command = space + 1;
if (!strcmp(opt, "smart-attach-daemon2")) {
daemonize = 1;
}
}
if (!uwsgi_ud) {
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
uwsgi_ud = uwsgi.daemons;
}
else {
while (uwsgi_ud) {
old_ud = uwsgi_ud;
uwsgi_ud = uwsgi_ud->next;
}
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
old_ud->next = uwsgi_ud;
}
uwsgi_ud->command = command;
uwsgi_ud->pid = 0;
uwsgi_ud->status = 0;
uwsgi_ud->freq = freq;
uwsgi_ud->registered = 0;
uwsgi_ud->next = NULL;
uwsgi_ud->respawns = 0;
uwsgi_ud->last_spawn = 0;
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi.daemons_cnt++;
}
+282 -144
View File
@@ -6,7 +6,6 @@ a supervisor for multiple uWSGI instances
*/
#include "uwsgi.h"
#include <glob.h>
extern struct uwsgi_server uwsgi;
@@ -88,7 +87,7 @@ void uwsgi_emperor_blacklist_add(char *id) {
}
}
strcpy(uebi->id, id);
strncpy(uebi->id, id, 0xff);
gettimeofday(&uebi->first_attempt, NULL);
memcpy(&uebi->last_attempt, &uebi->first_attempt, sizeof(struct timeval));
uebi->throttle_level = uwsgi.emperor_throttle;
@@ -125,17 +124,12 @@ struct uwsgi_emperor_scanner *emperor_scanners;
int uwsgi_emperor_is_valid(char *name) {
if (uwsgi_endswith(name, ".xml") ||
uwsgi_endswith(name, ".ini") ||
uwsgi_endswith(name, ".yml") ||
uwsgi_endswith(name, ".yaml") ||
uwsgi_endswith(name, ".js") ||
uwsgi_endswith(name, ".json")) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
if (strlen(name) < 0xff) {
return 1;
}
if (strlen(name) < 0xff) {
return 1;
}
}
return 0;
@@ -155,48 +149,64 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
DIR *dir = opendir(".");
while ((de = readdir(dir)) != NULL) {
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (stat(de->d_name, &st))
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (!S_ISREG(st.st_mode))
continue;
ui_current = emperor_get(de->d_name);
ui_current = emperor_get(de->d_name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
continue;
}
}
else {
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
closedir(dir);
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
if (c_ui->zerg) {
char *colon = strrchr(c_ui->name, ':');
if (!colon) {
emperor_stop(c_ui);
}
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
c_ui = c_ui->ui_next;
}
c_ui = c_ui->ui_next;
}
}
// this is the monitor for glob patterns
@@ -213,50 +223,66 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
}
for (i = 0; i < (int) g.gl_pathc; i++) {
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
ui_current = emperor_get(g.gl_pathv[i]);
if (!S_ISREG(st.st_mode))
continue;
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
continue;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
ui_current = emperor_get(g.gl_pathv[i]);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
continue;
}
}
else {
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
// check if mtime is changed and the uWSGI instance must be reloaded
if (st.st_mtime > ui_current->last_mod) {
emperor_respawn(ui_current, st.st_mtime);
}
}
else {
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
globfree(&g);
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
while (c_ui) {
if (c_ui->scanner == ues) {
if (c_ui->zerg) {
char *colon = strrchr(c_ui->name, ':');
if (!colon) {
emperor_stop(c_ui);
}
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
free(filename);
}
}
}
c_ui = c_ui->ui_next;
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
c_ui = c_ui->ui_next;
}
}
@@ -308,7 +334,7 @@ static void royal_death(int signum) {
}
}
uwsgi_log("[emperor] *** RAGNAROK EVOKED ***\n");
uwsgi_log("[emperor] *** RAGNAROK EVOKED ***\n");
uwsgi_notify("The Emperor is buried.");
exit(0);
}
@@ -330,7 +356,7 @@ static void emperor_stats() {
while (c_ui) {
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n", c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
uwsgi_log("vassal instance %s (last modified %lld) status %d loyal %d zerg %d\n", c_ui->name, (long long) c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
c_ui = c_ui->ui_next;
}
@@ -422,18 +448,29 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
struct uwsgi_header uh;
// reload the uWSGI instance
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
// push the config to the config pipe (if needed)
if (c_ui->use_config) {
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
uh.modifier1 = 115;
uh.pktsize = c_ui->config_len;
uh.modifier2 = 0;
if (write(c_ui->pipe_config[0], &uh, 4) != 4) {
uwsgi_error("[uwsgi-emperor] write() header config");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
else {
if (write(c_ui->pipe_config[0], c_ui->config, c_ui->config_len) != (long) c_ui->config_len) {
uwsgi_error("[uwsgi-emperor] write() config");
}
}
}
c_ui->respawns++;
c_ui->last_mod = mod;
c_ui->last_run = uwsgi_now();
@@ -459,7 +496,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
#endif
if (strlen(name) > (0xff - 1)) {
uwsgi_log("[emperor] invalid vassal name\n", name);
uwsgi_log("[emperor] invalid vassal name: %s\n", name);
return;
}
@@ -498,7 +535,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
uwsgi_log("[emperor-tyrant] invalid permissions for vassal %s\n", name);
return;
}
}
@@ -554,6 +591,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
if (n_ui->zerg) {
uwsgi.emperor_broodlord_num++;
}
// TODO pre-start hook
// a new uWSGI instance will start
@@ -570,10 +611,19 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
if (n_ui->use_config) {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
struct uwsgi_header uh;
uh.modifier1 = 115;
uh.pktsize = n_ui->config_len;
uh.modifier2 = 0;
if (write(n_ui->pipe_config[0], &uh, 4) != 4) {
uwsgi_error("[uwsgi-emperor] write() header config");
}
else {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) != (long) n_ui->config_len) {
uwsgi_error("[uwsgi-emperor] write() config");
}
}
}
return;
}
@@ -607,6 +657,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
free(uef);
// add UWSGI_BROODLORD_NUM
if (n_ui->zerg) {
uef = uwsgi_num2str(uwsgi.emperor_broodlord_num);
if (setenv("UWSGI_BROODLORD_NUM", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
@@ -623,6 +683,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
free(oe);
@@ -714,7 +775,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
@@ -768,14 +829,14 @@ void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
uwsgi.emperor_absolute_dir = uwsgi.cwd;
if (!uwsgi_startswith(ues->arg, "glob://", 7)) {
ues->arg+=7;
ues->arg += 7;
}
}
void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_startswith(ues->arg, "dir://", 6)) {
ues->arg+=6;
ues->arg += 6;
}
if (chdir(ues->arg)) {
@@ -789,6 +850,8 @@ void uwsgi_imperial_monitor_directory_init(struct uwsgi_emperor_scanner *ues) {
exit(1);
}
ues->arg = uwsgi.emperor_absolute_dir;
}
struct uwsgi_imperial_monitor *imperial_monitor_get_by_id(char *scheme) {
@@ -881,13 +944,13 @@ next:
int uwsgi_emperor_scanner_event(int fd) {
struct uwsgi_emperor_scanner *ues = emperor_scanners;
while (ues) {
while (ues) {
if (ues->fd > -1 && ues->fd == fd) {
ues->event_func(ues);
return 1;
}
ues = ues->next;
}
ues = ues->next;
}
return 0;
@@ -993,18 +1056,17 @@ void emperor_loop() {
}
// check if a monitor is mapped to that file descriptor
if (uwsgi_emperor_scanner_event(interesting_fd)) continue;
if (uwsgi_emperor_scanner_event(interesting_fd)) {
continue;
}
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
char byte;
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
if (!ui_current->config_len) {
emperor_del(ui_current);
}
emperor_del(ui_current);
}
else {
if (byte == 17) {
@@ -1025,7 +1087,7 @@ void emperor_loop() {
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
emperor_add(NULL, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
@@ -1041,9 +1103,9 @@ void emperor_loop() {
// check for heartbeat (if required)
ui_current = ui->ui_next;
while(ui_current) {
while (ui_current) {
if (ui_current->last_heartbeat > 0) {
if ( (ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
// set last_heartbeat to 0 avoiding races
ui_current->last_heartbeat = 0;
@@ -1076,7 +1138,20 @@ void emperor_loop() {
diedpid = 0;
}
if (diedpid < 0) {
uwsgi_error("waitpid()");
// it looks like it happens when OOM is triggered to Linux cgroup, but it could be a uWSGI bug :P
// by the way, fallback to a clean situation...
if (errno == ECHILD) {
uwsgi_log("--- MUTINY DETECTED !!! IMPALING VASSALS... ---\n");
ui_current = ui->ui_next;
while (ui_current) {
struct uwsgi_instance *rebel_vassal = ui_current;
ui_current = ui_current->ui_next;
emperor_del(rebel_vassal);
}
}
else {
uwsgi_error("waitpid()");
}
}
ui_current = ui;
while (ui_current->ui_next) {
@@ -1129,6 +1204,13 @@ void emperor_send_stats(int fd) {
return;
}
if (uwsgi.stats_http) {
if (uwsgi_send_http_stats(client_fd)) {
close(client_fd);
return;
}
}
struct uwsgi_stats *us = uwsgi_stats_new(8192);
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION))
@@ -1208,6 +1290,9 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
goto end0;
if (uwsgi_stats_keyval_comma(us, "monitor", c_ui->scanner->arg))
goto end0;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) c_ui->respawns))
goto end0;
@@ -1227,49 +1312,49 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_comma(us))
goto end0;
goto end0;
if (uwsgi_stats_key(us, "blacklist"))
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
goto end0;
if (uwsgi_stats_list_open(us))
goto end0;
struct uwsgi_emperor_blacklist_item *uebi = emperor_blacklist;
while (uebi) {
while (uebi) {
if (uwsgi_stats_object_open(us))
goto end0;
goto end0;
if (uwsgi_stats_keyval_comma(us, "id", uebi->id))
goto end0;
if (uwsgi_stats_keyval_comma(us, "id", uebi->id))
goto end0;
if (uwsgi_stats_keylong_comma(us, "throttle_level", uebi->throttle_level/1000))
goto end0;
if (uwsgi_stats_keylong_comma(us, "throttle_level", uebi->throttle_level / 1000))
goto end0;
if (uwsgi_stats_keylong_comma(us, "attempt", (unsigned long long) uebi->attempt))
goto end0;
if (uwsgi_stats_keylong_comma(us, "attempt", (unsigned long long) uebi->attempt))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_attempt", (unsigned long long) uebi->first_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong_comma(us, "first_attempt", (unsigned long long) uebi->first_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong(us, "last_attempt", (unsigned long long) uebi->last_attempt.tv_sec))
goto end0;
if (uwsgi_stats_keylong(us, "last_attempt", (unsigned long long) uebi->last_attempt.tv_sec))
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
goto end0;
uebi = uebi->next;
uebi = uebi->next;
if (uebi) {
if (uwsgi_stats_comma(us))
goto end0;
}
}
}
if (uwsgi_stats_list_close(us))
goto end0;
goto end0;
if (uwsgi_stats_object_close(us))
goto end0;
@@ -1277,6 +1362,10 @@ void emperor_send_stats(int fd) {
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
ssize_t res = write(client_fd, us->base + pos, remains);
if (res <= 0) {
if (res < 0) {
@@ -1299,42 +1388,91 @@ end:
void uwsgi_emperor_start() {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
if (uwsgi.emperor_procname) {
uwsgi_set_processname(uwsgi.emperor_procname);
}
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
if (uwsgi.emperor_procname) {
uwsgi.emperor_pid = uwsgi_fork(uwsgi.emperor_procname);
}
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
emperor_loop();
// never here
exit(1);
}
}
void uwsgi_check_emperor() {
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = atoi(emperor_env);
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
if (emperor_env) {
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = atoi(emperor_env);
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
uwsgi_log("*** has_emperor mode detected (fd: %d) ***\n", uwsgi.emperor_fd);
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
}
}
if (getenv("UWSGI_EMPEROR_FD_CONFIG")) {
uwsgi.emperor_fd_config = atoi(getenv("UWSGI_EMPEROR_FD_CONFIG"));
}
}
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
struct uwsgi_instance *ui_current = emperor_get(name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (uid != ui_current->uid || gid != ui_current->gid) {
uwsgi_log("[emperor-tyrant] !!! permissions of vassal %s changed. stopping the instance... !!!\n", name);
emperor_stop(ui_current);
return;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one) if needed
if (config) {
if (ui_current->config)
free(ui_current->config);
ui_current->config = uwsgi_str(config);
ui_current->config_len = strlen(ui_current->config);
}
// reload the instance
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
char *new_config = NULL;
size_t new_config_len = 0;
if (config) {
new_config = uwsgi_str(config);
new_config_len = strlen(new_config);
}
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
}
}
+45
View File
@@ -0,0 +1,45 @@
#include <uwsgi.h>
// 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;
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
}
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 (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
}
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 (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
}
void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
char *redirect = NULL;
size_t redirect_len = 0;
if (uwsgi_response_prepare_headers(wsgi_req, "301 Moved Permanently", 21)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (wsgi_req->query_string_len == 0) {
redirect = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1);
redirect_len = wsgi_req->path_info_len + 1;
}
else {
redirect = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/?", 2, wsgi_req->query_string, wsgi_req->query_string_len);
redirect_len = wsgi_req->path_info_len + 2 + wsgi_req->query_string_len;
}
uwsgi_response_add_header(wsgi_req, "Location", 8, redirect, redirect_len);
free(redirect);
return;
}
+544 -312
View File
File diff suppressed because it is too large Load Diff
+499
View File
@@ -0,0 +1,499 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Exceptions management
generally exceptions are printed in the logs, but if you enable
an exception manager they will be stored in a (relatively big) uwsgi packet
with the following structure.
"vars" -> keyval of request vars
"backtrace" -> list of backtrace lines. Each line is a list of 5 elements filename,line,function,text,custom
"unix" -> seconds since the epoch
"class" -> the exception class
"msg" -> a text message mapped to the extension
"repr" -> a text message mapped to the extension in language-specific gergo
"wid" -> worker id
"core" -> the core generating the exception
"pid" -> pid of the worker
"node" -> hostname
Other vars can be added, but you cannot be sure they will be used by exceptions handler.
The exception-uwsgi packet is passed "as is" to the exception handler
Exceptions hooks:
a request plugin can export that hooks:
struct uwsgi_buffer *backtrace(struct wsgi_request *);
struct uwsgi_buffer *exception_class(struct wsgi_request *);
struct uwsgi_buffer *exception_msg(struct wsgi_request *);
struct uwsgi_buffer *exception_repr(struct wsgi_request *);
void exception_log(struct wsgi_request *);
Remember to reset the exception status (if possibile) after each call
Exceptions catcher:
This is a special development-mode in which exceptions are printed
to the HTTP client.
*/
struct uwsgi_buffer *uwsgi_exception_handler_object(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append_keyval(ub, "vars", 4, wsgi_req->buffer,wsgi_req->uh->pktsize)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
struct uwsgi_buffer *bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
if (bt) {
if (uwsgi_buffer_append_keyval(ub, "backtrace", 9, bt->buf, bt->pos)) {
uwsgi_buffer_destroy(bt);
goto error;
}
uwsgi_buffer_destroy(bt);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ec = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
if (ec) {
if (uwsgi_buffer_append_keyval(ub, "class", 5, ec->buf, ec->pos)) {
uwsgi_buffer_destroy(ec);
goto error;
}
uwsgi_buffer_destroy(ec);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *em = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (em) {
if (uwsgi_buffer_append_keyval(ub, "msg", 3, em->buf, em->pos)) {
uwsgi_buffer_destroy(em);
goto error;
}
uwsgi_buffer_destroy(em);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *er = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
if (er) {
if (uwsgi_buffer_append_keyval(ub, "repr", 4, er->buf, er->pos)) {
uwsgi_buffer_destroy(er);
goto error;
}
uwsgi_buffer_destroy(er);
}
}
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now())) goto error;
if (uwsgi_buffer_append_keynum(ub, "wid", 3, uwsgi.mywid)) goto error;
if (uwsgi_buffer_append_keynum(ub, "pid", 3, uwsgi.mypid)) goto error;
if (uwsgi_buffer_append_keynum(ub, "core", 4, wsgi_req->async_id)) goto error;
if (uwsgi_buffer_append_keyval(ub, "node", 4, uwsgi.hostname, uwsgi.hostname_len)) goto error;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static void append_vars_to_ubuf(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
if (uwsgi_buffer_append(ub, key, keylen)) return;
if (uwsgi_buffer_append(ub, " = ", 3)) return;
if (uwsgi_buffer_append(ub, val, vallen)) return;
if (uwsgi_buffer_append(ub, "\n", 1)) return;
}
static void append_backtrace_to_ubuf(uint16_t pos, char *value, uint16_t len, void *data) {
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
uint16_t item = 0;
if (pos > 0) {
item = pos % 5;
}
switch(item) {
// filename
case 0:
if (uwsgi_buffer_append(ub, "filename: \"", 11)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
break;
// lineno
case 1:
if (uwsgi_buffer_append(ub, "line: ", 6)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, " ", 1)) return;
break;
// function
case 2:
if (uwsgi_buffer_append(ub, "function: \"", 11)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
break;
// text
case 3:
if (len > 0) {
if (uwsgi_buffer_append(ub, "text/code: \"", 12)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
}
break;
// custom
case 4:
if (len > 0) {
if (uwsgi_buffer_append(ub, "custom: \"", 9)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
}
if (uwsgi_buffer_append(ub, "\n", 1)) return;
break;
default:
break;
}
}
int uwsgi_exceptions_catch(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) {
return -1;
}
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) {
return -1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append(ub, "uWSGI exceptions catcher for \"", 30)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto error;
if (uwsgi_buffer_append(ub, "\" (request plugin: \"", 20)) goto error;
if (uwsgi_buffer_append(ub, (char *) uwsgi.p[wsgi_req->uh->modifier1]->name, strlen(uwsgi.p[wsgi_req->uh->modifier1]->name))) goto error;
if (uwsgi_buffer_append(ub, "\", modifier1: ", 14 )) goto error;
if (uwsgi_buffer_num64(ub, wsgi_req->uh->modifier1)) goto error;
if (uwsgi_buffer_append(ub, ")\n\n", 3)) goto error;
if (uwsgi_buffer_append(ub, "Exception: ", 11)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *ub_exc_repr = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
if (ub_exc_repr) {
if (uwsgi_buffer_append(ub, ub_exc_repr->buf, ub_exc_repr->pos)) {
uwsgi_buffer_destroy(ub_exc_repr);
goto error;
}
uwsgi_buffer_destroy(ub_exc_repr);
}
else {
goto notavail3;
}
}
else {
notavail3:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Exception class: ", 17)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ub_exc_class = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
if (ub_exc_class) {
if (uwsgi_buffer_append(ub, ub_exc_class->buf, ub_exc_class->pos)) {
uwsgi_buffer_destroy(ub_exc_class);
goto error;
}
uwsgi_buffer_destroy(ub_exc_class);
}
else {
goto notavail;
}
}
else {
notavail:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Exception message: ", 19)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *ub_exc_msg = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub_exc_msg) {
if (uwsgi_buffer_append(ub, ub_exc_msg->buf, ub_exc_msg->pos)) {
uwsgi_buffer_destroy(ub_exc_msg);
goto error;
}
uwsgi_buffer_destroy(ub_exc_msg);
}
else {
goto notavail2;
}
}
else {
notavail2:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Backtrace:\n", 11)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
struct uwsgi_buffer *ub_exc_bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
if (ub_exc_bt) {
struct uwsgi_buffer *parsed_bt = uwsgi_buffer_new(4096);
if (uwsgi_hooked_parse_array(ub_exc_bt->buf, ub_exc_bt->pos, append_backtrace_to_ubuf, parsed_bt)) {
uwsgi_buffer_destroy(ub_exc_bt);
uwsgi_buffer_destroy(parsed_bt);
goto error;
}
uwsgi_buffer_destroy(ub_exc_bt);
if (uwsgi_buffer_append(ub, parsed_bt->buf, parsed_bt->pos)) {
uwsgi_buffer_destroy(parsed_bt);
goto error;
}
uwsgi_buffer_destroy(parsed_bt);
}
else {
goto notavail4;
}
}
else {
notavail4:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, append_vars_to_ubuf, ub)) {
goto error;
}
if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) {
goto error;
}
uwsgi_buffer_destroy(ub);
return 0;
error:
uwsgi_buffer_destroy(ub);
return -1;
}
static void uwsgi_exception_run_handlers(struct uwsgi_buffer *ub) {
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
struct iovec iov[2];
iov[1].iov_base = ub->buf;
iov[1].iov_len = ub->pos;
while(usl) {
struct uwsgi_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) usl->custom_ptr;
iov[0].iov_base = &uehi;
iov[0].iov_len = sizeof(long);
// now send the message to the exception handler thread
if (writev(uwsgi.exception_handler_thread->pipe[0], iov, 2) != (ssize_t) (ub->pos+sizeof(long))) {
uwsgi_error("[uwsgi-exception-handler-error] uwsgi_exception_run_handlers()/writev()");
}
usl = usl->next;
}
}
void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
int do_exit = uwsgi.reload_on_exception;
if (!wsgi_req) goto log2;
if (do_exit) goto check_catch;
if (wsgi_req && uwsgi.exception_handlers_instance) {
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
if (ehi) {
uwsgi_exception_run_handlers(ehi);
uwsgi_buffer_destroy(ehi);
}
}
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].exceptions++;
uwsgi_apps[wsgi_req->app_id].exceptions++;
if (uwsgi.reload_on_exception_type && uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_type;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
if (uwsgi.reload_on_exception_value && uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_value;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
if (uwsgi.reload_on_exception_repr && uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_repr;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
check_catch:
if (catch && wsgi_req) {
if (uwsgi_exceptions_catch(wsgi_req)) {
// for now, just goto, new features could be added
goto log;
}
}
log:
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_log) {
uwsgi.p[wsgi_req->uh->modifier1]->exception_log(wsgi_req);
}
log2:
if (do_exit) {
exit(UWSGI_EXCEPTION_CODE);
}
}
struct uwsgi_exception_handler *uwsgi_register_exception_handler(char *name, int (*func)(struct uwsgi_exception_handler_instance *, char *, size_t)) {
struct uwsgi_exception_handler *old_ueh = NULL, *ueh = uwsgi.exception_handlers;
while(ueh) {
if (!strcmp(name, ueh->name)) {
return NULL;
}
old_ueh = ueh;
ueh = ueh->next;
}
ueh = uwsgi_calloc(sizeof(struct uwsgi_exception_handler));
ueh->name = name;
ueh->func = func;
if (old_ueh) {
old_ueh->next = ueh;
}
else {
uwsgi.exception_handlers = ueh;
}
return ueh;
}
struct uwsgi_exception_handler *uwsgi_exception_handler_by_name(char *name) {
struct uwsgi_exception_handler *ueh = uwsgi.exception_handlers;
while(ueh) {
if (!strcmp(name, ueh->name)) {
return ueh;
}
ueh = ueh->next;
}
return NULL;
}
static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
char *buf = uwsgi_malloc(uwsgi.exception_handler_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_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) ptr;
if (!uehi)
break;
if (uehi->handler->func(uehi, msg, msg_size)) {
uwsgi_log("[uwsgi-exception] error running the handler \"%s\" args: \"%s\"\n", uehi->handler->name, uehi->arg ? uehi->arg : "");
}
}
}
}
free(buf);
}
void uwsgi_exception_setup_handlers() {
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
while(usl) {
char *handler = uwsgi_str(usl->value);
char *colon = strchr(handler, ':');
if (colon) {
*colon = 0;
}
struct uwsgi_exception_handler *ueh = uwsgi_exception_handler_by_name(handler);
if (!ueh) {
uwsgi_log("unable to find exception handler: %s\n", handler);
free(handler);
exit(1);
}
free(handler);
struct uwsgi_exception_handler_instance *uehi = uwsgi_calloc(sizeof(struct uwsgi_exception_handler_instance));
uehi->handler = ueh;
if (colon) {
uehi->arg = colon+1;
}
usl->custom_ptr = uehi;
usl = usl->next;
}
}
void uwsgi_exceptions_handler_thread_start() {
// start the exception_handler_thread
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
if (!uwsgi.exception_handler_thread) {
uwsgi_log("unable to spawn exception handler thread\n");
exit(1);
}
}
+85 -78
View File
@@ -2,29 +2,29 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int, void *), void *data) {
struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), void *data) {
struct uwsgi_gateway *ug;
int num=1,i;
struct uwsgi_gateway *ug;
int num = 1, i;
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<ushared->gateways_cnt;i++) {
if (!strcmp(name, ushared->gateways[i].name)) {
num++;
}
}
for (i = 0; i < ushared->gateways_cnt; i++) {
if (!strcmp(name, ushared->gateways[i].name)) {
num++;
}
}
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug->fullname = fullname;
ug->data = data;
@@ -35,10 +35,14 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int, void *), vo
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
ushared->gateways_cnt++;
return ug;
return ug;
}
static void gateway_brutal_end() {
_exit(UWSGI_END_CODE);
}
void gateway_respawn(int id) {
@@ -48,112 +52,115 @@ void gateway_respawn(int id) {
if (uwsgi.master_process)
uwsgi.shared->gateways_harakiri[id] = 0;
gw_pid = uwsgi_fork(ug->fullname);
if (gw_pid < 0) {
uwsgi_error("fork()");
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
if (uwsgi.master_as_root) uwsgi_as_root();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
uwsgi.mypid = getpid();
atexit(gateway_brutal_end);
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
ug->loop(id, ug->data);
// never here !!! (i hope)
exit(1);
exit(1);
}
ug->pid = gw_pid;
ug->respawns++;
if (ug->respawns == 1) {
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
uwsgi_log("spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
else {
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
uwsgi_log("respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
}
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while (uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = -1;
uwsgi_sock->shared = 0;
uwsgi_sock->name = name;
uwsgi_sock->name = name;
uwsgi_sock->name_len = strlen(name);
uwsgi_sock->owner = owner;
return uwsgi_sock;
return uwsgi_sock;
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while (uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = fd;
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
uwsgi_sock->owner = owner;
uwsgi_sock->owner = owner;
return uwsgi_sock;
return uwsgi_sock;
}
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_del_fd(queue, ugs->fd, event_queue_read());
}
ugs = ugs->next;
}
*i_am_cheap = 1;
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_del_fd(queue, ugs->fd, event_queue_read());
}
ugs = ugs->next;
}
*i_am_cheap = 1;
}
+93
View File
@@ -0,0 +1,93 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// Bernstein classic hash (this is not static as it is used by other areas)
uint32_t djb33x_hash(char *key, uint64_t keylen) {
register uint32_t hash = 5381;
uint64_t i;
for (i = 0; i < keylen; i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
// Murmur2 hash Copyright (C) Austin Appleby
// adapted from nginx
uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t h, k;
uint8_t *ukey = (uint8_t *) key;
h = 0 ^ keylen;
while (keylen >= 4) {
k = ukey[0];
k |= ukey[1] << 8;
k |= ukey[2] << 16;
k |= ukey[3] << 24;
k *= 0x5bd1e995;
k ^= k >> 24;
k *= 0x5bd1e995;
h *= 0x5bd1e995;
h ^= k;
ukey += 4;
keylen -= 4;
}
switch (keylen) {
case 3:
h ^= key[2] << 16;
case 2:
h ^= key[1] << 8;
case 1:
h ^= key[0];
h *= 0x5bd1e995;
}
h ^= h >> 13;
h *= 0x5bd1e995;
h ^= h >> 15;
return h;
}
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
while(uha) {
if (!strcmp(name, uha->name)) {
return uha;
}
uha = uha->next;
}
return NULL;
}
void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
struct uwsgi_hash_algo *old_uha = NULL, *uha = uwsgi.hash_algos;
while(uha) {
if (!strcmp(uha->name, name)) return;
old_uha = uha;
uha = uha->next;
}
uha = uwsgi_calloc(sizeof(struct uwsgi_hash_algo));
uha->name = name;
uha->func = func;
if (old_uha) {
old_uha->next = uha;
}
else {
uwsgi.hash_algos = uha;
}
}
void uwsgi_hash_algo_register_all() {
uwsgi_hash_algo_register("djb33x", djb33x_hash);
uwsgi_hash_algo_register("murmur2", murmur2_hash);
}
+20 -19
View File
@@ -13,7 +13,7 @@ void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
for (i = strlen(line) - 1; i >= 0; i--) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
line[i] = 0;
continue;
@@ -27,7 +27,7 @@ char *ini_lstrip(char *line) {
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
@@ -43,7 +43,7 @@ char *ini_get_key(char *key) {
off_t i;
char *ptr = key;
for(i=0;i< (int) strlen(key);i++) {
for (i = 0; i < (int) strlen(key); i++) {
ptr++;
if (key[i] == '=') {
key[i] = 0;
@@ -54,12 +54,12 @@ char *ini_get_key(char *key) {
return ptr;
}
char *ini_get_line(char *ini, off_t size) {
char *ini_get_line(char *ini, size_t size) {
off_t i;
size_t i;
char *ptr = ini;
for(i=0;i<size;i++) {
for (i = 0; i < size; i++) {
ptr++;
if (ini[i] == '\n') {
ini[i] = 0;
@@ -78,7 +78,7 @@ char *ini_get_line(char *ini, off_t size) {
void uwsgi_ini_config(char *file, char *magic_table[]) {
int len = 0;
size_t len = 0;
char *ini;
char *ini_line;
@@ -92,28 +92,29 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
section_asked = colon + 1;
}
}
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
while(len) {
while (len) {
ini_line = ini_get_line(ini, len);
if (ini_line == NULL) {
break;
@@ -125,8 +126,8 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini_rstrip(key);
if (key[0] != 0) {
if (key[0] == '[') {
section = key+1;
section[strlen(section)-1] = 0;
section = key + 1;
section[strlen(section) - 1] = 0;
}
else if (key[0] == ';' || key[0] == '#') {
// this is a comment
@@ -139,7 +140,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
add_exported_option((char *)key, val, 0);
add_exported_option((char *) key, val, 0);
}
}
}
+379 -164
View File
@@ -2,104 +2,195 @@
extern struct uwsgi_server uwsgi;
struct http_status_codes {
const char key[3];
const char *message;
int message_size;
};
/* statistically ordered */
struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{"", NULL},
};
void uwsgi_init_default() {
uwsgi.cpus = 1;
uwsgi.backtrace_depth = 64;
uwsgi.max_apps = 64;
uwsgi.max_apps = 64;
uwsgi.master_queue = -1;
uwsgi.master_queue = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.stats_fd = -1;
uwsgi.original_log_fd = -1;
uwsgi.stats_pusher_default_freq = 3;
uwsgi.emperor_fd_config = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
uwsgi.original_log_fd = -1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.emperor_fd_config = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.default_app = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
uwsgi.buffer_size = 4096;
uwsgi.numproc = 1;
// default max number of rpc slot
uwsgi.rpc_max = 64;
uwsgi.forkbomb_delay = 2;
uwsgi.offload_threads_events = 64;
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.default_app = -1;
uwsgi.cheaper_overload = 3;
uwsgi.buffer_size = 4096;
uwsgi.body_read_warning = 8;
uwsgi.numproc = 1;
uwsgi.log_master_bufsize = 8192;
uwsgi.forkbomb_delay = 2;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.async = 1;
uwsgi.listen_queue = 100;
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
uwsgi.cheaper_overload = 3;
#ifdef UWSGI_SPOOLER
uwsgi.shared->spooler_frequency = 30;
uwsgi.log_master_bufsize = 8192;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
#endif
uwsgi.shared->mule_signal_pipe[0] = -1;
uwsgi.shared->mule_signal_pipe[1] = -1;
uwsgi.worker_reload_mercy = 60;
uwsgi.shared->mule_queue_pipe[0] = -1;
uwsgi.shared->mule_queue_pipe[1] = -1;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.shared->worker_log_pipe[0] = -1;
uwsgi.shared->worker_log_pipe[1] = -1;
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
// a workers hould be running for at least 10 seconds
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
uwsgi.shared->spooler_frequency = 30;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
uwsgi.shared->mule_signal_pipe[0] = -1;
uwsgi.shared->mule_signal_pipe[1] = -1;
uwsgi.shared->mule_queue_pipe[0] = -1;
uwsgi.shared->mule_queue_pipe[1] = -1;
uwsgi.shared->worker_log_pipe[0] = -1;
uwsgi.shared->worker_log_pipe[1] = -1;
uwsgi.shared->worker_req_log_pipe[0] = -1;
uwsgi.shared->worker_req_log_pipe[1] = -1;
uwsgi.req_log_fd = 2;
#ifdef UWSGI_SSL
// 1 day of tolerance
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
// 1 day of tolerance
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
uwsgi.ssl_sessions_timeout = 300;
#endif
uwsgi.alarm_freq = 3;
uwsgi.alarm_msg_size = 8192;
uwsgi.exception_handler_msg_size = 65536;
uwsgi.multicast_ttl = 1;
uwsgi.multicast_loop = 1;
// filling http status codes
struct http_status_codes *http_sc;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
uwsgi.empty = "";
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi_websockets_init();
}
void uwsgi_setup_reload() {
char env_reload_buf[11];
char env_reload_buf[11];
char *env_reloads = getenv("UWSGI_RELOADS");
if (env_reloads) {
//convert env value to int
uwsgi.reloads = atoi(env_reloads);
uwsgi.reloads++;
//convert reloads to string
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
}
}
uwsgi.is_a_reload = 1;
}
else {
if (setenv("UWSGI_RELOADS", "0", 1)) {
uwsgi_error("setenv()");
}
}
if (env_reloads) {
//convert env value to int
uwsgi.reloads = atoi(env_reloads);
uwsgi.reloads++;
//convert reloads to string
int rlen = snprintf(env_reload_buf, 10, "%u", uwsgi.reloads);
if (rlen > 0) {
env_reload_buf[rlen] = 0;
if (setenv("UWSGI_RELOADS", env_reload_buf, 1)) {
uwsgi_error("setenv()");
}
}
uwsgi.is_a_reload = 1;
}
else {
if (setenv("UWSGI_RELOADS", "0", 1)) {
uwsgi_error("setenv()");
}
}
}
@@ -108,33 +199,33 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
char *plugins_requested = NULL;
char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
if (!original_proc_name) {
// here we use argv[0];
original_proc_name = argv_zero;
setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
}
char *p = strrchr(original_proc_name, '/');
if (p == NULL)
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
if (!original_proc_name) {
// here we use argv[0];
original_proc_name = argv_zero;
setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
}
char *p = strrchr(original_proc_name, '/');
if (p == NULL)
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
}
@@ -143,93 +234,217 @@ void uwsgi_commandline_config() {
uwsgi.option_index = -1;
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
char *optname;
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
if (i == '?') {
uwsgi_log("getopt_long() error\n");
exit(1);
}
if (i == '?') {
uwsgi_log("getopt_long() error\n");
exit(1);
}
if (uwsgi.option_index > -1) {
optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
}
else {
optname = uwsgi_get_optname_by_index(i);
}
if (!optname) {
uwsgi_log("unable to parse command line options\n");
exit(1);
}
uwsgi.option_index = -1;
add_exported_option(optname, optarg, 0);
}
if (uwsgi.option_index > -1) {
optname = (char *) uwsgi.long_options[uwsgi.option_index].name;
}
else {
optname = uwsgi_get_optname_by_index(i);
}
if (!optname) {
uwsgi_log("unable to parse command line options\n");
exit(1);
}
uwsgi.option_index = -1;
add_exported_option(optname, optarg, 0);
}
#ifdef UWSGI_DEBUG
uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
#endif
if (optind < uwsgi.argc) {
for (i = optind; i < uwsgi.argc; i++) {
char *lazy = uwsgi.argv[i];
if (lazy[0] != '[') {
uwsgi_opt_load(NULL, lazy, NULL);
// manage magic mountpoint
int magic = 0;
int j;
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->magic) {
if (uwsgi.gp[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
if (!magic) {
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->magic) {
if (uwsgi.p[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
}
}
}
}
if (optind < uwsgi.argc) {
for (i = optind; i < uwsgi.argc; i++) {
char *lazy = uwsgi.argv[i];
if (lazy[0] != '[') {
uwsgi_opt_load(NULL, lazy, NULL);
// manage magic mountpoint
int magic = 0;
int j;
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->magic) {
if (uwsgi.gp[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
if (!magic) {
for (j = 0; j < 256; j++) {
if (uwsgi.p[j]->magic) {
if (uwsgi.p[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
}
}
}
}
}
void uwsgi_setup_workers() {
int i,j;
int i, j;
// allocate shared memory for workers + master
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt));
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1));
for (i = 0; i <= uwsgi.numproc; i++) {
// allocate memory for apps
uwsgi.workers[i].apps = (struct uwsgi_app *) uwsgi_calloc_shared(sizeof(struct uwsgi_app) * uwsgi.max_apps);
for (i = 0; i <= uwsgi.numproc; i++) {
// allocate memory for apps
uwsgi.workers[i].apps = (struct uwsgi_app *) uwsgi_calloc_shared(sizeof(struct uwsgi_app) * uwsgi.max_apps);
// allocate memory for cores
uwsgi.workers[i].cores = (struct uwsgi_core *) uwsgi_calloc_shared(sizeof(struct uwsgi_core) * uwsgi.cores);
// allocate memory for cores
uwsgi.workers[i].cores = (struct uwsgi_core *) uwsgi_calloc_shared(sizeof(struct uwsgi_core) * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
// allocate shared memory for thread states (required for some language, like python)
uwsgi.workers[i].cores[j].ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps);
// raw per-request buffer
uwsgi.workers[i].cores[j].buffer = uwsgi_malloc_shared(uwsgi.buffer_size);
// iovec for uwsgi vars
uwsgi.workers[i].cores[j].hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size);
if (uwsgi.post_buffering > 0)
uwsgi.workers[i].cores[j].post_buf = uwsgi_malloc_shared(uwsgi.post_buffering_bufsize);
}
// master does not need to following steps...
if (i == 0) continue;
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
// this is a trick for avoiding too much memory areas
void *ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps * uwsgi.cores);
// add 4 bytes for uwsgi header
void *buffers = uwsgi_malloc_shared((uwsgi.buffer_size+4) * uwsgi.cores);
void *hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
void *post_buf = NULL;
if (uwsgi.post_buffering > 0)
post_buf = uwsgi_malloc_shared(uwsgi.post_buffering_bufsize * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
// allocate shared memory for thread states (required for some language, like python)
uwsgi.workers[i].cores[j].ts = ts + ((sizeof(void *) * uwsgi.max_apps) * j);
// raw per-request buffer (+4 bytes for uwsgi header)
uwsgi.workers[i].cores[j].buffer = buffers + ((uwsgi.buffer_size+4) * j);
// iovec for uwsgi vars
uwsgi.workers[i].cores[j].hvec = hvec + ((sizeof(struct iovec) * uwsgi.vec_size) * j);
if (post_buf)
uwsgi.workers[i].cores[j].post_buf = post_buf + (uwsgi.post_buffering_bufsize * j);
}
// master does not need to following steps...
if (i == 0)
continue;
uwsgi.workers[i].signal_pipe[0] = -1;
uwsgi.workers[i].signal_pipe[1] = -1;
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
}
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
if (uwsgi.post_buffering > 0) {
total_memory += (uwsgi.post_buffering_bufsize * uwsgi.cores);
}
total_memory *= (uwsgi.numproc + uwsgi.master_process);
if (uwsgi.numproc > 0)
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", (unsigned long long) total_memory, (unsigned long long) (total_memory / 1024), uwsgi.cores * uwsgi.numproc);
// allocate signal table
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
}
pid_t uwsgi_daemonize2() {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize2);
}
else {
if (!uwsgi.is_a_reload) {
uwsgi_log("*** daemonizing uWSGI ***\n");
daemonize(uwsgi.daemonize2);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize2);
}
}
uwsgi.mypid = getpid();
uwsgi.workers[0].pid = uwsgi.mypid;
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
return uwsgi.mypid;
}
// fix/check related options
void sanitize_args() {
if (uwsgi.async > 1) {
uwsgi.cores = uwsgi.async;
}
if (uwsgi.threads > 1) {
uwsgi.has_threads = 1;
uwsgi.cores = uwsgi.threads;
}
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 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");
}
}
if (uwsgi.write_errors_exception_only) {
uwsgi.ignore_sigpipe = 1;
uwsgi.ignore_write_errors = 1;
}
if (uwsgi.cheaper_count == 0) uwsgi.cheaper = 0;
if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
uwsgi_log("invalid cheaper value: must be lower than processes\n");
exit(1);
}
if (uwsgi.cheaper && uwsgi.cheaper_count) {
if (uwsgi.cheaper_initial) {
if (uwsgi.cheaper_initial < uwsgi.cheaper_count) {
uwsgi_log("warning: invalid cheaper-initial value (%d), must be equal or higher than cheaper (%d), using %d as initial number of workers\n",
uwsgi.cheaper_initial, uwsgi.cheaper_count, uwsgi.cheaper_count);
uwsgi.cheaper_initial = uwsgi.cheaper_count;
}
else if (uwsgi.cheaper_initial > uwsgi.numproc) {
uwsgi_log("warning: invalid cheaper-initial value (%d), must be lower or equal than worker count (%d), using %d as initial number of workers\n",
uwsgi.cheaper_initial, uwsgi.numproc, uwsgi.numproc);
uwsgi.cheaper_initial = uwsgi.numproc;
}
}
else {
uwsgi.cheaper_initial = uwsgi.cheaper_count;
}
}
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]) {
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]);
exit(1);
}
}
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
struct http_status_codes *http_sc;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, status, 3)) {
*len = http_sc->message_size;
return http_sc->message;
}
}
return NULL;
}
+1008
View File
File diff suppressed because it is too large Load Diff
+31 -31
View File
@@ -13,7 +13,7 @@ extern struct uwsgi_server uwsgi;
void uwsgi_json_config(char *file, char *magic_table[]) {
int len = 0;
size_t len = 0;
char *json_data;
@@ -31,25 +31,25 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
int i;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
object_asked = colon+1;
object_asked = colon + 1;
}
}
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef JANSSON_MAJOR_VERSION
#ifdef JANSSON_MAJOR_VERSION
root = json_loads(json_data, 0, &error);
#else
root = json_loads(json_data, &error);
@@ -66,46 +66,46 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
exit(1);
}
config_iter = json_object_iter(config);
while(config_iter) {
while (config_iter) {
key = json_object_iter_key(config_iter);
config_value = json_object_iter_value(config_iter);
config_value = json_object_iter_value(config_iter);
if (json_is_string(config_value)) {
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
add_exported_option((char *) key, (char *) json_string_value(config_value), 0);
}
else if (json_is_true(config_value)) {
add_exported_option((char *)key, strdup("1"), 0);
add_exported_option((char *) key, strdup("1"), 0);
}
else if (json_is_false(config_value) || json_is_null(config_value)) {
add_exported_option((char *)key, strdup("0"), 0);
add_exported_option((char *) key, strdup("0"), 0);
}
else if (json_is_integer(config_value)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_value)), 0);
}
else if (json_is_array(config_value)) {
for(i=0;i<(int)json_array_size(config_value);i++) {
config_array_item = json_array_get(config_value, i);
for (i = 0; i < (int) json_array_size(config_value); i++) {
config_array_item = json_array_get(config_value, i);
if (json_is_string(config_array_item)) {
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *)key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *)key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
add_exported_option((char *) key, (char *) json_string_value(config_array_item), 0);
}
else if (json_is_true(config_array_item)) {
add_exported_option((char *) key, strdup("1"), 0);
}
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
add_exported_option((char *) key, strdup("0"), 0);
}
else if (json_is_integer(config_array_item)) {
add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
}
}
}
config_iter = json_object_iter_next(config, config_iter);
}
}
#endif
+68 -67
View File
@@ -19,25 +19,25 @@ void ldap2uwsgi(char *ldapname, char *uwsginame) {
int i;
for(i=0;i< (int) strlen(ldapname);i++) {
if (isupper( (int)ldapname[i])) {
for (i = 0; i < (int) strlen(ldapname); i++) {
if (isupper((int) ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower( (int) ldapname[i]);
*ptr++ = tolower((int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++= 0;
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for(i=0;i< (int)strlen(name);i++) {
if (isupper( (int) name[i])) {
for (i = 0; i < (int) strlen(name); i++) {
if (isupper((int) name[i])) {
counter++;
}
}
@@ -52,7 +52,7 @@ struct uwsgi_ldap_entry {
};
void uwsgi_name_to_ldap(char *src, char *dst) {
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
@@ -61,16 +61,16 @@ void uwsgi_name_to_ldap(char *src, char *dst) {
strcat(dst, " 'uWSGI");
ptr+= 7;
ptr += 7;
for(i=0;i< (int)strlen(src);i++) {
if (src[i] == '-') {
i++;
*ptr++= toupper( (int) src[i]);
}
else {
*ptr++= src[i];
}
for (i = 0; i < (int) strlen(src); i++) {
if (src[i] == '-') {
i++;
*ptr++ = toupper((int) src[i]);
}
else {
*ptr++ = src[i];
}
}
strcat(dst, "'");
@@ -82,7 +82,7 @@ struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num,
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
@@ -96,9 +96,9 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
int i;
struct uwsgi_ldap_entry *ule;
for(i=0;i<count;i++) {
for (i = 0; i < count; i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name+1)) {
if (uwsgi_list_has_str(ule->names, name + 1)) {
return ule;
}
}
@@ -114,23 +114,24 @@ struct uwsgi_ldap_entry *get_ldap_names(int *count) {
*count = 0;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
while( op && op->name ) {
while (op && op->name) {
uwsgi_name_to_ldap((char *)op->name, ldap_name);
uwsgi_name_to_ldap((char *) op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (entry)
goto next;
entry = &ule[*count] ;
entry = &ule[*count];
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
*count = *count + 1;
entry->has_arg = op->type;
next:
op++;
}
@@ -150,7 +151,7 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
@@ -168,19 +169,19 @@ void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
entry = &ule[i];
for (i = 0; i < items; i++) {
char *list2 = uwsgi_concat2(entry->names+1, "");
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
free(list2);
}
@@ -198,38 +199,38 @@ void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for(i=0;i<items;i++) {
for (i = 0; i < items; i++) {
entry = &ule[i];
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names+1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p)-2, p+1);
p = strtok(NULL, " ");
}
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
free(list2);
}
}
@@ -264,7 +265,7 @@ void uwsgi_ldap_config(char *url) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
@@ -281,25 +282,25 @@ void uwsgi_ldap_config(char *url) {
#endif
#if LDAP_API_VERSION >= 3000
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ( (ldp = ldap_init( ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
@@ -318,17 +319,17 @@ void uwsgi_ldap_config(char *url) {
entry = ldap_first_entry(ldp, results);
int found = 0;
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr,"uWSGI",5)) {
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr, "uWSGI", 5)) {
found = 1;
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr+5, uwsgi_attr);
ldap2uwsgi(attr + 5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
@@ -336,7 +337,7 @@ void uwsgi_ldap_config(char *url) {
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
@@ -345,7 +346,7 @@ void uwsgi_ldap_config(char *url) {
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char*) uwsgi_attr, uwsgi_val, 0);
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
+1022
View File
File diff suppressed because it is too large Load Diff
+231 -140
View File
@@ -20,7 +20,7 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
return uwsgi.registered_locks;
}
while(uli) {
while (uli) {
if (!uli->next) {
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
if (rw) {
@@ -45,6 +45,10 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
#ifdef UWSGI_LOCK_USE_MUTEX
#ifdef OBSOLETE_LINUX_KERNEL
#undef EOWNERDEAD
#endif
#ifdef EOWNERDEAD
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
int uwsgi_pthread_robust_mutexes_enabled = 1;
@@ -60,36 +64,49 @@ int uwsgi_pthread_robust_mutexes_enabled = 1;
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
#ifndef PTHREAD_PRIO_INHERIT
int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
int __protocol);
#define PTHREAD_PRIO_INHERIT 1
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
pthread_mutexattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
#ifdef EOWNERDEAD
retry:
#endif
if (pthread_mutexattr_init(&attr)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
#ifdef EOWNERDEAD
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#endif
if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) {
uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
exit(1);
}
if (uwsgi_pthread_robust_mutexes_enabled) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
}
#endif
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
#ifdef EOWNERDEAD
if (uwsgi_pthread_robust_mutexes_enabled) {
uwsgi_log("!!! it looks like your kernel does not support pthread robust mutexes !!!\n");
@@ -99,9 +116,9 @@ retry:
goto retry;
}
#endif
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
pthread_mutexattr_destroy(&attr);
@@ -116,25 +133,25 @@ retry:
return uli;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item * uli) {
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item * uli) {
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_check(uli);
#else
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0) {
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
return uli->pid;
#endif
}
@@ -149,7 +166,7 @@ void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
#else
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
#endif
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
@@ -164,7 +181,7 @@ void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
#endif
}
@@ -173,7 +190,7 @@ void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
uli->pid = uwsgi.mypid;
#endif
}
@@ -182,7 +199,7 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = 0;
uli->pid = 0;
#endif
}
@@ -196,20 +213,20 @@ struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
if (pthread_rwlockattr_init(&attr)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_init(&attr)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
pthread_rwlockattr_destroy(&attr);
@@ -235,36 +252,46 @@ struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
return uwsgi_lock_fast_init(id);
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
umtx_init((struct umtx*) uli->lock_ptr);
umtx_init((struct umtx *) uli->lock_ptr);
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
umtx_lock((struct umtx *) uli->lock_ptr, (u_long) getpid());
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
umtx_unlock((struct umtx *) uli->lock_ptr, (u_long) getpid());
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
if (umtx_trylock((struct umtx *) uli->lock_ptr, (u_long) getpid())) {
umtx_unlock((struct umtx *) uli->lock_ptr, (u_long) getpid());
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item * uli) {
return uwsgi_lock_fast_check(uli);
}
#elif defined(UWSGI_LOCK_USE_POSIX_SEM)
@@ -275,36 +302,46 @@ pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_f
#include <semaphore.h>
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
sem_init((sem_t*) uli->lock_ptr, 1, 1);
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
sem_init((sem_t *) uli->lock_ptr, 1, 1);
uli->can_deadlock = 1;
return uli;
return uli;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
return uwsgi_lock_fast_init(id);
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
sem_wait((sem_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
sem_wait((sem_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
sem_post((sem_t*) uli->lock_ptr);
uli->pid = 0;
sem_post((sem_t *) uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (sem_trywait((sem_t *) uli->lock_ptr) == 0) {
sem_post((sem_t*) uli->lock_ptr);
return 0;
}
return uli->pid;
sem_post((sem_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item * uli) {
return uwsgi_lock_fast_check(uli);
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
@@ -342,19 +379,27 @@ pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) { uwsgi_lock_fast(uli);}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_fast_check(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#else
@@ -384,10 +429,10 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
// used by ftok
static int counter = 1;
union semun {
int val;
int val;
struct semid_ds *buf;
ushort *array;
} semu ;
} semu;
int semid;
key_t myKey;
@@ -400,10 +445,10 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
exit(1);
}
counter++;
semid = semget(myKey, 1, IPC_CREAT|0666);
semid = semget(myKey, 1, IPC_CREAT | 0666);
}
else {
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666);
}
if (semid < 0) {
@@ -418,7 +463,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
uwsgi_error("semctl()");
exit(1);
}
return uli;
}
@@ -432,9 +477,11 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
memcpy(&semid, uli->lock_ptr, sizeof(int));
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
}
}
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
@@ -447,16 +494,26 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
memcpy(&semid, uli->lock_ptr, sizeof(int));
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
}
}
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) {
return uwsgi_lock_ipcsem_init(id);
}
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) {
uwsgi_lock_ipcsem(uli);
}
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) {
uwsgi_lock_ipcsem(uli);
}
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) {
uwsgi_unlock_ipcsem(uli);
}
// ipc cannot deadlock
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
@@ -467,13 +524,17 @@ void uwsgi_ipcsem_clear(void) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers) goto clear;
if (!uwsgi.workers)
goto clear;
if (uwsgi.mywid == 0) goto clear;
if (uwsgi.mywid == 0)
goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid)
goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1)
goto clear;
return;
@@ -482,7 +543,7 @@ clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
while(uli) {
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
@@ -493,11 +554,17 @@ clear:
}
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
void uwsgi_setup_locking() {
int i;
if (uwsgi.locking_setup) return;
// use the fastest available locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
@@ -514,8 +581,10 @@ void uwsgi_setup_locking() {
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
goto ready;
}
uwsgi_log("unable to find lock engine \"%s\"\n", uwsgi.lock_engine);
exit(1);
}
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
@@ -534,40 +603,54 @@ void uwsgi_setup_locking() {
uwsgi.lock_size = UWSGI_LOCK_SIZE;
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
ready:
// application generic lock
int i;
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
}
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
}
// event queue lock (mitigate same event on multiple queues)
if (uwsgi.threads > 1) {
pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
}
if (uwsgi.threads > 1) {
pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
}
if (uwsgi.master_process) {
// signal table lock
uwsgi.signal_table_lock = uwsgi_lock_init("signal");
if (uwsgi.master_process) {
// signal table lock
uwsgi.signal_table_lock = uwsgi_lock_init("signal");
// fmon table lock
uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
// fmon table lock
uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
// cron table lock
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
#ifdef UWSGI_SSL
// register locking for legions
struct uwsgi_legion *ul = uwsgi.legions;
while(ul) {
ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
ul = ul->next;
}
#endif
uwsgi.locking_setup = 1;
}
@@ -589,43 +672,51 @@ int uwsgi_fcntl_lock(int fd) {
int uwsgi_fcntl_is_locked(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
if (fcntl(fd, F_SETLK, &fl)) {
if (fcntl(fd, F_SETLK, &fl)) {
return 1;
}
return 0;
}
void uwsgi_deadlock_check(pid_t diedpid) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (!uli->can_deadlock)
goto nextlock;
pid_t locked_pid = 0;
if (uli->rw) {
locked_pid = uwsgi_rwlock_check(uli);
}
else {
locked_pid = uwsgi_lock_check(uli);
}
if (locked_pid == diedpid) {
uwsgi_log("[deadlock-detector] pid %d was holding lock %s (%p)\n", (int) diedpid, uli->id, uli->lock_ptr);
if (uli->rw) {
uwsgi_rwunlock(uli);
}
else {
uwsgi_unlock(uli);
}
}
while (uli) {
if (!uli->can_deadlock)
goto nextlock;
pid_t locked_pid = 0;
if (uli->rw) {
locked_pid = uwsgi_rwlock_check(uli);
}
else {
locked_pid = uwsgi_lock_check(uli);
}
if (locked_pid == diedpid) {
uwsgi_log("[deadlock-detector] pid %d was holding lock %s (%p)\n", (int) diedpid, uli->id, uli->lock_ptr);
if (uli->rw) {
uwsgi_rwunlock(uli);
}
else {
uwsgi_unlock(uli);
}
}
nextlock:
uli = uli->next;
}
uli = uli->next;
}
}
void uwsgi_user_lock(int lock_num) {
uwsgi_lock(uwsgi.user_lock[lock_num]);
}
void uwsgi_user_unlock(int lock_num) {
uwsgi_unlock(uwsgi.user_lock[lock_num]);
}
+868 -403
View File
File diff suppressed because it is too large Load Diff
+92 -48
View File
@@ -10,73 +10,117 @@ struct wsgi_request *simple_current_wsgi_req() {
}
void uwsgi_register_loop(char *name, void *loop) {
void uwsgi_register_loop(char *name, void (*func) (void)) {
if (uwsgi.loops_cnt >= MAX_LOOPS) {
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
exit(1);
struct uwsgi_loop *old_loop = NULL, *loop = uwsgi.loops;
while (loop) {
// check if the loop engine is already registered
if (!strcmp(name, loop->name))
return;
old_loop = loop;
loop = loop->next;
}
uwsgi.loops[uwsgi.loops_cnt].name = name;
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
uwsgi.loops_cnt++;
loop = uwsgi_calloc(sizeof(struct uwsgi_loop));
loop->name = name;
loop->loop = func;
if (old_loop) {
old_loop->next = loop;
}
else {
uwsgi.loops = loop;
}
}
void *uwsgi_get_loop(char *name) {
int i;
struct uwsgi_loop *loop = uwsgi.loops;
for (i = 0; i < uwsgi.loops_cnt; i++) {
if (!strcmp(name, uwsgi.loops[i].name)) {
return uwsgi.loops[i].loop;
while (loop) {
if (!strcmp(name, loop->name)) {
return loop->loop;
}
loop = loop->next;
}
return NULL;
}
void *simple_loop(void *arg1) {
/*
this is the default (simple) loop.
it will run simple_loop_run function for each spawned thread
simple_loop_run monitors sockets and signals descriptors
and manages them.
*/
void simple_loop() {
uwsgi_loop_cores_run(simple_loop_run);
}
void uwsgi_loop_cores_run(void *(*func) (void *)) {
int i;
for (i = 1; i < uwsgi.threads; i++) {
long j = i;
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
}
long y = 0;
func((void *) y);
}
void uwsgi_setup_thread_req(long core_id, struct wsgi_request *wsgi_req) {
int i;
sigset_t smask;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
// run per-thread socket hook
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->proto_thread_fixup) {
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
}
uwsgi_sock = uwsgi_sock->next;
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
}
}
void simple_loop_run_int(int core_id) {
long y = core_id;
simple_loop_run((void *) y);
}
void *simple_loop_run(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
#ifdef UWSGI_THREADING
int i;
sigset_t smask;
if (uwsgi.threads > 1) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
// run per-thread socket hook
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->proto_thread_fixup) {
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
}
uwsgi_sock = uwsgi_sock->next;
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_thread) {
uwsgi.p[i]->init_thread(core_id);
}
}
}
uwsgi_setup_thread_req(core_id, wsgi_req);
}
#endif
// initialize the main event queue to monitor sockets
int main_queue = event_queue_init();
@@ -97,7 +141,7 @@ void *simple_loop(void *arg1) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
if (wsgi_req_recv(main_queue, wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
+192 -840
View File
File diff suppressed because it is too large Load Diff
+278
View File
@@ -0,0 +1,278 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// check if all of the workers are dead and exit uWSGI
void uwsgi_master_check_death() {
if (uwsgi_instance_is_dying) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
return;
}
}
uwsgi_log("goodbye to uWSGI.\n");
exit(0);
}
}
// check if all of the workers are dead, and trigger a reload
int uwsgi_master_check_reload(char **argv) {
if (uwsgi_instance_is_reloading) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
return 0;
}
}
uwsgi_reload(argv);
// never here (unless in shared library mode)
return -1;
}
return 0;
}
// check for chain reload
void uwsgi_master_check_chain() {
if (!uwsgi.status.chain_reloading) return;
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
int i;
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
uwsgi_curse(i, SIGHUP);
break;
}
}
uwsgi_unblock_signal(SIGHUP);
}
// special function for assuming all of the workers are dead
void uwsgi_master_commit_status() {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].pid = 0;
}
}
void uwsgi_master_check_idle() {
static time_t last_request_timecheck = 0;
static uint64_t last_request_count = 0;
int i;
int waitpid_status;
if (!uwsgi.idle || uwsgi.status.is_cheap)
return;
uwsgi.current_time = uwsgi_now();
if (!last_request_timecheck)
last_request_timecheck = uwsgi.current_time;
// security check, stop the check if there are busy workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi_worker_is_busy(i)) {
return;
}
}
}
if (last_request_count != uwsgi.workers[0].requests) {
last_request_timecheck = uwsgi.current_time;
last_request_count = uwsgi.workers[0].requests;
}
// a bit of over-engeneering to avoid clock skews
else if (last_request_timecheck < uwsgi.current_time && (uwsgi.current_time - last_request_timecheck > uwsgi.idle)) {
uwsgi_log("workers have been inactive for more than %d seconds (%llu-%llu)\n", uwsgi.idle, (unsigned long long) uwsgi.current_time, (unsigned long long) last_request_timecheck);
uwsgi.status.is_cheap = 1;
if (uwsgi.die_on_idle) {
if (uwsgi.has_emperor) {
char byte = 22;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
kill_them_all(0);
}
}
else {
kill_them_all(0);
}
return;
}
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
last_request_timecheck = 0;
}
}
void uwsgi_master_check_workers_deadline() {
int i;
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);
}
}
/* 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);
}
}
// then for evil memory checkers
if (uwsgi.evil_reload_on_as) {
if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) {
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;
}
}
if (uwsgi.evil_reload_on_rss) {
if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) {
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;
}
}
// 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) {
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) {
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);
}
}
// need to find a better way
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
}
}
void uwsgi_master_check_gateways_deadline() {
int i;
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) {
kill(ushared->gateways[i].pid, SIGKILL);
}
ushared->gateways_harakiri[i] = 0;
}
}
}
}
void uwsgi_master_check_mules_deadline() {
int i;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
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;
}
}
}
}
void uwsgi_master_check_spoolers_deadline() {
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;
}
uspool = uspool->next;
}
}
int uwsgi_master_check_spoolers_death(int diedpid) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->pid > 0 && diedpid == uspool->pid) {
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
uspool->respawned++;
uspool->pid = spooler_start(uspool);
return -1;
}
uspool = uspool->next;
}
return 0;
}
int uwsgi_master_check_emperor_death(int diedpid) {
if (uwsgi.emperor_pid >= 0 && diedpid == uwsgi.emperor_pid) {
uwsgi_log_verbose("!!! Emperor died !!!\n");
uwsgi_emperor_start();
return -1;
}
return 0;
}
int uwsgi_master_check_mules_death(int diedpid) {
int i;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid == diedpid) {
uwsgi_log("OOOPS mule %d (pid: %d) crippled...trying respawn...\n", i + 1, uwsgi.mules[i].pid);
uwsgi_mule(i + 1);
return -1;
}
}
return 0;
}
int uwsgi_master_check_gateways_death(int diedpid) {
int i;
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid == diedpid) {
gateway_respawn(i);
return -1;
}
}
return 0;
}
int uwsgi_master_check_daemons_death(int diedpid) {
/* reload the daemons */
if (uwsgi_daemon_check_pid_reload(diedpid)) {
return -1;
}
return 0;
}
int uwsgi_worker_is_busy(int wid) {
int i;
for(i=0;i<uwsgi.cores;i++) {
if (uwsgi.workers[wid].cores[i].in_request) {
return 1;
}
}
return 0;
}
+174
View File
@@ -0,0 +1,174 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_master_manage_events(int interesting_fd) {
// is a logline ?
if (uwsgi.log_master && !uwsgi.threaded_logger) {
// stderr log ?
if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) {
uwsgi_master_log();
return 0;
}
// req log ?
if (uwsgi.req_log_master && interesting_fd == uwsgi.shared->worker_req_log_pipe[0]) {
uwsgi_master_req_log();
return 0;
}
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats);
return 0;
}
}
// a zerg connection ?
if (uwsgi.zerg_server) {
if (interesting_fd == uwsgi.zerg_server_fd) {
uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL);
return 0;
}
}
// emperor event ?
if (uwsgi.has_emperor) {
if (interesting_fd == uwsgi.emperor_fd) {
uwsgi_master_manage_emperor();
return 0;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
uwsgi.status.is_cheap = 0;
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
// how many worker we need to respawn ?
int needed = uwsgi.numproc;
// if in cheaper mode, just respawn the minimal amount
if (uwsgi.cheaper) {
needed = uwsgi.cheaper_count;
}
int i;
for (i = 1; i <= needed; i++) {
if (uwsgi_respawn_worker(i))
return -1;
}
// here we continue instead of returning
break;
}
uwsgi_sock = uwsgi_sock->next;
}
}
// an SNMP request ?
if (uwsgi.snmp_addr && interesting_fd == uwsgi.snmp_fd) {
uwsgi_master_manage_snmp(uwsgi.snmp_fd);
return 0;
}
// a UDP request ?
if (uwsgi.udp_socket && interesting_fd == uwsgi.udp_fd) {
uwsgi_master_manage_udp(uwsgi.udp_fd);
return 0;
}
// check if some file monitor is ready
// no need to lock as we are only getting registered items (and only the master can register them)
int i;
for (i = 0; i < ushared->files_monitored_cnt; i++) {
if (ushared->files_monitored[i].registered) {
if (interesting_fd == ushared->files_monitored[i].fd) {
struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd);
// now call the file_monitor handler
if (uf)
uwsgi_route_signal(uf->sig);
return 0;
}
}
}
// check if some timer elapsed
// no need to lock again
for (i = 0; i < ushared->timers_cnt; i++) {
if (ushared->timers[i].registered) {
if (interesting_fd == ushared->timers[i].fd) {
struct uwsgi_timer *ut = event_queue_ack_timer(interesting_fd);
// now call the timer handler
if (ut)
uwsgi_route_signal(ut->sig);
return 0;
}
}
}
uint8_t uwsgi_signal;
// check for worker signal
if (interesting_fd == uwsgi.shared->worker_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO restart workers here
uwsgi_log_verbose("lost connection with workers !!!\n");
close(interesting_fd);
}
return 0;
}
// check for spooler signal
if (uwsgi.spoolers) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO restart spoolers here
uwsgi_log_verbose("lost connection with spoolers\n");
close(interesting_fd);
}
return 0;
}
}
// check for mules signal
if (uwsgi.mules_cnt > 0) {
if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO respawn mules here
uwsgi_log_verbose("lost connection with mules\n");
close(interesting_fd);
}
// return 0;
}
}
return 0;
}
+667 -257
View File
File diff suppressed because it is too large Load Diff
+229 -211
View File
@@ -19,14 +19,14 @@ void mule_send_msg(int fd, char *message, size_t len) {
if (write(fd, message, len) != (ssize_t) len) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("mule_send_msg()");
}
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("mule_send_msg()");
}
}
}
@@ -34,54 +34,66 @@ void uwsgi_mule(int id) {
int i;
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
pid_t pid = uwsgi_fork(uwsgi.mules[id - 1].name);
if (pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = getpid();
uwsgi.mypid = uwsgi.mules[id - 1].pid;
uwsgi_fixup_fds(0, id, NULL);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.my_signal_socket = uwsgi.mules[id - 1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
uwsgi_close_all_sockets();
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.mules[id-1].patch) {
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
// never here
break;
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here ?
end_me(1);
}
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = pid;
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = pid;
uwsgi_log("spawned uWSGI mule %d (pid: %d)\n", id, (int) pid);
}
}
@@ -90,7 +102,7 @@ int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
while(umf) {
while (umf) {
if (umf->mule->id == muleid) {
return 1;
}
@@ -103,54 +115,54 @@ int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
int farm_has_signaled(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
while (umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
}
int farm_has_msg(int fd) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while(umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
int i;
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
while (umf) {
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
return 1;
}
umf = umf->next;
}
}
return 0;
return 0;
}
void uwsgi_mule_add_farm_to_queue(int queue) {
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
}
}
}
void uwsgi_mule_handler() {
ssize_t len;
uint8_t uwsgi_signal;
int rlen;
int interesting_fd;
// this must be configurable
char message[65536];
@@ -158,12 +170,12 @@ void uwsgi_mule_handler() {
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1]);
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
uwsgi_mule_add_farm_to_queue(mule_queue);
for(;;) {
for (;;) {
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
if (rlen <= 0) {
continue;
@@ -172,33 +184,33 @@ void uwsgi_mule_handler() {
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
}
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
}
}
else {
int i,found = 0;
for(i=0;i<256;i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
int i, found = 0;
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule_msg) {
if (uwsgi.p[i]->mule_msg(message, len)) {
found = 1;
break;
}
}
}
}
if (!found)
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
uwsgi_log("*** mule %d received a %ld bytes message ***\n", uwsgi.muleid, (long) len);
}
}
}
@@ -209,7 +221,7 @@ struct uwsgi_mule *get_mule_by_id(int id) {
int i;
for(i=0;i<uwsgi.mules_cnt;i++) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].id == id) {
return &uwsgi.mules[i];
}
@@ -220,229 +232,235 @@ struct uwsgi_mule *get_mule_by_id(int id) {
struct uwsgi_farm *get_farm_by_name(char *name) {
int i;
int i;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (!strcmp(uwsgi.farms[i].name, name)) {
return &uwsgi.farms[i];
}
}
return NULL;
return NULL;
}
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while(uwsgi_mf) {
old_umf = uwsgi_mf;
if (!uwsgi_mf) {
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
uwsgi_mf = *umf;
}
else {
while (uwsgi_mf) {
old_umf = uwsgi_mf;
uwsgi_mf = uwsgi_mf->next;
}
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
old_umf->next = uwsgi_mf;
}
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
uwsgi_mf->mule = um;
uwsgi_mf->next = NULL;
return uwsgi_mf;
return uwsgi_mf;
}
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
ssize_t len = 0;
struct pollfd *mulepoll;
int count = 4;
int farms_count = 0;
uint8_t uwsgi_signal;
int i;
ssize_t len = 0;
struct pollfd *mulepoll;
int count = 4;
int farms_count = 0;
uint8_t uwsgi_signal;
int i;
if (uwsgi.muleid == 0) return -1;
if (uwsgi.muleid == 0)
return -1;
if (manage_signals) count = 2;
if (manage_signals)
count = 2;
if (!manage_farms) goto next;
if (!manage_farms)
goto next;
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
}
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid))
farms_count++;
}
next:
if (timeout > -1) timeout = timeout*1000;
if (timeout > -1)
timeout = timeout * 1000;
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count + farms_count));
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
mulepoll[0].events = POLLIN;
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
mulepoll[1].events = POLLIN;
if (count > 2) {
mulepoll[2].fd = uwsgi.signal_socket;
mulepoll[2].events = POLLIN;
mulepoll[3].fd = uwsgi.my_signal_socket;
mulepoll[3].events = POLLIN;
}
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1];
mulepoll[0].events = POLLIN;
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
mulepoll[1].events = POLLIN;
if (count > 2) {
mulepoll[2].fd = uwsgi.signal_socket;
mulepoll[2].events = POLLIN;
mulepoll[3].fd = uwsgi.my_signal_socket;
mulepoll[3].events = POLLIN;
}
if (farms_count > 0) {
int tmp_cnt = 0;
for(i=0;i<uwsgi.farms_cnt;i++) {
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
mulepoll[count+tmp_cnt].events = POLLIN;
mulepoll[count + tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
mulepoll[count + tmp_cnt].events = POLLIN;
tmp_cnt++;
}
}
}
}
int ret = poll(mulepoll, count+farms_count, timeout);
if (ret <= 0) {
uwsgi_error("poll");
}
else {
if (mulepoll[0].revents & POLLIN) {
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
}
else if (mulepoll[1].revents & POLLIN) {
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
}
else {
if (count > 2) {
int interesting_fd = -1;
if (mulepoll[2].revents & POLLIN) {
interesting_fd = mulepoll[2].fd;
}
else if (mulepoll[3].revents & POLLIN) {
interesting_fd = mulepoll[3].fd;
}
int ret = poll(mulepoll, count + farms_count, timeout);
if (ret <= 0) {
uwsgi_error("poll");
}
else {
if (mulepoll[0].revents & POLLIN) {
len = read(uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1], message, buffer_size);
}
else if (mulepoll[1].revents & POLLIN) {
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
}
else {
if (count > 2) {
int interesting_fd = -1;
if (mulepoll[2].revents & POLLIN) {
interesting_fd = mulepoll[2].fd;
}
else if (mulepoll[3].revents & POLLIN) {
interesting_fd = mulepoll[3].fd;
}
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
// set the error condition
len = -1;
goto clear;
}
}
goto clear;
}
}
// read messages in the farm
for(i=0;i<farms_count;i++) {
if (mulepoll[count+i].revents & POLLIN) {
len = read(mulepoll[count+i].fd, message, buffer_size);
break;
}
}
}
}
for (i = 0; i < farms_count; i++) {
if (mulepoll[count + i].revents & POLLIN) {
len = read(mulepoll[count + i].fd, message, buffer_size);
break;
}
}
}
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
if (len < 0) {
uwsgi_error("read()");
goto clear;
}
clear:
free(mulepoll);
return len;
free(mulepoll);
return len;
}
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, value);
uwsgi_string_new_list(&uwsgi.mules_patches, value);
}
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
int i;
for(i=0;i<atoi(value);i++) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
}
for (i = 0; i < atoi(value); i++) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
}
}
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
uwsgi.farms_cnt++;
uwsgi_string_new_list(&uwsgi.farms_list, value);
uwsgi_string_new_list(&uwsgi.farms_list, value);
}
void uwsgi_setup_mules_and_farms() {
int i;
if (uwsgi.mules_cnt > 0) {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
uwsgi.mules[i].id = i + 1;
uwsgi.mules[i].id = i + 1;
snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", i + 1);
}
}
snprintf(uwsgi.mules[i].name, 0xff, "uWSGI mule %d", i + 1);
}
}
if (uwsgi.farms_cnt > 0) {
uwsgi.farms = (struct uwsgi_farm *) uwsgi_calloc_shared(sizeof(struct uwsgi_farm) * uwsgi.farms_cnt);
if (uwsgi.farms_cnt > 0) {
uwsgi.farms = (struct uwsgi_farm *) uwsgi_calloc_shared(sizeof(struct uwsgi_farm) * uwsgi.farms_cnt);
struct uwsgi_string_list *farm_name = uwsgi.farms_list;
for (i = 0; i < uwsgi.farms_cnt; i++) {
struct uwsgi_string_list *farm_name = uwsgi.farms_list;
for (i = 0; i < uwsgi.farms_cnt; i++) {
char *farm_value = uwsgi_str(farm_name->value);
char *farm_value = uwsgi_str(farm_name->value);
char *mules_list = strchr(farm_value, ':');
if (!mules_list) {
uwsgi_log("invalid farm value (%s) must be in the form name:mule[,muleN].\n", farm_value);
exit(1);
}
char *mules_list = strchr(farm_value, ':');
if (!mules_list) {
uwsgi_log("invalid farm value (%s) must be in the form name:mule[,muleN].\n", farm_value);
exit(1);
}
mules_list[0] = 0;
mules_list++;
mules_list[0] = 0;
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
free(farm_value);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
char *p = strtok(mules_list, ",");
while (p != NULL) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
exit(1);
}
char *p = strtok(mules_list, ",");
while (p != NULL) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
exit(1);
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
farm_name = farm_name->next;
farm_name = farm_name->next;
}
}
}
}
}
+18 -13
View File
@@ -16,25 +16,28 @@ void uwsgi_systemd_notify(char *message) {
iovec[1].iov_len = strlen(message);
iovec[2].iov_base = "\n";
iovec[2].iov_len = 1;
iovec[2].iov_len = 1;
msghdr->msg_iovlen = 3;
sendmsg(uwsgi.notification_fd, msghdr, 0);
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
uwsgi_error("sendmsg()");
}
}
void uwsgi_systemd_notify_ready(void) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
msghdr->msg_iovlen = 1;
sendmsg(uwsgi.notification_fd, msghdr, 0);
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
uwsgi_error("sendmsg()");
}
}
@@ -49,24 +52,26 @@ void uwsgi_systemd_init(char *systemd_socket) {
return;
}
size_t len = strlen(systemd_socket);
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
memset(sd_sun, 0, sizeof(struct sockaddr_un));
sd_sun->sun_family = AF_UNIX;
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
strncpy(sd_sun->sun_path, systemd_socket, UMIN(len, sizeof(sd_sun->sun_path)));
if (sd_sun->sun_path[0] == '@')
sd_sun->sun_path[0] = 0;
msghdr = uwsgi_malloc(sizeof(struct msghdr));
memset(msghdr, 0, sizeof(struct msghdr));
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec) * 3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec) * 3);
msghdr->msg_name = sd_sun;
msghdr->msg_namelen = sizeof(struct sockaddr_un);
msghdr->msg_namelen = sizeof(struct sockaddr_un) - (sizeof(sd_sun->sun_path) - len);
uwsgi.notification_object = msghdr;
uwsgi.notify = uwsgi_systemd_notify;
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
+509
View File
@@ -0,0 +1,509 @@
#include "uwsgi.h"
/*
uWSGI offloading subsystem
steps to offload a task
1) allocate a uwsgi_offload_request structure (could be on stack)
struct uwsgi_offload_request uor;
2) prepare it for a specific engine (last argument is the takeover flag)
uwsgi_offload_setup(my_engine, &uor, 1)
3) run it (last argument is the waiter)
int uwsgi_offload_run(wsgi_req, &uor, NULL);
between 2 and 3 you can set specific values
*/
extern struct uwsgi_server uwsgi;
#define uwsgi_offload_retry if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) return 0;
#define uwsgi_offload_0r_1w(x, y) if (event_queue_del_fd(ut->queue, x, event_queue_read())) return -1;\
if (event_queue_fd_read_to_write(ut->queue, y)) return -1;
void uwsgi_offload_setup(struct uwsgi_offload_engine *uoe, struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req, uint8_t takeover) {
memset(uor, 0, sizeof(struct uwsgi_offload_request));
uor->engine = uoe;
uor->s = wsgi_req->fd;
uor->fd = -1;
uor->fd2 = -1;
// an engine could changes behaviour based on pipe anf takeover values
uor->pipe[0] = -1;
uor->pipe[1] = -1;
uor->takeover = takeover;
}
static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
struct uwsgi_core *uc = &uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id];
uc->offloaded_requests++;
// round robin
if (uc->offload_rr >= uwsgi.offload_threads) {
uc->offload_rr = 0;
}
struct uwsgi_thread *ut = uwsgi.offload_thread[uc->offload_rr];
uc->offload_rr++;
if (write(ut->pipe[0], uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
if (uor->takeover) {
wsgi_req->fd_closed = 0;
}
return -1;
}
return 0;
}
/*
transfer offload engine:
name -> socket name
ubuf -> data to send
*/
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);
if (uor->fd < 0) {
uwsgi_error("u_offload_transfer_prepare()/connect()");
return -1;
}
return 0;
}
/*
sendfile offload engine:
name -> filename to transfer
fd -> file descriptor of file to transfer
fd2 -> sendfile destination (default wsgi_req->fd)
len -> size of the file or amount of data to transfer
pos -> position in the file
*/
static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name && uor->fd == -1) return -1;
if (uor->name) {
uor->fd = open(uor->name, O_RDONLY | O_NONBLOCK);
if (uor->fd < 0) {
uwsgi_error_open(uor->name);
return -1;
}
}
// make a fstat to get the file size
if (!uor->len) {
struct stat st;
if (fstat(uor->fd, &st)) {
uwsgi_error("u_offload_sendfile_prepare()/fstat()");
if (uor->name) {
close(uor->fd);
}
return -1;
}
uor->len = st.st_size;
}
if (uor->fd2 == -1) {
uor->fd2 = uor->s;
}
uor->s = -1;
return 0;
}
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
// close the socket and the file descriptor
if (uor->takeover && uor->s > -1) {
close(uor->s);
}
if (uor->fd != -1) {
close(uor->fd);
}
if (uor->fd2 != -1) {
close(uor->fd2);
}
// remove the structure from the linked list;
struct uwsgi_offload_request *prev = uor->prev;
struct uwsgi_offload_request *next = uor->next;
if (uor == ut->offload_requests_head) {
ut->offload_requests_head = next;
}
if (uor == ut->offload_requests_tail) {
ut->offload_requests_tail = prev;
}
if (prev) {
prev->next = next;
}
if (next) {
next->prev = prev;
}
if (uor->buf) {
free(uor->buf);
}
if (uor->ubuf) {
uwsgi_buffer_destroy(uor->ubuf);
}
if (uor->pipe[0] != -1) {
close(uor->pipe[1]);
close(uor->pipe[0]);
}
free(uor);
}
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
if (!ut->offload_requests_head) {
ut->offload_requests_head = uor;
}
if (ut->offload_requests_tail) {
ut->offload_requests_tail->next = uor;
uor->prev = ut->offload_requests_tail;
}
ut->offload_requests_tail = uor;
}
static struct uwsgi_offload_request *uwsgi_offload_get_by_fd(struct uwsgi_thread *ut, int s) {
struct uwsgi_offload_request *uor = ut->offload_requests_head;
while (uor) {
if (uor->s == s || uor->fd == s || uor->fd2 == s) {
return uor;
}
uor = uor->next;
}
return NULL;
}
static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
int i;
void *events = event_queue_alloc(uwsgi.offload_threads_events);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.offload_threads_events);
for (i = 0; i < nevents; i++) {
int interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == ut->pipe[1]) {
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
ssize_t len = read(ut->pipe[1], uor, sizeof(struct uwsgi_offload_request));
if (len != sizeof(struct uwsgi_offload_request)) {
uwsgi_error("read()");
free(uor);
continue;
}
// cal the event function for the first time
if (uor->engine->event_func(ut, uor, -1)) {
uwsgi_offload_close(ut, uor);
continue;
}
uwsgi_offload_append(ut, uor);
continue;
}
// get the task from the interesting fd
struct uwsgi_offload_request *uor = uwsgi_offload_get_by_fd(ut, interesting_fd);
if (!uor)
continue;
// run the hook
if (uor->engine->event_func(ut, uor, interesting_fd)) {
uwsgi_offload_close(ut, uor);
}
}
}
}
struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
the offload task starts after having acquired the file fd
uor->len -> the size of the file
uor->pos -> start writing from pos (default 0)
status: none
*/
static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (len < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
off_t sbytes = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, 0, NULL, &sbytes, 0);
// transfer finished
if (ret == -1) {
uor->pos += sbytes;
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#elif defined(__APPLE__)
off_t len = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
// transfer finished
if (ret == -1) {
uor->pos += len;
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#endif
return -1;
}
/*
the offload task starts soon after the call to connect()
status:
0 -> waiting for connection on fd
1 -> sending request to fd (write event)
2 -> start waiting for read on s and fd
3 -> write to s
4 -> write to fd
*/
static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_write(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// waiting for connection
case 0:
if (fd == uor->fd) {
uor->status = 1;
// ok try to send the request right now...
return u_offload_transfer_do(ut, uor, fd);
}
return -1;
// write event (or just connected)
case 1:
if (fd == uor->fd) {
rlen = write(uor->fd, uor->ubuf->buf + uor->written, uor->ubuf->pos-uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= (size_t)uor->ubuf->pos) {
uor->status = 2;
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()");
}
}
return -1;
// read event from s or fd
case 2:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
if (fd == uor->fd) {
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
uwsgi_offload_0r_1w(uor->fd, uor->s)
uor->status = 3;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> read()/fd");
}
}
else if (fd == uor->s) {
rlen = read(uor->s, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
uwsgi_offload_0r_1w(uor->s, uor->fd)
uor->status = 4;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> read()/s");
}
}
return -1;
// write event on s
case 3:
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_fd_write_to_read(ut->queue, uor->s)) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 2;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()/s");
}
return -1;
// write event on fd
case 4:
rlen = write(uor->fd, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
uor->status = 2;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()/fd");
}
return -1;
default:
break;
}
return -1;
}
int uwsgi_offload_run(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor, int *wait) {
if (uor->engine->prepare_func(wsgi_req, uor)) {
return -1;
}
if (wait) {
if (pipe(uor->pipe)) {
uwsgi_error("uwsgi_offload_setup()/pipe()");
return -1;
}
*wait = uor->pipe[0];
uwsgi_socket_nb(uor->pipe[0]);
uwsgi_socket_nb(uor->pipe[1]);
}
if (uor->takeover) {
wsgi_req->fd_closed = 1;
}
if (uwsgi_offload_enqueue(wsgi_req, uor)) {
close(uor->pipe[0]);
close(uor->pipe[1]);
if (uor->takeover) {
wsgi_req->fd_closed = 0;
}
return -1;
}
return 0;
};
struct uwsgi_offload_engine *uwsgi_offload_engine_by_name(char *name) {
struct uwsgi_offload_engine *uoe = uwsgi.offload_engines;
while(uoe) {
if (!strcmp(name, uoe->name)) {
return uoe;
}
}
return NULL;
}
struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*prepare_func)(struct wsgi_request *, struct uwsgi_offload_request *), int (*event_func) (struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
struct uwsgi_offload_engine *old_engine=NULL,*engine=uwsgi.offload_engines;
while(engine) {
if (!strcmp(engine->name, name)) {
return engine;
}
old_engine = engine;
engine = engine->next;
}
engine = uwsgi_calloc(sizeof(struct uwsgi_offload_engine));
engine->name = name;
engine->prepare_func = prepare_func;
engine->event_func = event_func;
if (old_engine) {
old_engine->next = engine;
}
else {
uwsgi.offload_engines = engine;
}
return engine;
}
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);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_sendfile, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname, struct uwsgi_buffer *ubuf) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_transfer, &uor, wsgi_req, 1);
uor.name = socketname;
uor.ubuf = ubuf;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+92 -62
View File
@@ -2,7 +2,29 @@
extern struct uwsgi_server uwsgi;
static int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_ELF
static void uwsgi_plugin_parse_section(char *filename) {
size_t s_len = 0;
char *buf = uwsgi_elf_section(filename, "uwsgi", &s_len);
if (buf) {
char *ctx = NULL;
char *p = strtok_r(buf, "\n", &ctx);
while (p) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
p = strtok_r(NULL, "\n", &ctx);
}
free(buf);
}
}
#endif
int plugin_already_loaded(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -12,7 +34,7 @@ static int plugin_already_loaded(const char *plugin) {
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
if (uwsgi.p[i]->alias) {
if (!strcmp(plugin, uwsgi.p[i]->alias)) {
@@ -20,29 +42,29 @@ static int plugin_already_loaded(const char *plugin) {
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
}
for(i=0;i<uwsgi.gp_cnt;i++) {
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->name) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
if (!strcmp(plugin, uwsgi.gp[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
return 1;
}
}
if (uwsgi.gp[i]->alias) {
if (!strcmp(plugin, uwsgi.gp[i]->alias)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
}
}
}
return 1;
}
}
}
return 0;
}
@@ -54,9 +76,8 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
char *plugin_filename = NULL;
int need_free = 0;
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
char *plugin_name = uwsgi_strip(uwsgi_str(plugin));
char *plugin_symbol_name_start = plugin_name;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
@@ -66,7 +87,7 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
if (colon) {
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
plugin_name = colon + 1;
colon[0] = ':';
}
@@ -79,10 +100,13 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// step 1: check for absolute plugin (stop if it fails)
if (strchr(plugin_name, '/')) {
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_name);
#endif
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
uwsgi_log("%s\n", dlerror());
goto end;
}
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
@@ -93,8 +117,11 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
while (pdir) {
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
if (plugin_handle) {
plugin_abs_path = plugin_filename;
@@ -109,19 +136,22 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// last step: search in compile-time plugin_dir
if (!plugin_handle) {
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
plugin_abs_path = plugin_filename;
//free(plugin_filename);
}
success:
if (!plugin_handle) {
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
// is it a link ?
memset(linkpath_buf, 0, 1024);
@@ -129,13 +159,12 @@ success:
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strncpy(linkpath, linkpath_buf, linkpath_size+1);
strncpy(linkpath, linkpath_buf, linkpath_size + 1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
#endif
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
if (!slash) {
slash = linkpath;
@@ -143,16 +172,16 @@ success:
else {
slash++;
}
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash)-3, "",0);
plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
}
}
if (up) {
if (up) {
if (!up->name) {
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
@@ -162,8 +191,8 @@ success:
}
if (plugin_already_loaded(up->name)) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
if (plugin_filename)
@@ -178,8 +207,8 @@ success:
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
op++;
}
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
@@ -192,14 +221,14 @@ success:
free(plugin_entry_symbol);
return NULL;
}
}
if (modifier != -1) {
fill_plugin_table(modifier, up);
fill_plugin_table(modifier, up);
up->modifier1 = modifier;
}
else {
fill_plugin_table(up->modifier1, up);
fill_plugin_table(up->modifier1, up);
}
if (need_free)
free(plugin_name);
@@ -210,10 +239,10 @@ success:
if (up->on_load)
up->on_load();
return plugin_handle;
}
}
if (!has_option)
uwsgi_log( "%s\n", dlerror());
}
uwsgi_log("%s\n", dlerror());
}
end:
if (need_free)
@@ -228,14 +257,14 @@ int uwsgi_try_autoload(char *option) {
DIR *d;
struct dirent *dp;
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while (pdir) {
d = opendir(pdir->value);
if (d) {
while ((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(pdir->value, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
@@ -248,27 +277,28 @@ int uwsgi_try_autoload(char *option) {
}
closedir(d);
}
pdir = pdir->next;
}
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
// last step: search in compile-time plugin_dir
d = opendir(UWSGI_PLUGIN_DIR);
if (!d) return 0;
if (!d)
return 0;
while((dp = readdir(d)) != NULL) {
while ((dp = readdir(d)) != NULL) {
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
if (uwsgi_load_plugin(-1, filename, option)) {
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
free(filename);
closedir(d);
// add new options
build_options();
return 1;
}
free(filename);
}
}
}
closedir(d);
+107
View File
@@ -0,0 +1,107 @@
#include <uwsgi.h>
/*
upload progress facilities
*/
extern struct uwsgi_server uwsgi;
char *uwsgi_upload_progress_create(struct wsgi_request *wsgi_req, int *fd) {
const char *x_progress_id = "X-Progress-ID=";
char *xpi_ptr = (char *) x_progress_id;
uint16_t i;
char *upload_progress_filename = NULL;
if (wsgi_req->uri_len <= 51)
return NULL;
for (i = 0; i < wsgi_req->uri_len; i++) {
if (wsgi_req->uri[i] == xpi_ptr[0]) {
if (xpi_ptr[0] == '=') {
if (wsgi_req->uri + i + 36 <= wsgi_req->uri + wsgi_req->uri_len) {
upload_progress_filename = wsgi_req->uri + i + 1;
}
break;
}
xpi_ptr++;
}
else {
xpi_ptr = (char *) x_progress_id;
}
}
// now check for valid uuid (from spec available at http://en.wikipedia.org/wiki/Universally_unique_identifier)
if (!upload_progress_filename)
return NULL;
uwsgi_log("upload progress uuid = %.*s\n", 36, upload_progress_filename);
if (!check_hex(upload_progress_filename, 8))
return NULL;
if (upload_progress_filename[8] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 9, 4))
return NULL;
if (upload_progress_filename[13] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 14, 4))
return NULL;
if (upload_progress_filename[18] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 19, 4))
return NULL;
if (upload_progress_filename[23] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 24, 12))
return NULL;
upload_progress_filename = uwsgi_concat4n(uwsgi.upload_progress, strlen(uwsgi.upload_progress), "/", 1, upload_progress_filename, 36, ".js", 3);
// here we use O_EXCL to avoid eventual application bug in uuid generation/using
*fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP);
if (*fd < 0) {
uwsgi_error_open(upload_progress_filename);
free(upload_progress_filename);
return NULL;
}
return upload_progress_filename;
}
int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t remains) {
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) {
return -1;
}
if (lseek(fd, 0, SEEK_SET)) {
uwsgi_error("uwsgi_upload_progress_update()/lseek()");
return -1;
}
if (write(fd, buf, ret) != ret) {
uwsgi_error("uwsgi_upload_progress_update()/write()");
return -1;
}
if (fsync(fd)) {
uwsgi_error("uwsgi_upload_progress_update()/fsync()");
return -1;
}
return 0;
}
void uwsgi_upload_progress_destroy(char *filename, int fd) {
close(fd);
if (unlink(filename)) {
uwsgi_error("uwsgi_upload_progress_destroy()/unlink()");
}
free(filename);
}
+676 -1674
View File
File diff suppressed because it is too large Load Diff
+97 -89
View File
@@ -4,132 +4,137 @@ extern struct uwsgi_server uwsgi;
void uwsgi_init_queue() {
if (!uwsgi.queue_blocksize)
uwsgi.queue_blocksize = 8192;
uwsgi.queue_blocksize = 8192;
if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
exit(1);
}
if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
exit(1);
}
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
int queue_fd;
struct stat qst;
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
int queue_fd;
struct stat qst;
if (stat(uwsgi.queue_store, &qst)) {
uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (queue_fd >= 0) {
// fill the queue store
if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
exit(1);
}
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
}
if (stat(uwsgi.queue_store, &qst)) {
uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (queue_fd >= 0) {
// fill the queue store
if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t) qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
exit(1);
}
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
}
if (queue_fd < 0) {
uwsgi_error_open(uwsgi.queue_store);
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
if (queue_fd < 0) {
uwsgi_error_open(uwsgi.queue_store);
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue+=16;
}
else {
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size)+16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue+=16;
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue += 16;
close(queue_fd);
}
else {
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue += 16;
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
uwsgi_log("*** Queue subsystem initialized: %luMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
}
char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
char *uwsgi_queue_get(uint64_t index, uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (index >= uwsgi.queue_size) return NULL;
if (index >= uwsgi.queue_size)
return NULL;
ptr = ptr + (uwsgi.queue_blocksize*index);
ptr = ptr + (uwsgi.queue_blocksize * index);
uqi = (struct uwsgi_queue_item *) ptr;
*size = uqi->size;
return ptr + sizeof(struct uwsgi_queue_item);
}
char *uwsgi_queue_pop(uint64_t *size) {
char *uwsgi_queue_pop(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (uwsgi.queue_header->pos == 0) {
uwsgi.queue_header->pos = uwsgi.queue_size-1;
uwsgi.queue_header->pos = uwsgi.queue_size - 1;
}
else {
uwsgi.queue_header->pos--;
}
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
if (!uqi->size)
return NULL;
*size = uqi->size;
*size = uqi->size;
// remove item
uqi->size = 0;
return ptr + sizeof(struct uwsgi_queue_item);
return ptr + sizeof(struct uwsgi_queue_item);
}
char *uwsgi_queue_pull(uint64_t *size) {
char *uwsgi_queue_pull(uint64_t * size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
char *ptr = (char *) uwsgi.queue;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pull_pos);
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pull_pos);
uqi = (struct uwsgi_queue_item *) ptr;
if (!uqi->size) return NULL;
if (!uqi->size)
return NULL;
*size = uqi->size;
uwsgi.queue_header->pull_pos++;
if (uwsgi.queue_header->pull_pos >= uwsgi.queue_size) uwsgi.queue_header->pull_pos = 0;
if (uwsgi.queue_header->pull_pos >= uwsgi.queue_size)
uwsgi.queue_header->pull_pos = 0;
// remove item
uqi->size = 0;
return ptr + sizeof(struct uwsgi_queue_item);
}
@@ -142,9 +147,10 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
if (!size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.queue_header->pos);
ptr = ptr + (uwsgi.queue_blocksize * uwsgi.queue_header->pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
@@ -154,33 +160,35 @@ int uwsgi_queue_push(char *message, uint64_t size) {
memcpy(ptr, message, size);
uwsgi.queue_header->pos++;
if (uwsgi.queue_header->pos >= uwsgi.queue_size) uwsgi.queue_header->pos = 0;
if (uwsgi.queue_header->pos >= uwsgi.queue_size)
uwsgi.queue_header->pos = 0;
return 1;
}
int uwsgi_queue_set(uint64_t pos, char *message, uint64_t size) {
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
struct uwsgi_queue_item *uqi;
char *ptr = (char *) uwsgi.queue;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
if (!size)
return 0;
if (pos >= uwsgi.queue_size) return 0;
if (pos >= uwsgi.queue_size)
return 0;
ptr = ptr + (uwsgi.queue_blocksize*pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr = ptr + (uwsgi.queue_blocksize * pos);
uqi = (struct uwsgi_queue_item *) ptr;
ptr += sizeof(struct uwsgi_queue_item);
ptr += sizeof(struct uwsgi_queue_item);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
uqi->size = size;
uqi->ts = uwsgi_now();
memcpy(ptr, message, size);
return 1;
return 1;
}
+334 -31
View File
@@ -1,64 +1,367 @@
/*
uWSGI timers implementation
uWSGI rbtree implementation based on nginx
based on Linux hrtimers and nginx timeout management.
rbtree with allowed duplicate keys is used
Copyright (C) Igor Sysoev
Copyright (C) Nginx, Inc.
Copyright (C) Unbit S.a.s.
The red-black tree code is based on the algorithm described in
the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
*/
#include "uwsgi.h"
#include <uwsgi.h>
struct rb_root *uwsgi_init_rb_timer() {
#define uwsgi_rbt_red(node) ((node)->color = 1)
#define uwsgi_rbt_black(node) ((node)->color = 0)
#define uwsgi_rbt_is_red(node) ((node)->color)
#define uwsgi_rbt_is_black(node) (!uwsgi_rbt_is_red(node))
#define uwsgi_rbt_copy_color(n1, n2) (n1->color = n2->color)
struct rb_root *u_rb_root = uwsgi_malloc(sizeof(struct rb_root));
u_rb_root->rb_node = NULL;
struct uwsgi_rbtree *uwsgi_init_rb_timer() {
return u_rb_root;
struct uwsgi_rbtree *tree = uwsgi_calloc(sizeof(struct uwsgi_rbtree));
struct uwsgi_rb_timer *sentinel = uwsgi_calloc(sizeof(struct uwsgi_rb_timer));
// no need to set it black, calloc already did it
//uwsgi_rbt_black(sentinel);
tree->root = sentinel;
tree->sentinel = sentinel;
return tree;
}
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct rb_root *root) {
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
struct rb_node *node = root->rb_node;
if (!node)
node = tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (node == NULL) return NULL;
if (tree->root == sentinel) return NULL;
while(node->rb_left != NULL) {
node = node->rb_left;
while (node->left != sentinel) {
node = node->left;
}
return ((struct uwsgi_rb_timer *) node);
return node;
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *root, time_t key, void *data) {
static void uwsgi_rbtree_lr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *urbt = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct rb_node **p = &root->rb_node, *parent = NULL;
struct uwsgi_rb_timer *current_rb_timer;
struct uwsgi_rb_timer *temp;
memset(urbt, 0, sizeof(struct uwsgi_rb_timer));
temp = node->right;
node->right = temp->left;
urbt->key = key;
urbt->data = data;
if (temp->left != sentinel) {
temp->left->parent = node;
}
while(*p) {
parent = *p;
temp->parent = node->parent;
current_rb_timer = (struct uwsgi_rb_timer *) parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->left) {
node->parent->left = temp;
}
else {
node->parent->right = temp;
}
temp->left = node;
node->parent = temp;
}
static void uwsgi_rbtree_rr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *temp;
temp = node->left;
node->left = temp->right;
if (temp->right != sentinel) {
temp->right->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->right) {
node->parent->right = temp;
}
else {
node->parent->left = temp;
}
temp->right = node;
node->parent = temp;
}
static void uwsgi_rbt_add(struct uwsgi_rb_timer *temp, struct uwsgi_rb_timer *node, struct uwsgi_rb_timer *sentinel) {
struct uwsgi_rb_timer **p;
for (;;) {
p = (node->value < temp->value) ? &temp->left : &temp->right;
if (*p == sentinel)
break;
temp = *p;
}
*p = node;
node->parent = temp;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_red(node);
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *tree, uint64_t value, void *data) {
struct uwsgi_rb_timer *node = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct uwsgi_rb_timer *new_node = node;
node->value = value;
node->data = data;
struct uwsgi_rb_timer *temp = NULL;
/* a binary tree insert */
struct uwsgi_rb_timer **root = &tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (*root == sentinel) {
node->parent = NULL;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_black(node);
*root = node;
return new_node;
}
uwsgi_rbt_add(*root, node, sentinel);
/* re-balance tree */
while (node != *root && uwsgi_rbt_is_red(node->parent)) {
if (node->parent == node->parent->parent->left) {
temp = node->parent->parent->right;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->right) {
node = node->parent;
uwsgi_rbtree_lr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_rr(root, sentinel, node->parent->parent);
}
if (key <= current_rb_timer->key) {
p = &(*p)->rb_left;
}
else {
p = &(*p)->rb_right;
temp = node->parent->parent->left;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->left) {
node = node->parent;
uwsgi_rbtree_rr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_lr(root, sentinel, node->parent->parent);
}
}
}
rb_link_node((struct rb_node *) urbt, parent, p);
uwsgi_rbt_black(*root);
rb_insert_color((struct rb_node *) urbt, root);
return new_node;
}
return urbt;
void uwsgi_del_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
uint8_t red;
struct uwsgi_rb_timer **root, *sentinel, *subst, *temp, *w;
/* a binary tree delete */
root = &tree->root;
sentinel = tree->sentinel;
if (node->left == sentinel) {
temp = node->right;
subst = node;
}
else if (node->right == sentinel) {
temp = node->left;
subst = node;
}
else {
subst = uwsgi_min_rb_timer(tree, node->right);
if (subst->left != sentinel) {
temp = subst->left;
}
else {
temp = subst->right;
}
}
if (subst == *root) {
*root = temp;
uwsgi_rbt_black(temp);
return;
}
red = uwsgi_rbt_is_red(subst);
if (subst == subst->parent->left) {
subst->parent->left = temp;
}
else {
subst->parent->right = temp;
}
if (subst == node) {
temp->parent = subst->parent;
}
else {
if (subst->parent == node) {
temp->parent = subst;
}
else {
temp->parent = subst->parent;
}
subst->left = node->left;
subst->right = node->right;
subst->parent = node->parent;
uwsgi_rbt_copy_color(subst, node);
if (node == *root) {
*root = subst;
}
else {
if (node == node->parent->left) {
node->parent->left = subst;
}
else {
node->parent->right = subst;
}
}
if (subst->left != sentinel) {
subst->left->parent = subst;
}
if (subst->right != sentinel) {
subst->right->parent = subst;
}
}
if (red) {
return;
}
/* a delete fixup */
while (temp != *root && uwsgi_rbt_is_black(temp)) {
if (temp == temp->parent->left) {
w = temp->parent->right;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
w = temp->parent->right;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_black(w->left);
uwsgi_rbt_red(w);
uwsgi_rbtree_rr(root, sentinel, w);
w = temp->parent->right;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->right);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
temp = *root;
}
}
else {
w = temp->parent->left;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
w = temp->parent->left;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->left)) {
uwsgi_rbt_black(w->right);
uwsgi_rbt_red(w);
uwsgi_rbtree_lr(root, sentinel, w);
w = temp->parent->left;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->left);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
temp = *root;
}
}
}
uwsgi_rbt_black(temp);
}
+572
View File
@@ -0,0 +1,572 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_simple_wait_read_hook(int fd, int timeout) {
struct pollfd upoll;
timeout = timeout * 1000;
upoll.fd = fd;
upoll.events = POLLIN;
upoll.revents = 0;
int ret = poll(&upoll, 1, timeout);
if (ret > 0) {
if (upoll.revents & POLLIN) {
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_read_hook()/poll()");
}
return ret;
}
/*
seek()/rewind() language-independent implementations.
*/
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()");
}
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()");
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (uwsgi.post_buffering) {
if (pos < 0) {
if (pos > (off_t) wsgi_req->post_pos) {
wsgi_req->post_pos = 0;
return;
}
wsgi_req->post_pos -= pos;
return;
}
if (pos >= (off_t) uwsgi.post_buffering) {
pos = uwsgi.post_buffering - 1;
}
wsgi_req->post_pos = pos;
}
}
/*
read() and readline() language-independent implementations.
*/
#define uwsgi_read_error0(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: Client closed connection\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
#define uwsgi_read_error(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: %s\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos,\
strerror(errno));
#define uwsgi_read_timeout(x) uwsgi_log("[uwsgi-body-read] Timeout reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
size_t remains = UMIN(uwsgi.buffer_size, wsgi_req->post_cl - wsgi_req->post_pos);
int ret;
// allocate more memory if needed
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos = 0;
// still something to use ?
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()");
return -1;
}
wsgi_req->post_readline_buf = tmp_buf;
wsgi_req->post_readline_size += remains;
// INFORM THE USER HIS readline() USAGE IS FOOLISH
if (!wsgi_req->post_warning && wsgi_req->post_readline_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using readline() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_readline_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
}
// 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);
if (ret == 0) {
uwsgi_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;
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;
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);
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);
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);
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);
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);
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
return -1;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
return -1;
}
// TODO take hint into account
// readline_buf is allocated when needed and freed at the end of the request
char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
// return 0 if no post_cl or pos >= post_cl and no residual data
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
return uwsgi.empty;
}
// some residual data ?
if (wsgi_req->post_readline_pos > 0) {
size_t i;
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
// found a newline
if (wsgi_req->post_readline_buf[i] == '\n') {
*rlen = (i+1)-wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += *rlen;
// all the readline buffer has been consumed
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
return buf;
}
}
// ok, no newline found, continue below
}
// allocate memory on the first round
if (!wsgi_req->post_readline_buf) {
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()");
*rlen = -1;
return NULL;
}
wsgi_req->post_readline_size = amount;
}
// ok, no newline found, consume a bit more of memory and retry
for(;;) {
// no more data to consume
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
if (consume_body_for_readline(wsgi_req)) {
*rlen = -1;
return NULL;
}
size_t i;
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
if (wsgi_req->post_readline_buf[i] == '\n') {
*rlen = (i+1)-wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += *rlen;
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
return buf;
}
}
}
// no line found, let's return all
*rlen = wsgi_req->post_readline_size - wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos = 0;
return buf;
}
char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
int ret = -1;
size_t remains = hint;
// return empty if no post_cl or pos >= post_cl and no residual data
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
return uwsgi.empty;
}
// return the whole input
if (remains <= 0) {
remains = wsgi_req->post_cl;
}
// some residual data ?
if (wsgi_req->post_readline_pos > 0) {
if (remains <= (wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos)) {
*rlen = remains;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += remains;
return buf;
}
// the hint is higher than residual data, let's copy it to read() memory and go on
size_t avail = wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos;
// check if we have enough memory...
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()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
wsgi_req->post_read_buf_size = avail;
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
// fix remains...
if (remains > 0) {
remains -= avail;
}
*rlen += avail;
memcpy(wsgi_req->post_read_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, avail);
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
if (remains + wsgi_req->post_pos > wsgi_req->post_cl) {
remains = wsgi_req->post_cl - wsgi_req->post_pos;
}
if (remains == 0) {
if (*rlen > 0) {
return wsgi_req->post_read_buf;
}
else {
return uwsgi.empty;
}
}
// read from post buffering memory
if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) {
*rlen += remains;
char *buf = wsgi_req->post_buffering_buf+wsgi_req->post_pos;
wsgi_req->post_pos += remains;
return buf;
}
// ok we need to check if we need to allocate memory
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()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf_size = remains;
}
// need to realloc ?
else {
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()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
wsgi_req->post_read_buf_size = (remains+*rlen);
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
}
// check for disk buffered body first (they are all read in one shot)
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()");
return NULL;
}
*rlen += remains;
wsgi_req->post_pos+= remains;
return wsgi_req->post_read_buf;
}
// ok read all the required bytes...
while(remains > 0) {
// here we first try to read (as data could be already available)
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen , remains);
if (len > 0) {
wsgi_req->post_pos+=len;
remains -= len;
*rlen += len;
continue;
}
// client closed connection...
if (len == 0) {
*rlen = -1;
uwsgi_read_error0(remains);
return NULL;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
uwsgi_read_error(remains);
return NULL;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen, remains);
if (len > 0) {
wsgi_req->post_pos+=len;
remains -= len;
*rlen += len;
continue;
}
*rlen = -1;
if (len == 0) {
uwsgi_read_error0(remains);
}
else {
uwsgi_read_error(remains);
}
return NULL;
}
// 0 means timeout
else if (ret == 0) {
*rlen = 0;
uwsgi_read_timeout(remains);
return NULL;
}
*rlen = -1;
uwsgi_read_error(remains);
return NULL;
}
return wsgi_req->post_read_buf;
}
/*
post buffering
*/
int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
size_t remains = wsgi_req->post_cl;
int ret;
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]);
}
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
if (rlen > 0) {
remains -= rlen;
ptr += rlen;
continue;
}
if (rlen == 0) {
uwsgi_read_error0(remains);
return -1;
}
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
if (rlen > 0) {
remains -= rlen;
ptr += rlen;
continue;
}
}
if (ret < 0) {
uwsgi_read_error(remains);
return -1;
}
uwsgi_read_timeout(remains);
return -1;
}
return 0;
}
int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
size_t post_remains = wsgi_req->post_cl;
int ret;
int upload_progress_fd = -1;
char *upload_progress_filename = NULL;
wsgi_req->post_file = tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/tmpfile()");
return -1;
}
if (uwsgi.upload_progress) {
// first check for X-Progress-ID size
// separator + 'X-Progress-ID' + '=' + uuid
upload_progress_filename = uwsgi_upload_progress_create(wsgi_req, &upload_progress_fd);
if (!upload_progress_filename) {
uwsgi_log("invalid X-Progress-ID value: must be a UUID\n");
}
}
// manage buffered data and upload progress
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]);
}
// we use the already available post buffering buffer to read chunks....
size_t remains = UMIN(post_remains, uwsgi.post_buffering);
// first try to read data (there could be something already available
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
if (rlen > 0) goto write;
if (rlen == 0) {
uwsgi_read_error0(remains);
goto end;
}
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(remains);
goto end;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
if (rlen > 0) goto write;
if (rlen == 0) {
uwsgi_read_error0(remains);
}
else {
uwsgi_read_error(remains);
}
goto end;
}
if (ret < 0) {
uwsgi_read_error(remains);
goto end;
}
uwsgi_read_timeout(remains);
goto end;
write:
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
goto end;
}
post_remains -= rlen;
if (upload_progress_filename) {
// stop updating it on errors
if (uwsgi_upload_progress_update(wsgi_req, upload_progress_fd, post_remains)) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
upload_progress_filename = NULL;
}
}
}
rewind(wsgi_req->post_file);
if (upload_progress_filename) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
}
return 0;
end:
if (upload_progress_filename) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
}
return -1;
}
+45 -22
View File
@@ -1,46 +1,60 @@
#ifdef UWSGI_PCRE
#include "uwsgi.h"
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
extern struct uwsgi_server uwsgi;
void uwsgi_opt_pcre_jit(char *opt, char *value, void *foobar) {
#if defined(PCRE_STUDY_JIT_COMPILE) && defined(PCRE_CONFIG_JIT)
int has_jit = 0, ret;
ret = pcre_config(PCRE_CONFIG_JIT, &has_jit);
if (ret != 0 || has_jit != 1)
return;
uwsgi.pcre_jit = PCRE_STUDY_JIT_COMPILE;
#endif
}
int uwsgi_regexp_build(char *re, pcre ** pattern, pcre_extra ** pattern_extra) {
const char *errstr;
int erroff;
*pattern = pcre_compile( (const char *)re, 0, &errstr, &erroff, NULL);
if (!*pattern) {
*pattern = pcre_compile((const char *) re, 0, &errstr, &erroff, NULL);
if (!*pattern) {
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
return -1;
}
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
if (*pattern_extra == NULL && errstr != NULL) {
int opt = uwsgi.pcre_jit;
*pattern_extra = (pcre_extra *) pcre_study((const pcre *) *pattern, opt, &errstr);
if (*pattern_extra == NULL && errstr != NULL) {
pcre_free(*pattern);
uwsgi_log("pcre (study) error: %s\n", errstr);
return -1;
}
return 0;
}
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length) {
int uwsgi_regexp_match(pcre * pattern, pcre_extra * pattern_extra, char *subject, int length) {
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, NULL, 0);
}
int uwsgi_regexp_match_ovec(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length, int *ovec, int n ) {
int uwsgi_regexp_match_ovec(pcre * pattern, pcre_extra * pattern_extra, char *subject, int length, int *ovec, int n) {
if (n > 0) {
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, ovec, (n+1)*3 );
return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, ovec, (n + 1) * 3);
}
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
return pcre_exec((const pcre *) pattern, (const pcre_extra *) pattern_extra, subject, length, 0, 0, NULL, 0);
}
int uwsgi_regexp_ovector(pcre *pattern, pcre_extra *pattern_extra) {
int uwsgi_regexp_ovector(pcre * pattern, pcre_extra * pattern_extra) {
int n;
if (pcre_fullinfo((const pcre*)pattern, (const pcre_extra *)pattern_extra, PCRE_INFO_CAPTURECOUNT, &n))
if (pcre_fullinfo((const pcre *) pattern, (const pcre_extra *) pattern_extra, PCRE_INFO_CAPTURECOUNT, &n))
return 0;
return n;
@@ -51,35 +65,44 @@ char *uwsgi_regexp_apply_ovec(char *src, int src_n, char *dst, int dst_n, int *o
int i;
int dollar = 0;
char *res = uwsgi_malloc( dst_n + (src_n * n) + 1);
size_t dollars = n;
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
char *ptr = res;
for(i=0;i<dst_n;i++) {
for (i = 0; i < dst_n; i++) {
if (dollar) {
if (isdigit((int)dst[i])) {
if (isdigit((int) dst[i])) {
int pos = (dst[i] - 48);
if (pos <= n) {
pos = pos * 2;
memcpy(ptr, src + ovector[pos], ovector[pos+1]-ovector[pos]);
ptr+=ovector[pos+1]-ovector[pos];
memcpy(ptr, src + ovector[pos], ovector[pos + 1] - ovector[pos]);
ptr += ovector[pos + 1] - ovector[pos];
}
}
else {
*ptr++= dst[i];
*ptr++ = '$';
*ptr++ = dst[i];
}
dollar = 0;
}
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++= dst[i];
*ptr++ = dst[i];
}
}
}
*ptr++= 0;
*ptr++ = 0;
return res;
}
+644 -59
View File
@@ -1,61 +1,226 @@
#ifdef UWSGI_ROUTING
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
char *pass1 = data;
size_t pass1_len = data_len;
// cannot fail
if (subject) {
pass1 = uwsgi_regexp_apply_ovec(subject, subject_len, data, data_len, ur->ovector, ur->ovn);
pass1_len = strlen(pass1);
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(pass1_len);
size_t i;
int status = 0;
char *key = NULL;
size_t keylen = 0;
for(i=0;i<pass1_len;i++) {
switch(status) {
case 0:
if (pass1[i] == '$') {
status = 1;
break;
}
if (uwsgi_buffer_append(ub, pass1 + i, 1)) goto error;
break;
case 1:
if (pass1[i] == '{') {
status = 2;
key = pass1+i+1;
keylen = 0;
break;
}
status = 0;
key = NULL;
keylen = 0;
if (uwsgi_buffer_append(ub, "$", 1)) goto error;
if (uwsgi_buffer_append(ub, pass1 + i, 1)) goto error;
break;
case 2:
if (pass1[i] == '}') {
uint16_t vallen = 0;
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
if (value) {
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
}
status = 0;
key = NULL;
keylen = 0;
break;
}
keylen++;
break;
default:
break;
}
}
// fix the buffer
if (status == 1) {
if (uwsgi_buffer_append(ub, "$", 1)) goto error;
}
else if (status == 2) {
if (uwsgi_buffer_append(ub, "${", 2)) goto error;
if (keylen > 0) {
if (uwsgi_buffer_append(ub, key, keylen)) goto error;
}
}
// add the final NULL byte (to simplify plugin work)
if (uwsgi_buffer_append(ub, "\0", 1)) goto error;
// .. but came back of 1 position to avoid accounting it
ub->pos--;
if (pass1 != data) {
free(pass1);
}
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
struct uwsgi_route *routes = uwsgi.routes;
void *goon_func = NULL;
int n = -1;
if (!routes) return UWSGI_ROUTE_CONTINUE;
char *orig_subject = subject;
uint16_t orig_subject_len = subject_len;
if (uwsgi_parse_vars(wsgi_req)) {
return UWSGI_ROUTE_BREAK;
}
while (routes) {
while(routes) {
char **subject = (char **) (((char *)(wsgi_req))+routes->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+routes->subject_len);
#ifdef UWSGI_DEBUG
uwsgi_log("route subject = %.*s\n", *subject_len, *subject);
#endif
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, *subject, *subject_len, routes->ovector, routes->ovn);
if (n>= 0) {
int ret = routes->func(wsgi_req, routes);
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
goto next;
}
if (goon_func && goon_func == routes->func) {
goto next;
}
goon_func = NULL;
wsgi_req->route_goto = 0;
if (!routes->if_func) {
if (!subject) {
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
subject = *subject2 ;
subject_len = *subject_len2;
}
n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, subject, subject_len, routes->ovector, routes->ovn);
}
else {
int ret = routes->if_func(wsgi_req, routes);
// error
if (ret < 0) {
return UWSGI_ROUTE_BREAK;
}
// true
if (!routes->if_negate) {
if (ret == 0) {
goto next;
}
n = ret;
}
else {
if (ret > 0) {
goto next;
}
n = 1;
}
}
if (n >= 0) {
wsgi_req->is_routing = 1;
int ret = routes->func(wsgi_req, routes);
wsgi_req->is_routing = 0;
if (ret == UWSGI_ROUTE_BREAK) {
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].routed_requests++;
return ret;
}
if (ret == UWSGI_ROUTE_CONTINUE) {
return ret;
}
if (ret == UWSGI_ROUTE_GOON) {
goon_func = routes->func;
}
}
next:
subject = orig_subject;
subject_len = orig_subject_len;
routes = routes->next;
if (routes) wsgi_req->route_pc++;
}
return UWSGI_ROUTE_CONTINUE;
}
int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *uri, int len) {
int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
struct uwsgi_route *routes = uwsgi.routes;
if (!uwsgi.routes)
return UWSGI_ROUTE_CONTINUE;
if (!routes) return UWSGI_ROUTE_CONTINUE;
// avoid loops
if (wsgi_req->is_routing)
return UWSGI_ROUTE_CONTINUE;
while(routes) {
int n = uwsgi_regexp_match_ovec(routes->pattern, routes->pattern_extra, uri, len, routes->ovector, routes->ovn);
if (n>= 0) {
int ret = routes->func(wsgi_req, routes);
if (ret != UWSGI_ROUTE_NEXT) {
return ret;
}
}
if (uwsgi_parse_vars(wsgi_req)) {
return UWSGI_ROUTE_BREAK;
}
routes = routes->next;
}
// in case ogf static files serving previous rules could be applied
if (wsgi_req->routes_applied) {
return UWSGI_ROUTE_CONTINUE;
}
return UWSGI_ROUTE_CONTINUE;
return uwsgi_apply_routes_do(wsgi_req, NULL, 0);
}
static void *uwsgi_route_get_condition_func(char *name) {
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
while(urc) {
if (!strcmp(urc->name, name)) {
return urc->func;
}
urc = urc->next;
}
return NULL;
}
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
uint64_t pos = 0;
while(ur) {
old_ur = ur;
ur = ur->next;
pos++;
}
ur = uwsgi_calloc(sizeof(struct uwsgi_route));
if (old_ur) {
old_ur->next = ur;
}
else {
uwsgi.routes = ur;
}
ur->pos = pos;
// is it a label ?
if (foobar == NULL) {
ur->label = value;
ur->label_len = strlen(value);
return;
}
char *route = uwsgi_str(value);
char *space = strchr(route, ' ');
@@ -66,23 +231,27 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
*space = 0;
struct uwsgi_route *ur = uwsgi.routes;
if (!ur) {
uwsgi.routes = uwsgi_calloc(sizeof(struct uwsgi_route));
ur = uwsgi.routes;
}
else {
while(ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_route));
ur = ur->next;
break;
}
ur = ur->next;
if (!strcmp(foobar, "if") || !strcmp(foobar, "if-not")) {
char *colon = strchr(route, ':');
if (!colon) {
uwsgi_log("invalid route condition syntax\n");
exit(1);
}
*colon = 0;
if (!strcmp(foobar, "if-not")) {
ur->if_negate = 1;
}
foobar = colon+1;
ur->if_func = uwsgi_route_get_condition_func(route);
if (!ur->if_func) {
uwsgi_log("unable to find \"%s\" route condition\n", route);
exit(1);
}
}
if (!strcmp(foobar, "http_host")) {
else if (!strcmp(foobar, "http_host")) {
ur->subject = offsetof(struct wsgi_request, host);
ur->subject_len = offsetof(struct wsgi_request, host_len);
}
@@ -94,21 +263,44 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
ur->subject = offsetof(struct wsgi_request, query_string);
ur->subject_len = offsetof(struct wsgi_request, query_string_len);
}
else if (!strcmp(foobar, "remote_addr")) {
ur->subject = offsetof(struct wsgi_request, remote_addr);
ur->subject_len = offsetof(struct wsgi_request, remote_addr_len);
}
else if (!strcmp(foobar, "user_agent")) {
ur->subject = offsetof(struct wsgi_request, user_agent);
ur->subject_len = offsetof(struct wsgi_request, user_agent_len);
}
else if (!strcmp(foobar, "referer")) {
ur->subject = offsetof(struct wsgi_request, referer);
ur->subject_len = offsetof(struct wsgi_request, referer_len);
}
else if (!strcmp(foobar, "remote_user")) {
ur->subject = offsetof(struct wsgi_request, remote_user);
ur->subject_len = offsetof(struct wsgi_request, remote_user_len);
}
else {
ur->subject = offsetof(struct wsgi_request, path_info);
ur->subject_len = offsetof(struct wsgi_request, path_info_len);
}
if (uwsgi_regexp_build(route, &ur->pattern, &ur->pattern_extra)) {
exit(1);
ur->subject_str = foobar;
ur->subject_str_len = strlen(ur->subject_str);
ur->regexp = route;
if (ur->subject && ur->subject_len) {
if (uwsgi_regexp_build(route, &ur->pattern, &ur->pattern_extra)) {
exit(1);
}
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
if (ur->ovn > 0) {
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)));
}
}
ur->ovn = uwsgi_regexp_ovector(ur->pattern, ur->pattern_extra);
if (ur->ovn > 0) {
ur->ovector = uwsgi_calloc(sizeof(int) * (3 * (ur->ovn + 1)) );
}
char *command = space+1;
char *command = space + 1;
ur->action = uwsgi_str(command);
char *colon = strchr(command, ':');
if (!colon) {
@@ -119,21 +311,22 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
*colon = 0;
struct uwsgi_router *r = uwsgi.routers;
while(r) {
while (r) {
if (!strcmp(r->name, command)) {
if (r->func(ur, colon+1) == 0) {
if (r->func(ur, colon + 1) == 0) {
// apply is_last
struct uwsgi_route *last_ur = ur;
ur = uwsgi.routes;
while(ur) {
while (ur) {
if (ur->func == last_ur->func) {
ur->is_last = 0;
}
ur = ur->next;
ur = ur->next;
}
last_ur->is_last = 1;
return;
}
break;
}
r = r->next;
}
@@ -142,7 +335,359 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
exit(1);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_route *, char *)) {
int uwsgi_route_api_func(struct wsgi_request *wsgi_req, char *router, char *args) {
struct uwsgi_route *ur = NULL;
struct uwsgi_router *r = uwsgi.routers;
while(r) {
if (!strcmp(router, r->name)) {
goto found;
}
r = r->next;
}
free(args);
return -1;
found:
ur = uwsgi_calloc(sizeof(struct uwsgi_route));
// initialize the virtual route
if (r->func(ur, args)) {
free(ur);
free(args);
return -1;
}
// call it
int ret = ur->func(wsgi_req, ur);
if (ur->free) {
ur->free(ur);
}
free(ur);
free(args);
return ret;
}
// continue/last route
static int uwsgi_router_continue_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
return UWSGI_ROUTE_CONTINUE;
}
static int uwsgi_router_continue(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_continue_func;
return 0;
}
// break route
static int uwsgi_router_break_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
if (route->data_len >= 3) {
if (uwsgi_response_prepare_headers(wsgi_req, route->data, route->data_len)) goto end;
if (uwsgi_response_add_connection_close(wsgi_req)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) goto end;
// no need to check for return value
uwsgi_response_write_headers_do(wsgi_req);
}
end:
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_break_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// goon route
static int uwsgi_router_goon_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
return UWSGI_ROUTE_GOON;
}
static int uwsgi_router_goon(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_goon_func;
return 0;
}
// log route
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_log("%.*s\n", ub->pos, ub->buf);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_log(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_log_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// logvar route
static int uwsgi_router_logvar_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_logvar_add(wsgi_req, ur->data, ur->data_len, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_logvar(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_logvar_func;
char *equal = strchr(arg, '=');
if (!equal) {
uwsgi_log("invalid logvar syntax, must be key=value\n");
exit(1);
}
ur->data = arg;
ur->data_len = equal-arg;
ur->data2 = equal+1;
ur->data2_len = strlen(ur->data2);
return 0;
}
// goto route
static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
// build the label (if needed)
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
// find the label
struct uwsgi_route *routes = uwsgi.routes;
while(routes) {
if (!routes->label) goto next;
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
wsgi_req->route_goto = routes->pos;
goto found;
}
next:
routes = routes->next;
}
wsgi_req->route_goto = ur->custom;
found:
uwsgi_buffer_destroy(ub);
if (wsgi_req->route_goto <= wsgi_req->route_pc) {
wsgi_req->route_goto = 0;
uwsgi_log("[uwsgi-route] ERROR \"goto\" instruction can only jump forward (check your label !!!)\n");
return UWSGI_ROUTE_BREAK;
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_goto(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_goto_func;
ur->data = arg;
ur->data_len = strlen(arg);
ur->custom = atoi(arg);
return 0;
}
// addvar route
static int uwsgi_router_addvar_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
if (!ub) return UWSGI_ROUTE_BREAK;
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, ub->buf, ub->pos)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_addvar(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_addvar_func;
char *equal = strchr(arg, '=');
if (!equal) {
uwsgi_log("[uwsgi-route] invalid addvar syntax, must be KEY=VAL\n");
exit(1);
}
ur->data = arg;
ur->data_len = equal-arg;
ur->data2 = equal+1;
ur->data2_len = strlen(ur->data2);
return 0;
}
// addheader route
static int uwsgi_router_addheader_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_additional_header_add(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_addheader(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_addheader_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// remheader route
static int uwsgi_router_remheader_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uwsgi_remove_header(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_remheader(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_remheader_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// signal route
static int uwsgi_router_signal_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
uwsgi_signal_send(uwsgi.signal_socket, route->custom);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_signal(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_signal_func;
ur->custom = atoi(arg);
return 0;
}
// send route
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
if (route->custom) {
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
}
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_send_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
static int uwsgi_router_send_crnl(struct uwsgi_route *ur, char *arg) {
uwsgi_router_send(ur, arg);
ur->custom = 1;
return 0;
}
static int uwsgi_route_condition_exists(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (uwsgi_file_exists(ub->buf)) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (uwsgi_is_file(ub->buf)) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (uwsgi_is_dir(ub->buf)) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_islink(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (uwsgi_is_link(ub->buf)) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_isexec(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (!access(ub->buf, X_OK)) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
// register embedded routers
void uwsgi_register_embedded_routers() {
uwsgi_register_router("continue", uwsgi_router_continue);
uwsgi_register_router("last", uwsgi_router_continue);
uwsgi_register_router("break", uwsgi_router_break);
uwsgi_register_router("goon", uwsgi_router_goon);
uwsgi_register_router("log", uwsgi_router_log);
uwsgi_register_router("logvar", uwsgi_router_logvar);
uwsgi_register_router("goto", uwsgi_router_goto);
uwsgi_register_router("addvar", uwsgi_router_addvar);
uwsgi_register_router("addheader", uwsgi_router_addheader);
uwsgi_register_router("delheader", uwsgi_router_remheader);
uwsgi_register_router("remheader", uwsgi_router_remheader);
uwsgi_register_router("signal", uwsgi_router_signal);
uwsgi_register_router("send", uwsgi_router_send);
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
uwsgi_register_route_condition("exists", uwsgi_route_condition_exists);
uwsgi_register_route_condition("isfile", uwsgi_route_condition_isfile);
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
struct uwsgi_router *ur = uwsgi.routers;
if (!ur) {
@@ -152,7 +697,7 @@ struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_
return uwsgi.routers;
}
while(ur) {
while (ur) {
if (!ur->next) {
ur->next = uwsgi_calloc(sizeof(struct uwsgi_router));
ur->next->name = name;
@@ -165,4 +710,44 @@ struct uwsgi_router *uwsgi_register_router(char *name, int (*func)(struct uwsgi_
return NULL;
}
struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*func) (struct wsgi_request *, struct uwsgi_route *)) {
struct uwsgi_route_condition *old_urc = NULL,*urc = uwsgi.route_conditions;
while(urc) {
if (!strcmp(urc->name, name)) {
return urc;
}
old_urc = urc;
urc = urc->next;
}
urc = uwsgi_calloc(sizeof(struct uwsgi_route_condition));
urc->name = name;
urc->func = func;
if (old_urc) {
old_urc->next = urc;
}
else {
uwsgi.route_conditions = urc;
}
return urc;
}
void uwsgi_routing_dump() {
struct uwsgi_route *routes = uwsgi.routes;
if (!routes) return;
uwsgi_log("*** dumping internal routing table ***\n");
while(routes) {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
routes = routes->next;
}
uwsgi_log("*** end of the internal routing table ***\n");
}
#endif
+102 -65
View File
@@ -7,25 +7,51 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
struct uwsgi_rpc *urpc;
int ret = -1;
if (uwsgi.mywid != 0) {
uwsgi_log("you can register RPC functions only in the master\n");
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register RPC functions\n");
return -1;
}
uwsgi_lock(uwsgi.rpc_table_lock);
if (uwsgi.shared->rpc_count < MAX_RPC) {
urpc = &uwsgi.shared->rpc_table[uwsgi.shared->rpc_count];
// first check if a function is already registered
size_t i;
for(i=0;i<uwsgi.shared->rpc_count[uwsgi.mywid];i++) {
int pos = (uwsgi.mywid * uwsgi.rpc_max) + i;
urpc = &uwsgi.rpc_table[pos];
if (!strcmp(name, urpc->name)) {
goto already;
}
}
if (uwsgi.shared->rpc_count[uwsgi.mywid] < uwsgi.rpc_max) {
int pos = (uwsgi.mywid * uwsgi.rpc_max) + uwsgi.shared->rpc_count[uwsgi.mywid];
urpc = &uwsgi.rpc_table[pos];
uwsgi.shared->rpc_count[uwsgi.mywid]++;
already:
memcpy(urpc->name, name, strlen(name));
urpc->modifier1 = modifier1;
urpc->args = args;
urpc->func = func;
uwsgi.shared->rpc_count++;
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
ret = 0;
uwsgi_log("registered RPC function %s\n", name);
if (uwsgi.mywid == 0) {
uwsgi_log("registered shared/inherited RPC function \"%s\"\n", name);
}
else {
uwsgi_log("registered RPC function \"%s\" on worker %d\n", name, uwsgi.mywid);
}
}
// implement cow
if (uwsgi.mywid == 0) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.shared->rpc_count[i] = uwsgi.shared->rpc_count[0];
int pos = (i * uwsgi.rpc_max);
memcpy(&uwsgi.rpc_table[pos], uwsgi.rpc_table, sizeof(struct uwsgi_rpc) * uwsgi.rpc_max);
}
}
uwsgi_unlock(uwsgi.rpc_table_lock);
@@ -36,13 +62,15 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
struct uwsgi_rpc *urpc = NULL;
int i;
uint64_t i;
uint16_t ret = 0;
for(i=0;i<uwsgi.shared->rpc_count;i++) {
if (uwsgi.shared->rpc_table[i].name[0] != 0) {
if (!strcmp(uwsgi.shared->rpc_table[i].name, name)) {
urpc = &uwsgi.shared->rpc_table[i];
int pos = (uwsgi.mywid * uwsgi.rpc_max);
for (i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) {
if (uwsgi.rpc_table[pos + i].name[0] != 0) {
if (!strcmp(uwsgi.rpc_table[pos + i].name, name)) {
urpc = &uwsgi.rpc_table[pos + i];
break;
}
}
@@ -58,85 +86,94 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t *len) {
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
uint8_t i;
uint16_t ulen;
struct uwsgi_header uh;
struct uwsgi_header *uh = NULL;
char *buffer = NULL;
*len = 0;
if (node == NULL || !strcmp(node, "")) {
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
buffer = uwsgi_malloc(UMAX16);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
}
// connect to node
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
// connect to node (async way)
int fd = uwsgi_connect(node, 0, 1);
if (fd < 0)
return NULL;
if (fd < 0) return NULL;
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return NULL;
}
// prepare a uwsgi array
// prepare a uwsgi array
uint16_t buffer_size = 2 + strlen(func);
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
buffer = uwsgi_malloc(4+buffer_size);
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
// set the uwsgi header
uh = (struct uwsgi_header *) buffer;
uh->modifier1 = 173;
uh->pktsize = buffer_size;
uh->modifier2 = 0;
// add func to the array
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
char *bufptr = buffer + 4;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
// 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])) {
goto error;
}
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
close(fd);
free(buffer);
return NULL;
// 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])) {
goto error;
}
close(fd);
*len = uh.pktsize;
*len = rlen;
if (*len == 0) {
free(buffer);
return NULL;
goto error;
}
return buffer;
error:
close(fd);
free(buffer);
return NULL;
}
void uwsgi_rpc_init() {
uwsgi.rpc_table = uwsgi_calloc_shared((sizeof(struct uwsgi_rpc) * uwsgi.rpc_max) * (uwsgi.numproc+1));
uwsgi.shared->rpc_count = uwsgi_calloc_shared(sizeof(uint64_t) * (uwsgi.numproc+1));
}
+24 -162
View File
@@ -1,177 +1,39 @@
#ifdef UWSGI_SENDFILE
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
ssize_t uwsgi_sendfile(struct wsgi_request *wsgi_req) {
int fd = wsgi_req->sendfile_fd;
int sockfd = wsgi_req->poll.fd;
struct stat stat_buf;
ssize_t sst = 0;
if (!wsgi_req->sendfile_fd_size) {
if (fstat(fd, &stat_buf)) {
uwsgi_error("fstat()");
goto end;
}
else {
wsgi_req->sendfile_fd_size = stat_buf.st_size;
}
}
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096;
if (wsgi_req->socket->proto_sendfile) {
sst = wsgi_req->socket->proto_sendfile(wsgi_req);
}
else {
sst = uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi.async);
}
}
end:
return sst;
}
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t *pos, int async) {
// sendfile() abstraction
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
int sf_ret;
off_t sf_len = filesize;
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, 0, NULL, &sf_len, 0);
*pos += sf_len;
}
else {
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret < 0) {
if (errno != EAGAIN) {
uwsgi_error("sendfile()");
return 0;
}
}
return sf_len;
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__)
int sf_ret;
off_t sf_len = filesize;
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, &sf_len, NULL, 0);
*pos += sf_len;
}
else {
sf_ret = sendfile(filefd, sockfd, 0, &sf_len, NULL, 0);
}
if (sf_ret) {
#ifdef UWSGI_DEBUG
uwsgi_log("sf_len = %d\n", sf_len);
#endif
uwsgi_error("sendfile()");
return 0;
}
return sf_len;
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__)
int sf_ret;
size_t written = 0;
if (async > 1) {
sf_ret = sendfile(sockfd, filefd, pos, chunk);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
return sf_ret;
}
while(written < filesize) {
sf_ret = sendfile(sockfd, filefd, pos, filesize-written);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
else if (sf_ret == 0) {
return 0;
}
written+= sf_ret;
}
return written;
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#else
static size_t nosf_buf_size = 0;
static char *nosf_buf;
char *nosf_buf2;
ssize_t jlen = 0;
ssize_t rlen = 0;
ssize_t i = 0;
if (!nosf_buf) {
nosf_buf = malloc(chunk);
}
else if (chunk != nosf_buf_size) {
nosf_buf2 = realloc(nosf_buf, chunk);
if (!nosf_buf2) {
free(nosf_buf);
// 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 (pos > 0) {
if (lseek(filefd, pos, SEEK_SET)) {
uwsgi_error("uwsgi_sendfile_do()/seek()");
return -1;
}
nosf_buf = nosf_buf2;
}
if (!nosf_buf) {
uwsgi_error("sendfile malloc()/realloc()");
return 0;
ssize_t rlen = read(filefd, buf, UMIN(len, 8192));
if (rlen <= 0) {
uwsgi_error("uwsgi_sendfile_do()/read()");
return -1;
}
nosf_buf_size = chunk;
if (async > 1) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
return 0;
}
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
return 0;
}
return jlen;
}
while (i < (int) filesize) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
break;
}
i += jlen;
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
break;
}
rlen += jlen;
}
return rlen;
return write(sockfd, buf, rlen);
#endif
}
#endif
+2 -9
View File
@@ -106,13 +106,11 @@ void uwsgi_setup_inherited_sockets() {
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
#ifdef UWSGI_MULTICAST
if (j == uwsgi.cluster_fd)
continue;
#endif
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
if (j == uwsgi.emperor_fd_config)
continue;
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
@@ -130,11 +128,6 @@ void uwsgi_setup_inherited_sockets() {
continue;
}
if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
if (j == uwsgi.cache_server_fd)
continue;
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
int found = 0;
while (ugs) {
+255 -228
View File
@@ -4,13 +4,18 @@ extern struct uwsgi_server uwsgi;
int uwsgi_signal_handler(uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
struct uwsgi_signal_entry *use = NULL;
use = &uwsgi.shared->signal_table[sig];
int pos = (uwsgi.mywid * 256) + sig;
use = &uwsgi.shared->signal_table[pos];
if (!use->handler)
return -1;
if (!uwsgi.p[use->modifier1]->signal_handler) {
return -1;
}
}
// check for COW
if (uwsgi.master_process) {
@@ -34,60 +39,57 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
// set harakiri here (if required and if i am a worker)
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 1;
uwsgi.mules[uwsgi.muleid-1].signum = sig;
uwsgi.mules[uwsgi.muleid-1].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
uwsgi.mules[uwsgi.muleid - 1].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
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]);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
#endif
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 0;
if(uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
uwsgi.workers[uwsgi.mywid].sig = 0;
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
}
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 0;
if(uwsgi.mules[uwsgi.muleid-1].harakiri > 0) {
set_mule_harakiri(0);
uwsgi.mules[uwsgi.muleid - 1].sig = 0;
if (uwsgi.mules[uwsgi.muleid - 1].harakiri > 0) {
set_mule_harakiri(0);
}
}
#ifdef UWSGI_SPOOLER
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
return ret;
}
int uwsgi_signal_registered(uint8_t sig) {
if (uwsgi.shared->signal_table[sig].handler != NULL)
int pos = (uwsgi.mywid * 256) + sig;
if (uwsgi.shared->signal_table[pos].handler != NULL)
return 1;
return 0;
@@ -97,19 +99,28 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (strlen(receiver) > 63) return -1;
if (!uwsgi.master_process) 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");
return -1;
}
if (strlen(receiver) > 63)
return -1;
uwsgi_lock(uwsgi.signal_table_lock);
use = &uwsgi.shared->signal_table[sig];
int pos = (uwsgi.mywid * 256) + sig;
use = &uwsgi.shared->signal_table[pos];
if (use->handler) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
if (use->handler && uwsgi.mywid == 0) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal as the master !!!\n");
uwsgi_unlock(uwsgi.signal_table_lock);
return -1;
}
strncpy(use->receiver, receiver, strlen(receiver)+1);
strncpy(use->receiver, receiver, strlen(receiver) + 1);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
@@ -121,6 +132,15 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
}
// check for cow
if (uwsgi.mywid == 0) {
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);
}
}
uwsgi_unlock(uwsgi.signal_table_lock);
return 0;
@@ -129,7 +149,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
if (strlen(filename) > (0xff-1)) {
if (strlen(filename) > (0xff - 1)) {
uwsgi_log("uwsgi_add_file_monitor: invalid filename length\n");
return -1;
}
@@ -140,9 +160,9 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
// fill the fmon table, the master will use it to add items to the event queue
memcpy(ushared->files_monitored[ushared->files_monitored_cnt].filename, filename, strlen(filename));
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].sig = sig;
ushared->files_monitored_cnt++;
}
else {
@@ -157,31 +177,31 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while(uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
return uwsgi_up;
}
@@ -189,10 +209,10 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while(up) {
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
@@ -201,15 +221,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024-1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
@@ -225,15 +245,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
@@ -267,107 +287,109 @@ void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while(uc->next) {
uc = uc->next;
old_uc = uc;
}
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value+i;
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value + i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.rb_timer_table_lock);
uwsgi_lock(uwsgi.rb_timer_table_lock);
if (ushared->rb_timers_cnt < 64) {
if (ushared->rb_timers_cnt < 64) {
// fill the timer table, the master will use it to add items to the event queue
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
ushared->rb_timers_cnt++;
}
else {
uwsgi_log("you can register max 64 rb_timers !!!\n");
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return -1;
}
// fill the timer table, the master will use it to add items to the event queue
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
ushared->rb_timers_cnt++;
}
else {
uwsgi_log("you can register max 64 rb_timers !!!\n");
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.rb_timer_table_lock);
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return 0;
return 0;
}
void create_signal_pipe(int *sigpipe) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
if (uwsgi.signal_bufsize) {
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
}
}
@@ -379,9 +401,10 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
uh.modifier1 = 110;
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return -1;
if (fd < 0)
return -1;
if (write(fd, (char *) &uh, 4) != 4) {
uwsgi_error("uwsgi_remote_signal_send()");
@@ -403,23 +426,24 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
if (write(fd, &sig, 1) != 1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("uwsgi_signal_send()");
}
return -1;
}
}
return 0;
}
void uwsgi_route_signal(uint8_t sig) {
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
int pos = (uwsgi.mywid * 256) + sig;
struct uwsgi_signal_entry *use = &ushared->signal_table[pos];
int i;
// send to first available worker
@@ -430,7 +454,7 @@ void uwsgi_route_signal(uint8_t sig) {
}
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
for(i=1;i<=uwsgi.numproc;i++) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
@@ -438,70 +462,68 @@ void uwsgi_route_signal(uint8_t sig) {
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver+6);
i = atoi(use->receiver + 6);
if (i > uwsgi.numproc) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
// route to subscribed
else if (!strcmp(use->receiver, "subscribed")) {
}
// route to spooler
#ifdef UWSGI_SPOOLER
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for(i=0;i<uwsgi.mules_cnt;i++) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
}
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i + 1);
}
}
}
else if (!strncmp(use->receiver, "mule", 4)) {
i = atoi(use->receiver+4);
i = atoi(use->receiver + 4);
if (i > uwsgi.mules_cnt) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else if (i == 0) {
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
}
else {
if (uwsgi_signal_send(uwsgi.mules[i-1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
if (uwsgi_signal_send(uwsgi.mules[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
}
}
else if (!strncmp(use->receiver, "farm_", 5)) {
char *name = use->receiver+5;
char *name = use->receiver + 5;
struct uwsgi_farm *uf = get_farm_by_name(name);
if (!uf) {
uwsgi_log("unknown farm: %s\n", name);
return;
}
if (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
}
else if (!strncmp(use->receiver, "farm", 4)) {
i = atoi(use->receiver+4);
i = atoi(use->receiver + 4);
if (i > uwsgi.farms_cnt || i <= 0) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else {
if (uwsgi_signal_send(uwsgi.farms[i-1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
}
if (uwsgi_signal_send(uwsgi.farms[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i - 1].name);
}
}
}
@@ -512,51 +534,56 @@ void uwsgi_route_signal(uint8_t sig) {
}
uint8_t uwsgi_signal_wait(int signum) {
int uwsgi_signal_wait(int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int ret;
struct pollfd pfd[2];
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
int received_signal = -1;
int ret;
struct pollfd pfd[2];
if (signum > -1) {
wait_for_specific_signal = 1;
}
wait_for_specific_signal = 1;
}
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
received_signal = uwsgi_signal;
}
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
}
received_signal = uwsgi_signal;
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
}
}
return received_signal;
return received_signal;
}
void uwsgi_receive_signal(int fd, char *name, int id) {
@@ -565,27 +592,27 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
ssize_t ret = read(fd, &uwsgi_signal, 1);
if (ret == 0) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
else if (ret > 0) {
}
else if (ret > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
}
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
}
return;
destroy:
// better to kill the whole worker...
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
end_me(0);
}
+105 -93
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_SNMP
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -249,11 +247,14 @@ static uint64_t get_uwsgi_snmp_value(uint64_t val, uint8_t * oid_t) {
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val, uint8_t * oid_t) {
val--;
uwsgi_wlock(uwsgi.snmp_lock);
if (uwsgi.shared->snmp_value[val].type) {
*oid_t = uwsgi.shared->snmp_value[val].type;
uwsgi_rwunlock(uwsgi.snmp_lock);
return uwsgi.shared->snmp_value[val].val;
}
uwsgi_rwunlock(uwsgi.snmp_lock);
*oid_t = SNMP_NULL;
return 0;
}
@@ -278,133 +279,144 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
for (i = tlen - 1; i >= 0; i--) {
#endif
cval[j] = ptr[1 + i];
j++;
}
return tlen + 1;
cval[j] = ptr[1 + i];
j++;
}
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) &snmp_val;
return tlen + 1;
}
// check for counter, counter64 or gauge
static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * buffer) {
uint8_t tlen;
int i, j;
uint8_t *ptr = (uint8_t *) & snmp_val;
if (oid_type == SNMP_COUNTER64) {
tlen = 8;
}
else if (oid_type == SNMP_NULL || oid_type == 0) {
tlen = 0;
}
else {
tlen = 4;
}
// check for counter, counter64 or gauge
buffer[0] = tlen;
if (oid_type == SNMP_COUNTER64) {
tlen = 8;
}
else if (oid_type == SNMP_NULL || oid_type == 0) {
tlen = 0;
}
else {
tlen = 4;
}
j = 1;
buffer[0] = tlen;
j = 1;
#ifdef __BIG_ENDIAN__
for (i = 0; i < tlen; i++) {
for (i = 0; i < tlen; i++) {
#else
for (i = tlen - 1; i >= 0; i--) {
for (i = tlen - 1; i >= 0; i--) {
#endif
buffer[j] = ptr[i];
j++;
}
buffer[j] = ptr[i];
j++;
}
return tlen + 1;
}
return tlen + 1;
}
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint64_t snmp_val;
uint8_t oid_sz;
uint8_t oid_type;
static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
uint64_t snmp_val;
uint8_t oid_sz;
uint8_t oid_type;
if (oid1 == 1) {
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
}
else if (oid1 == 2) {
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
}
else {
return -1;
}
if (oid1 == 1) {
snmp_val = get_uwsgi_snmp_value(oid2, &oid_type);
}
else if (oid1 == 2) {
snmp_val = get_uwsgi_custom_snmp_value(oid2, &oid_type);
}
else {
return -1;
}
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
buffer[size - 2] = oid_type;
oid_sz = snmp_int_to_snmp(snmp_val, oid_type, buffer + (size - 1));
if (oid_sz < 1)
return -1;
if (oid_sz < 1)
return -1;
oid_sz--;
oid_sz--;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
buffer[1] += oid_sz;
*seq1 += oid_sz;
*seq2 += oid_sz;
*seq3 += oid_sz;
return size + oid_sz;
return size + oid_sz;
}
}
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
if (value) {
uwsgi.snmp_addr = value;
uwsgi.master_process = 1;
}
if (value) {
uwsgi.snmp_addr = value;
uwsgi.master_process = 1;
}
}
void uwsgi_opt_snmp_community(char *opt, char *value, void *foobar) {
uwsgi.snmp = 1;
uwsgi.snmp_community = value;
uwsgi.snmp_community = value;
}
int uwsgi_setup_snmp(void) {
int snmp_fd = -1;
int i;
if (uwsgi.snmp) {
if (uwsgi.snmp_community) {
if (strlen(uwsgi.snmp_community) > 72) {
uwsgi_log("*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, 72);
}
else {
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
}
}
if (uwsgi.snmp_community) {
if (strlen(uwsgi.snmp_community) > 72) {
uwsgi_log("*** warning the supplied SNMP community string will be truncated to 72 chars ***\n");
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, 72);
}
else {
memcpy(uwsgi.shared->snmp_community, uwsgi.snmp_community, strlen(uwsgi.snmp_community) + 1);
}
}
uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
uwsgi.shared->snmp_gvalue[0].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[0].val = &uwsgi.workers[0].requests;
for (i = 0; i < uwsgi.numproc; i++) {
uwsgi.shared->snmp_gvalue[30 + i].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[30 + i].val = &uwsgi.workers[i + 1].requests;
}
for (i = 0; i < uwsgi.numproc; i++) {
uwsgi.shared->snmp_gvalue[30 + i].type = SNMP_COUNTER64;
uwsgi.shared->snmp_gvalue[30 + i].val = &uwsgi.workers[i + 1].requests;
}
if (uwsgi.snmp_addr) {
snmp_fd = bind_to_udp(uwsgi.snmp_addr, 0, 0);
if (snmp_fd < 0) {
uwsgi_log("unable to bind to udp socket. SNMP service will be disabled.\n");
}
else {
uwsgi_log("SNMP server enabled on %s\n", uwsgi.snmp_addr);
event_queue_add_fd_read(uwsgi.master_queue, snmp_fd);
}
}
else {
uwsgi_log("SNMP agent enabled.\n");
}
if (uwsgi.snmp_addr) {
snmp_fd = bind_to_udp(uwsgi.snmp_addr, 0, 0);
if (snmp_fd < 0) {
uwsgi_log("unable to bind to udp socket. SNMP service will be disabled.\n");
}
else {
uwsgi_log("SNMP server enabled on %s\n", uwsgi.snmp_addr);
event_queue_add_fd_read(uwsgi.master_queue, snmp_fd);
}
}
else {
uwsgi_log("SNMP agent enabled.\n");
}
}
}
return snmp_fd;
}
#else
#warning "*** SNMP support is disabled ***"
#endif
void uwsgi_master_manage_snmp(int snmp_fd) {
struct sockaddr_in udp_client;
socklen_t udp_len = sizeof(udp_client);
ssize_t rlen = recvfrom(snmp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
}
else if (rlen > 0) {
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
}
}
+458 -395
View File
File diff suppressed because it is too large Load Diff
+109 -94
View File
@@ -1,4 +1,3 @@
#ifdef UWSGI_SPOOLER
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -13,27 +12,31 @@ static void spooler_manage_task(struct uwsgi_spooler *, char *, char *);
static uint64_t wakeup = 0;
// function to allow waking up the spooler if blocked in event_wait
void spooler_wakeup() { wakeup++; }
void spooler_wakeup() {
wakeup++;
}
void uwsgi_opt_add_spooler(char *opt, char *directory, void *mode) {
int i;
struct uwsgi_spooler *us;
if (access(directory, R_OK | W_OK | X_OK)) {
uwsgi_error("[spooler directory] access()");
exit(1);
}
if (access(directory, R_OK | W_OK | X_OK)) {
uwsgi_error("[spooler directory] access()");
exit(1);
}
if (uwsgi.spooler_numproc > 0) {
for(i=0;i<uwsgi.spooler_numproc;i++) {
for (i = 0; i < uwsgi.spooler_numproc; i++) {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
if (mode)
us->mode = (long) mode;
}
}
else {
us = uwsgi_new_spooler(directory);
if (mode) us->mode = (long) mode;
us = uwsgi_new_spooler(directory);
if (mode)
us->mode = (long) mode;
}
}
@@ -41,31 +44,31 @@ void uwsgi_opt_add_spooler(char *opt, char *directory, void *mode) {
struct uwsgi_spooler *uwsgi_new_spooler(char *dir) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (!uspool) {
uwsgi.spoolers = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uwsgi.spoolers;
}
else {
while(uspool) {
if (uspool->next == NULL) {
uspool->next = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uspool->next;
break;
}
uspool = uspool->next;
}
}
if (!uspool) {
uwsgi.spoolers = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uwsgi.spoolers;
}
else {
while (uspool) {
if (uspool->next == NULL) {
uspool->next = uwsgi_calloc_shared(sizeof(struct uwsgi_spooler));
uspool = uspool->next;
break;
}
uspool = uspool->next;
}
}
if (!realpath(dir, uspool->dir)) {
uwsgi_error("[spooler] realpath()");
exit(1);
}
if (!realpath(dir, uspool->dir)) {
uwsgi_error("[spooler] realpath()");
exit(1);
}
uspool->next = NULL;
uspool->next = NULL;
return uspool;
return uspool;
}
@@ -73,18 +76,18 @@ struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) {
while (uspool) {
if (!strcmp(uspool->dir, name)) {
return uspool;
}
uspool = uspool->next;
}
return NULL;
}
pid_t spooler_start(struct uwsgi_spooler *uspool) {
pid_t spooler_start(struct uwsgi_spooler * uspool) {
int i;
pid_t pid = uwsgi_fork("uWSGI spooler");
@@ -93,8 +96,18 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
exit(1);
}
else if (pid == 0) {
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
// USR1 will be used to wake up the spooler
uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
@@ -105,24 +118,24 @@ pid_t spooler_start(struct uwsgi_spooler *uspool) {
uwsgi_close_all_sockets();
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
if (uwsgi.p[i]->post_fork) {
uwsgi.p[i]->post_fork();
}
}
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
@@ -137,14 +150,14 @@ void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
if (unlink(file)) {
uwsgi_error("unlink()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
uwsgi_error("unlink()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
}
@@ -194,7 +207,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
// now lock the file, it will no be runnable, until the lock is not removed
// a race could come if the spooler take the file before fcntl is called
// in such case the spooler will detect a zeroed file and will retry later
// in such case the spooler will detect a zeroed file and will retry later
if (uwsgi_fcntl_lock(fd)) {
close(fd);
uwsgi_unlock(uspool->lock);
@@ -217,8 +230,8 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
}
if (body && body_len > 0) {
if ((size_t)write(fd, body, body_len) != body_len) {
goto clear;
if ((size_t) write(fd, body, body_len) != body_len) {
goto clear;
}
}
@@ -241,8 +254,8 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
close(fd);
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
// and here waiting threads can continue
uwsgi_unlock(uspool->lock);
@@ -252,7 +265,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
*/
struct uwsgi_spooler *spoolers = uwsgi.spoolers;
while(spoolers) {
while (spoolers) {
if (!strcmp(spoolers->dir, uspool->dir)) {
if (spoolers->pid > 0 && spoolers->running == 0) {
(void) kill(spoolers->pid, SIGUSR1);
@@ -264,7 +277,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
return 1;
clear:
clear:
uwsgi_unlock(uspool->lock);
uwsgi_error("write()");
if (unlink(filename)) {
@@ -355,12 +368,6 @@ void spooler(struct uwsgi_spooler *uspool) {
}
wakeup = tmp_wakeup;
// need to recycle ?
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
end_me(0);
}
}
}
@@ -370,17 +377,18 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
n = scandir(dir, &tasklist, 0, versionsort);
if (n < 0) {
uwsgi_error("scandir()");
return;
}
while(n--) {
while (n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
free(tasklist[n]);
}
free(tasklist);
@@ -393,7 +401,8 @@ static void spooler_readdir(struct uwsgi_spooler *uspool, char *dir) {
DIR *sdir;
struct dirent *dp;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
sdir = opendir(dir);
if (sdir) {
@@ -418,7 +427,8 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
int spool_fd;
if (!dir) dir = uspool->dir;
if (!dir)
dir = uspool->dir;
if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
struct stat sf_lstat;
@@ -487,16 +497,16 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
uwsgi_error("read()");
destroy_spool(dir, task);
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
return;
}
}
// body available ?
if (sf_lstat.st_size > (uh.pktsize+4)) {
body_len = sf_lstat.st_size - (uh.pktsize+4);
if (sf_lstat.st_size > (uh.pktsize + 4)) {
body_len = sf_lstat.st_size - (uh.pktsize + 4);
body = uwsgi_malloc(body_len);
if ((size_t)uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
if ((size_t) uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
uwsgi_error("read()");
destroy_spool(dir, task);
uwsgi_protected_close(spool_fd);
@@ -520,27 +530,28 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
int callable_found = 0;
for(i=0;i<256;i++) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler) {
time_t now = uwsgi_now();
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
if (ret == 0) continue;
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
if (ret == 0)
continue;
callable_found = 1;
// increase task counter
uspool->tasks++;
if (ret == -2) {
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now()-now);
destroy_spool(dir, task);
uwsgi_log("[spooler %s pid: %d] done with task %s after %lld seconds\n", uspool->dir, (int) uwsgi.mypid, task, (long long) uwsgi_now() - now);
destroy_spool(dir, task);
}
// re-spool it
break;
break;
}
}
@@ -551,9 +562,17 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
uwsgi_protected_close(spool_fd);
uspool->running = 0;
// need to recycle ?
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t) uwsgi.spooler_max_tasks) {
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
end_me(0);
}
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
uwsgi_error("chdir()");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
@@ -564,7 +583,3 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
}
}
#else
#warning "*** Spooler support is disabled ***"
#endif
+4 -4
View File
@@ -8,9 +8,9 @@ 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) {
int value_len = strlen(fields[1]) + 1;
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);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
@@ -20,7 +20,7 @@ static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, cha
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
@@ -28,7 +28,7 @@ void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon+1;
query = colon + 1;
}
}
+499
View File
@@ -0,0 +1,499 @@
#include "../uwsgi.h"
#include <openssl/rand.h>
extern struct uwsgi_server uwsgi;
/*
ssl additional datas are retrieved via indexes.
You can create an index with SSL_CTX_get_ex_new_index and
set data in it with SSL_CTX_set_ex_data
*/
void uwsgi_ssl_init(void) {
OPENSSL_config(NULL);
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
uwsgi.ssl_initialized = 1;
}
void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
if (where & SSL_CB_HANDSHAKE_DONE) {
if (ssl->s3) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
}
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
return 1;
}
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
char session_blob[4096];
int len = i2d_SSL_SESSION(sess, NULL);
if (len > 4096) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] unable to store session of size %d\n", len);
}
return 0;
}
unsigned char *p = (unsigned char *) session_blob;
i2d_SSL_SESSION(sess, &p);
// ok let's write the value to the cache
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi_cache_set2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, session_blob, len, uwsgi.ssl_sessions_timeout, 0)) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] unable to store session of size %d in the cache\n", len);
}
}
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
return 0;
}
SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen, int *copy) {
uint64_t valsize = 0;
*copy = 0;
uwsgi_rlock(uwsgi.ssl_sessions_cache->lock);
char *value = uwsgi_cache_get2(uwsgi.ssl_sessions_cache, (char *)key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] cache miss\n");
}
return NULL;
}
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
return sess;
}
void uwsgi_ssl_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) {
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi_cache_del2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, 0, 0)) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] error removing cache item\n");
}
}
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
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);
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;
}
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) {
SSL_set_SSL_CTX(ssl, url->custom_ptr);
return SSL_TLSEXT_ERR_OK;
}
url = url->next;
}
#endif
if (uwsgi.sni_dir) {
size_t sni_dir_len = strlen(uwsgi.sni_dir);
char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4);
char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4);
char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3);
if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) {
char *client_ca = NULL;
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);
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:
free(sni_dir_cert);
free(sni_dir_key);
free(sni_dir_client_ca);
}
return SSL_TLSEXT_ERR_NOACK;
}
#endif
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
if (!ctx) {
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
return NULL;
}
// this part is taken from nginx and stud, removing unneeded functionality
// stud (for me) has made the best choice on choosing DH approach
long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
// disable compression (if possibile)
#ifdef SSL_OP_NO_COMPRESSION
ssloptions |= SSL_OP_NO_COMPRESSION;
#endif
// release/reuse buffers as soon as possibile
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
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;
}
// this part is based from stud
BIO *bio = BIO_new_file(crt, "r");
if (bio) {
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
if (dh) {
SSL_CTX_set_tmp_dh(ctx, dh);
DH_free(dh);
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
#ifdef NID_X9_62_prime256v1
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
EC_KEY_free(ecdh);
#endif
#endif
#endif
}
}
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);
return NULL;
}
// if ciphers are specified, prefer server ciphers
if (ciphers && strlen(ciphers) > 0) {
if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
uwsgi_log("[uwsgi-ssl] unable to set requested ciphers (%s) for context \"%s\"\n", ciphers, name);
SSL_CTX_free(ctx);
return NULL;
}
ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
}
// set session context (if possibile), this is required for client certificate authentication
if (name) {
SSL_CTX_set_session_id_context(ctx, (unsigned char *) name, strlen(name));
}
if (client_ca) {
if (client_ca[0] == '!') {
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, uwsgi_ssl_verify_callback);
client_ca++;
}
else {
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, uwsgi_ssl_verify_callback);
}
// in the future we should allow to set the verify depth
SSL_CTX_set_verify_depth(ctx, 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);
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);
return NULL;
}
SSL_CTX_set_client_CA_list(ctx, list);
}
SSL_CTX_set_info_callback(ctx, uwsgi_ssl_info_cb);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_CTX_set_tlsext_servername_callback(ctx, uwsgi_sni_cb);
#endif
// disable session caching by default
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if (uwsgi.ssl_sessions_use_cache) {
// we need to early initialize locking and caching
uwsgi_setup_locking();
uwsgi_cache_create_all();
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);
}
if (!uwsgi.ssl_sessions_cache->max_items) {
uwsgi_log("you have to enable uWSGI cache to use it as SSL session store !!!\n");
exit(1);
}
if (uwsgi.ssl_sessions_cache->blocksize < 4096) {
uwsgi_log("cache blocksize for SSL session store must be at least 4096 bytes\n");
exit(1);
}
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|
SSL_SESS_CACHE_NO_INTERNAL|
SSL_SESS_CACHE_NO_AUTO_CLEAR);
#ifdef SSL_OP_NO_TICKET
ssloptions |= SSL_OP_NO_TICKET;
#endif
// just for fun
SSL_CTX_sess_set_cache_size(ctx, 0);
// set the callback for ssl sessions
SSL_CTX_sess_set_new_cb(ctx, uwsgi_ssl_session_new_cb);
SSL_CTX_sess_set_get_cb(ctx, uwsgi_ssl_session_get_cb);
SSL_CTX_sess_set_remove_cb(ctx, uwsgi_ssl_session_remove_cb);
}
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
SSL_CTX_set_options(ctx, ssloptions);
return ctx;
}
char *uwsgi_rsa_sign(char *algo_key, char *message, size_t message_len, unsigned int *s_len) {
// openssl could not be initialized
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
*s_len = 0;
EVP_PKEY *pk = NULL;
char *algo = uwsgi_str(algo_key);
char *colon = strchr(algo, ':');
if (!colon) {
uwsgi_log("invalid RSA signature syntax, must be: <digest>:<pemfile>\n");
free(algo);
return NULL;
}
*colon = 0;
char *keyfile = colon + 1;
char *signature = NULL;
FILE *kf = fopen(keyfile, "r");
if (!kf) {
uwsgi_error_open(keyfile);
free(algo);
return NULL;
}
if (PEM_read_PrivateKey(kf, &pk, NULL, NULL) == 0) {
uwsgi_log("unable to load private key: %s\n", keyfile);
free(algo);
fclose(kf);
return NULL;
}
fclose(kf);
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (!ctx) {
free(algo);
EVP_PKEY_free(pk);
return NULL;
}
const EVP_MD *md = EVP_get_digestbyname(algo);
if (!md) {
uwsgi_log("unknown digest algo: %s\n", algo);
free(algo);
EVP_PKEY_free(pk);
EVP_MD_CTX_destroy(ctx);
return NULL;
}
*s_len = EVP_PKEY_size(pk);
signature = uwsgi_malloc(*s_len);
if (EVP_SignInit_ex(ctx, md, NULL) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
if (EVP_SignUpdate(ctx, message, message_len) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
if (EVP_SignFinal(ctx, (unsigned char *) signature, s_len, pk) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
clear:
free(algo);
EVP_PKEY_free(pk);
EVP_MD_CTX_destroy(ctx);
return signature;
}
char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
uint16_t i;
char *filename = uwsgi_concat4n(base, strlen(base), "/", 1, key, keylen, ".pem\0", 5);
for (i = strlen(base) + 1; i < (strlen(base) + 1) + keylen; i++) {
if (filename[i] >= '0' && filename[i] <= '9')
continue;
if (filename[i] >= 'A' && filename[i] <= 'Z')
continue;
if (filename[i] >= 'a' && filename[i] <= 'z')
continue;
if (filename[i] == '.')
continue;
if (filename[i] == '-')
continue;
if (filename[i] == '_')
continue;
filename[i] = '_';
}
return filename;
}
char *uwsgi_ssl_rand(size_t len) {
unsigned char *buf = uwsgi_calloc(len+1);
if (RAND_bytes(buf, len) <= 0) {
return NULL;
}
return (char *) buf;
}
char *uwsgi_sha1(char *src, size_t len, char *dst) {
SHA_CTX sha;
SHA1_Init(&sha);
SHA1_Update(&sha, src, len);
SHA1_Final((unsigned char *)dst, &sha);
return dst;
}
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
SHA_CTX sha;
SHA1_Init(&sha);
SHA1_Update(&sha, s1, len1);
SHA1_Update(&sha, s2, len2);
SHA1_Final((unsigned char *)dst, &sha);
return dst;
}
void uwsgi_opt_sni(char *opt, char *value, void *foobar) {
char *client_ca = NULL;
char *v = uwsgi_str(value);
char *space = strchr(v, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
exit(1);
}
*space = 0;
char *crt = space+1;
char *key = strchr(crt, ',');
if (!key) {
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
exit(1);
}
*key = '\0'; key++;
char *ciphers = strchr(key, ',');
if (ciphers) {
*ciphers = '\0'; ciphers++;
client_ca = strchr(ciphers, ',');
if (client_ca) {
*client_ca = '\0'; client_ca++;
}
}
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
SSL_CTX *ctx = uwsgi_ssl_new_server_context(v, crt, key, ciphers, client_ca);
if (!ctx) {
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", v);
free(v);
return;
}
#ifdef UWSGI_PCRE
if (!strcmp(opt, "sni-regexp")) {
struct uwsgi_regexp_list *url = uwsgi_regexp_new_list(&uwsgi.sni_regexp, v);
url->custom_ptr = ctx;
}
else {
#endif
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, v);
usl->custom_ptr = ctx;
#ifdef UWSGI_PCRE
}
#endif
}
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
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);
return NULL;
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
usl->custom_ptr = ctx;
return usl;
}
+623
View File
@@ -0,0 +1,623 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
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;
// check for supported encodings
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
// check for 'all'
if (uwsgi.static_gzip_all) goto gzip;
// 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)) {
goto gzip;
}
usl = usl->next;
}
// 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)) {
goto gzip;
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// 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) {
goto gzip;
}
url = url->next;
}
#endif
return 0;
gzip:
memcpy(filename + filename_len, ".gz\0", 4);
filename_len += 3;
if (stat(filename, st)) {
filename_len -= 3;
filename[filename_len] = 0;
return 0;
}
return 1;
}
static int set_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
struct tm *hdtm = gmtime(&t);
int ret = snprintf(dst, 31, "%s, %02d %s %4d %02d:%02d:%02d GMT",
week[hdtm->tm_wday], hdtm->tm_mday, months[hdtm->tm_mon], hdtm->tm_year + 1900, hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
if (ret <= 0 || ret > 31) {
return 0;
}
return ret;
}
// only RFC 1123 is supported
static time_t parse_http_date(char *date, uint16_t len) {
struct tm hdtm;
if (len != 29 && date[3] != ',')
return 0;
hdtm.tm_mday = uwsgi_str2_num(date + 5);
switch (date[8]) {
case 'J':
if (date[9] == 'a') {
hdtm.tm_mon = 0;
break;
}
if (date[9] == 'u') {
if (date[10] == 'n') {
hdtm.tm_mon = 5;
break;
}
if (date[10] == 'l') {
hdtm.tm_mon = 6;
break;
}
return 0;
}
return 0;
case 'F':
hdtm.tm_mon = 1;
break;
case 'M':
if (date[9] != 'a')
return 0;
if (date[10] == 'r') {
hdtm.tm_mon = 2;
break;
}
if (date[10] == 'y') {
hdtm.tm_mon = 4;
break;
}
return 0;
case 'A':
if (date[10] == 'r') {
hdtm.tm_mon = 3;
break;
}
if (date[10] == 'g') {
hdtm.tm_mon = 7;
break;
}
return 0;
case 'S':
hdtm.tm_mon = 8;
break;
case 'O':
hdtm.tm_mon = 9;
break;
case 'N':
hdtm.tm_mon = 10;
break;
case 'D':
hdtm.tm_mon = 11;
break;
default:
return 0;
}
hdtm.tm_year = uwsgi_str4_num(date + 12) - 1900;
hdtm.tm_hour = uwsgi_str2_num(date + 17);
hdtm.tm_min = uwsgi_str2_num(date + 20);
hdtm.tm_sec = uwsgi_str2_num(date + 23);
return timegm(&hdtm);
}
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
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);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_type_mtime;
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
#ifdef UWSGI_PCRE
int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
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);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_path_info;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
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);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_path_info_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_uri;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
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);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_uri_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = set_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
#endif
char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
int i;
int count = 0;
char *ext = NULL;
for (i = namelen - 1; i >= 0; i--) {
if (!isalnum((int) name[i])) {
if (name[i] == '.') {
ext = name + (namelen - count);
break;
}
}
count++;
}
if (!ext)
return NULL;
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while (udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
udd->hits++;
// auto optimization
if (udd->prev) {
if (udd->hits > udd->prev->hits) {
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
if (udd_parent) {
udd_parent->next = udd;
}
if (udd->next) {
udd->next->prev = udd_prev;
}
udd_prev->prev = udd;
udd_prev->next = udd->next;
udd->prev = udd_parent;
udd->next = udd_prev;
if (udd->prev == NULL) {
uwsgi.mimetypes = udd;
}
}
}
*size = udd->vallen;
return udd->value;
}
udd = udd->next;
}
return NULL;
}
ssize_t uwsgi_append_static_path(char *dir, size_t dir_len, char *file, size_t file_len) {
size_t len = dir_len;
if (len + 1 + file_len > PATH_MAX) {
return -1;
}
if (dir[len - 1] == '/') {
memcpy(dir + len, file, file_len);
dir[len + file_len] = 0;
len += file_len;
}
else {
dir[len] = '/';
memcpy(dir + len + 1, file, file_len);
dir[len + 1 + file_len] = 0;
len += 1 + file_len;
}
return len;
}
static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st, struct uwsgi_string_list **index) {
int ret = stat(filename, st);
// if non-existant return -1
if (ret < 0)
return -1;
if (S_ISREG(st->st_mode))
return 0;
// check for index
if (S_ISDIR(st->st_mode)) {
struct uwsgi_string_list *usl = uwsgi.static_index;
while (usl) {
ssize_t new_len = uwsgi_append_static_path(filename, *filename_len, usl->value, usl->len);
if (new_len >= 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
#endif
if (uwsgi_is_file2(filename, st)) {
*index = usl;
*filename_len = new_len;
return 0;
}
// reset to original name
filename[*filename_len] = 0;
}
usl = usl->next;
}
}
return -1;
}
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
int mime_type_size = 0;
char http_last_modified[49];
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
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);
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);
return uwsgi_response_write_headers_do(wsgi_req);
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
// HTTP status
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);
uwsgi_add_expires_path_info(wsgi_req, st);
uwsgi_add_expires_uri(wsgi_req, st);
#endif
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
// check for content-type related headers
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
}
// increase static requests counter
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].static_requests++;
// nginx
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);
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);
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
if (uwsgi_response_add_content_length(wsgi_req, st->st_size)) return -1;
int size = set_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
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
wsgi_req->status = 200;
return 0;
}
// Ok, the file must be transferred from uWSGI
// offloading will be automatically managed
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);
}
wsgi_req->status = 200;
return 0;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {
struct stat st;
char real_filename[PATH_MAX + 1];
size_t real_filename_len = 0;
char *filename = NULL;
size_t filename_len = 0;
struct uwsgi_string_list *index = NULL;
if (!is_a_file) {
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
filename_len = document_root_len + 1 + path_info_len;
}
else {
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
filename_len = document_root_len;
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif
if (uwsgi.static_cache_paths) {
uwsgi_rlock(uwsgi.static_cache_paths->lock);
uint64_t item_len;
char *item = uwsgi_cache_get2(uwsgi.static_cache_paths, filename, filename_len, &item_len);
if (item && item_len > 0 && item_len <= PATH_MAX) {
memcpy(real_filename, item, item_len);
real_filename_len = item_len;
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
goto found;
}
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
}
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
}
real_filename_len = strlen(real_filename);
if (uwsgi.static_cache_paths) {
uwsgi_wlock(uwsgi.static_cache_paths->lock);
uwsgi_cache_set2(uwsgi.static_cache_paths, filename, filename_len, real_filename, real_filename_len, uwsgi.use_static_cache_paths, UWSGI_CACHE_FLAG_UPDATE);
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
}
found:
free(filename);
if (uwsgi_starts_with(real_filename, real_filename_len, document_root, document_root_len)) {
struct uwsgi_string_list *safe = uwsgi.static_safe;
while(safe) {
if (!uwsgi_starts_with(real_filename, real_filename_len, safe->value, safe->len)) {
goto safe;
}
safe = safe->next;
}
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s or a safe path\n", real_filename, document_root_len, document_root);
return -1;
}
safe:
if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) {
if (index) {
// if we are here the PATH_INFO need to be changed
if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) {
return -1;
}
}
// skip methods other than GET and HEAD
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
return -1;
}
// check for skippable ext
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
while (sse) {
if (real_filename_len >= sse->len) {
if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
return -1;
}
}
sse = sse->next;
}
#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) {
return 0;
}
wsgi_req->routes_applied = 1;
#endif
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
}
return -1;
}
+430 -115
View File
@@ -3,15 +3,22 @@
utility functions for fast generating json output for the stats subsystem
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_stats *uwsgi_stats_new(size_t chunk_size) {
struct uwsgi_stats *us = uwsgi_malloc(sizeof(struct uwsgi_stats));
us->base = uwsgi_malloc(chunk_size);
us->base[0] = '{';
us->base[1] = '\n';
us->pos = 2;
us->pos = 1;
us->chunk = chunk_size;
us->size = chunk_size;
us->tabs = 1;
us->dirty = 0;
us->minified = uwsgi.stats_minified;
if (!us->minified) {
us->base[1] = '\n';
us->pos++;
}
return us;
}
@@ -19,9 +26,10 @@ int uwsgi_stats_symbol(struct uwsgi_stats *us, char sym) {
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
if (ptr+1 > watermark) {
if (ptr + 1 > watermark) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
@@ -36,6 +44,8 @@ int uwsgi_stats_symbol_nl(struct uwsgi_stats *us, char sym) {
if (uwsgi_stats_symbol(us, sym)) {
return -1;
}
if (us->minified)
return 0;
return uwsgi_stats_symbol(us, '\n');
}
@@ -45,24 +55,33 @@ int uwsgi_stats_comma(struct uwsgi_stats *us) {
}
int uwsgi_stats_apply_tabs(struct uwsgi_stats *us) {
if (us->minified)
return 0;
size_t i;
for(i=0;i<us->tabs;i++) {
if (uwsgi_stats_symbol(us, '\t')) return -1;
for (i = 0; i < us->tabs; i++) {
if (uwsgi_stats_symbol(us, '\t'))
return -1;
};
return 0;
}
int uwsgi_stats_object_open(struct uwsgi_stats *us) {
if (uwsgi_stats_apply_tabs(us)) return -1;
us->tabs++;
if (uwsgi_stats_apply_tabs(us))
return -1;
if (!us->minified)
us->tabs++;
return uwsgi_stats_symbol_nl(us, '{');
}
int uwsgi_stats_object_close(struct uwsgi_stats *us) {
if (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
if (!us->minified) {
if (uwsgi_stats_symbol(us, '\n'))
return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us))
return -1;
}
return uwsgi_stats_symbol(us, '}');
}
@@ -72,161 +91,187 @@ int uwsgi_stats_list_open(struct uwsgi_stats *us) {
}
int uwsgi_stats_list_close(struct uwsgi_stats *us) {
if (uwsgi_stats_symbol(us, '\n')) return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us)) return -1;
if (!us->minified) {
if (uwsgi_stats_symbol(us, '\n'))
return -1;
us->tabs--;
if (uwsgi_stats_apply_tabs(us))
return -1;
}
return uwsgi_stats_symbol(us, ']');
}
int uwsgi_stats_keyval(struct uwsgi_stats *us, char *key, char *value) {
if (uwsgi_stats_apply_tabs(us)) return -1;
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s\"", key, value);
if (ret < 0) return -1;
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyval_comma(struct uwsgi_stats *us, char *key, char *value) {
int ret = uwsgi_stats_keyval(us, key, value);
if (ret) return -1;
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyvalnum(struct uwsgi_stats *us, char *key, char *value, unsigned long long num) {
if (uwsgi_stats_apply_tabs(us)) return -1;
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
int ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0) return -1;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%s%llu\"", key, value, num);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
int uwsgi_stats_keyvalnum_comma(struct uwsgi_stats *us, char *key, char *value, unsigned long long num) {
int ret = uwsgi_stats_keyvalnum(us, key, value, num);
if (ret) return -1;
return uwsgi_stats_comma(us);
int ret = uwsgi_stats_keyvalnum(us, key, value, num);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyvaln(struct uwsgi_stats *us, char *key, char *value, int vallen) {
if (uwsgi_stats_apply_tabs(us)) return -1;
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
int ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0) return -1;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":\"%.*s\"", key, vallen, value);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
int uwsgi_stats_keyvaln_comma(struct uwsgi_stats *us, char *key, char *value, int vallen) {
int ret = uwsgi_stats_keyvaln(us, key, value, vallen);
if (ret) return -1;
return uwsgi_stats_comma(us);
int ret = uwsgi_stats_keyvaln(us, key, value, vallen);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
int uwsgi_stats_key(struct uwsgi_stats *us, char *key) {
if (uwsgi_stats_apply_tabs(us)) return -1;
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
int ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0) return -1;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":", key);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
int ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0) return -1;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\"", str);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
@@ -234,33 +279,303 @@ int uwsgi_stats_str(struct uwsgi_stats *us, char *str) {
int uwsgi_stats_keylong(struct uwsgi_stats *us, char *key, unsigned long long num) {
if (uwsgi_stats_apply_tabs(us)) return -1;
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr ;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0) return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base) return -1;
int ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr ;
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0) return -1;
}
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%llu", key, num);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
us->pos += ret;
return 0;
}
int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long long num) {
int ret = uwsgi_stats_keylong(us, key, num);
if (ret) return -1;
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
if (uwsgi.stats_http) {
if (uwsgi_send_http_stats(client_fd)) {
close(client_fd);
return;
}
}
struct uwsgi_stats *us = func();
if (!us)
goto end;
size_t remains = us->pos;
off_t pos = 0;
while (remains > 0) {
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
goto end0;
}
ssize_t res = write(client_fd, us->base + pos, remains);
if (res <= 0) {
if (res < 0) {
uwsgi_error("write()");
}
goto end0;
}
pos += res;
remains -= res;
}
end0:
free(us->base);
free(us);
end:
close(client_fd);
}
struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
struct uwsgi_stats_pusher *usp = uwsgi.stats_pushers;
while (usp) {
if (!strcmp(usp->name, name)) {
return usp;
}
usp = usp->next;
}
return usp;
}
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
struct uwsgi_stats_pusher_instance *old_uspi = NULL, *uspi = uwsgi.stats_pusher_instances;
while (uspi) {
old_uspi = uspi;
uspi = uspi->next;
}
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
uspi->arg = arg;
if (old_uspi) {
old_uspi->next = uspi;
}
else {
uwsgi.stats_pusher_instances = uspi;
}
return uspi;
}
void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
void *events = event_queue_alloc(1);
for (;;) {
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
if (nevents > 0) {
int interesting_fd = event_queue_interesting_fd(events, 0);
char buf[4096];
ssize_t len = read(interesting_fd, buf, 4096);
if (len <= 0) {
uwsgi_log("[uwsgi-stats-pusher] goodbye...\n");
return;
}
uwsgi_log("[uwsgi-stats-pusher] message received from master: %.*s\n", (int) len, buf);
continue;
}
time_t now = uwsgi_now();
struct uwsgi_stats_pusher_instance *uspi = uwsgi.stats_pusher_instances;
struct uwsgi_stats *us = NULL;
while (uspi) {
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
if ((uspi->last_run + delta) <= now) {
if (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
else {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us)
goto next;
}
uspi->pusher->func(uspi, now, us->base, us->pos);
}
uspi->last_run = now;
}
next:
uspi = uspi->next;
}
if (us) {
free(us->base);
free(us);
}
}
}
void uwsgi_stats_pusher_setup() {
struct uwsgi_string_list *usl = uwsgi.requested_stats_pushers;
while (usl) {
char *ssp = uwsgi_str(usl->value);
struct uwsgi_stats_pusher *pusher = NULL;
char *colon = strchr(ssp, ':');
if (colon) {
*colon = 0;
}
pusher = uwsgi_stats_pusher_get(ssp);
if (!pusher) {
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
free(ssp);
exit(1);
}
char *arg = NULL;
if (colon) {
arg = colon + 1;
*colon = ':';
}
uwsgi_stats_pusher_add(pusher, arg);
usl = usl->next;
free(ssp);
}
}
struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pusher_instance *, time_t, char *, size_t)) {
struct uwsgi_stats_pusher *pusher = uwsgi.stats_pushers, *old_pusher = NULL;
while (pusher) {
old_pusher = pusher;
pusher = pusher->next;
}
pusher = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher));
pusher->name = name;
pusher->func = func;
if (old_pusher) {
old_pusher->next = pusher;
}
else {
uwsgi.stats_pushers = pusher;
}
return pusher;
}
struct uwsgi_stats_pusher_file_conf {
char *path;
char *freq;
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
if (!uspi->configured) {
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
if (uspi->arg) {
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
free(uspi);
return;
}
}
if (!uspic->path)
uspic->path = "uwsgi.stats";
if (!uspic->separator)
uspic->separator = "\n\n";
if (uspic->freq)
uspi->freq = atoi(uspic->freq);
uspi->configured = 1;
uspi->data = uspic;
}
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uspic->path);
return;
}
ssize_t rlen = write(fd, json, json_len);
if (rlen != (ssize_t) json_len) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
rlen = write(fd, uspic->separator, strlen(uspic->separator));
if (rlen != (ssize_t) strlen(uspic->separator)) {
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
}
close(fd);
}
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;
uint16_t i;
// replace " with '
for(i=0;i<kl;i++) {
if (k[i] == '"') {
k[i] = '\'';
}
}
for(i=0;i<vl;i++) {
if (v[i] == '"') {
v[i] = '\'';
}
}
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
if (uwsgi_stats_str(us, var)) {
us->dirty = 1;
free(var);
return;
}
free(var);
if (uwsgi_stats_comma(us)) {
us->dirty = 1;
}
return;
}
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;
uint16_t pktsize = uh->pktsize;
if (!pktsize) return 0;
char *dst = uwsgi.workers[0].cores[0].buffer;
memcpy(dst, uc->buffer+4, uwsgi.buffer_size);
// ok now check if something changed...
if (!uc->in_request) return 0;
if (uh->pktsize != pktsize) return 0;
if (memcmp(dst, uc->buffer+4, uwsgi.buffer_size)) return 0;
// nothing changed let's dump vars
int ret = uwsgi_hooked_parse(dst, pktsize, stats_dump_var, us);
if (ret) return -1;
if (us->dirty) return -1;
if (uwsgi_stats_str(us, "")) return -1;
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
#include "../uwsgi.h"
/*
Storage subsystem: filesystem-like abstraction
struct uwsgi_storage_engine {
char *name;
uint16_t name_len;
int64_t (*get)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
int64_t (*set)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
};
struct uwsgi_storage {
char *name;
uint16_t name_len;
struct uwsgi_storage_engine *engine;
};
*/
struct uwsgi_storage* uwsgi_storage_by_name(char *name, uint16_t name_len) {
if (!name_len) {
name_len = strlen(name);
}
struct uwsgi_storage *s = uwsgi.virtualdisks;
while(s) {
if (!uwsgi_strncmp(s->name, s->name_len, name, name_len)) {
return s;
}
s = s->next;
}
return NULL;
}
int64_t uwsgi_storage_get(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *out_buf, uint64_t pos, uint64_t size, uint64_t flags) {
if (!storage->get) return -1;
return storage->get(key, key_len, out_buf, pos, size, flags);
}
int64_t uwsgi_storage_set(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *in_buf, uint64_t pos, uint64_t size, uint64_t flags) {
if (!storage->set) return -1;
return storage->set(key, key_len, out_buf, pos, size, flags);
}
+340
View File
@@ -0,0 +1,340 @@
#include <uwsgi.h>
// 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;
while (usl) {
if (keylen == usl->len) {
if (!memcmp(key, usl->value, keylen)) {
return usl;
}
}
usl = usl->next;
}
return NULL;
}
// lower a string
char *uwsgi_lower(char *str, size_t size) {
size_t i;
for (i = 0; i < size; i++) {
str[i] = tolower((int) str[i]);
}
return str;
}
// check if a string is contained in another one
char *uwsgi_str_contains(char *str, int slen, char what) {
int i;
for (i = 0; i < slen; i++) {
if (str[i] == what) {
return str + i;
}
}
return NULL;
}
int uwsgi_contains_n(char *s1, size_t s1_len, char *s2, size_t s2_len) {
size_t i;
char *ptr = s2;
for (i = 0; i < s1_len; i++) {
if (s1[i] == *ptr) {
ptr++;
if (ptr == s2 + s2_len) {
return 1;
}
}
else {
ptr = s2;
}
}
return 0;
}
// fast compare 2 sized strings
int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
if (slen != dlen)
return 1;
return memcmp(src, dst, dlen);
}
// fast compare 2 sized strings (case insensitive)
int uwsgi_strnicmp(char *src, int slen, char *dst, int dlen) {
if (slen != dlen)
return 1;
return strncasecmp(src, dst, dlen);
}
// fast sized check of initial part of a string
int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
if (slen < dlen)
return -1;
return memcmp(src, dst, dlen);
}
// unsized check
int uwsgi_startswith(char *src, char *what, int wlen) {
int i;
for (i = 0; i < wlen; i++) {
if (src[i] != what[i])
return -1;
}
return 0;
}
// concatenate strings
char *uwsgi_concatn(int c, ...) {
va_list s;
char *item;
int j = c;
char *buf;
size_t len = 1;
size_t tlen = 1;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
len += va_arg(s, int);
j--;
}
va_end(s);
buf = uwsgi_malloc(len);
memset(buf, 0, len);
j = c;
len = 0;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
tlen = va_arg(s, int);
memcpy(buf + len, item, tlen);
len += tlen;
j--;
}
va_end(s);
return buf;
}
char *uwsgi_concat2(char *one, char *two) {
char *buf;
size_t len = strlen(one) + strlen(two) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
return buf;
}
char *uwsgi_concat4(char *one, char *two, char *three, char *four) {
char *buf;
size_t len = strlen(one) + strlen(two) + strlen(three) + strlen(four) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
memcpy(buf + strlen(one) + strlen(two) + strlen(three), four, strlen(four));
return buf;
}
char *uwsgi_concat3(char *one, char *two, char *three) {
char *buf;
size_t len = strlen(one) + strlen(two) + strlen(three) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
return buf;
}
char *uwsgi_concat2n(char *one, int s1, char *two, int s2) {
char *buf;
size_t len = s1 + s2 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
return buf;
}
char *uwsgi_concat2nn(char *one, int s1, char *two, int s2, int *len) {
char *buf;
*len = s1 + s2 + 1;
buf = uwsgi_malloc(*len);
buf[*len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
return buf;
}
char *uwsgi_concat3n(char *one, int s1, char *two, int s2, char *three, int s3) {
char *buf;
size_t len = s1 + s2 + s3 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
memcpy(buf + s1 + s2, three, s3);
return buf;
}
char *uwsgi_concat4n(char *one, int s1, char *two, int s2, char *three, int s3, char *four, int s4) {
char *buf;
size_t len = s1 + s2 + s3 + s4 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
memcpy(buf + s1 + s2, three, s3);
memcpy(buf + s1 + s2 + s3, four, s4);
return buf;
}
// concat unsized strings
char *uwsgi_concat(int c, ...) {
va_list s;
char *item;
size_t len = 1;
int j = c;
char *buf;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
len += (int) strlen(item);
j--;
}
va_end(s);
buf = uwsgi_malloc(len);
memset(buf, 0, len);
j = c;
len = 0;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
memcpy(buf + len, item, strlen(item));
len += strlen(item);
j--;
}
va_end(s);
return buf;
}
char *uwsgi_strncopy(char *s, int len) {
char *buf;
buf = uwsgi_malloc(len + 1);
buf[len] = 0;
memcpy(buf, s, len);
return buf;
}
// this move a string back of one char and put a 0 at the end (used in uwsgi parsers for buffer reusing)
char *uwsgi_cheap_string(char *buf, int len) {
int i;
char *cheap_buf = buf - 1;
for (i = 0; i < len; i++) {
*cheap_buf++ = buf[i];
}
buf[len - 1] = 0;
return buf - 1;
}
+535 -422
View File
File diff suppressed because it is too large Load Diff
+56
View File
@@ -0,0 +1,56 @@
#include <uwsgi.h>
/*
uWSGI timebomb
this is a simple thread waiting for a timeout and calling exit
with the specified value.
You can use it as a last resort in async apps that could block
normal uWSGI behaviours
*/
struct time_bomb {
int timeout;
int exit_code;
};
static void *time_bomb(void *arg) {
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
struct time_bomb *tb = (struct time_bomb *) arg;
struct timeval tv;
tv.tv_sec = tb->timeout;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
uwsgi_log_verbose("*** BOOOOOOM ***\n");
exit(tb->exit_code);
}
void uwsgi_time_bomb(int timeout, int exit_code) {
pthread_t time_bomb_thread;
struct time_bomb *tb = uwsgi_malloc(sizeof(struct time_bomb));
tb->timeout = timeout;
tb->exit_code = exit_code;
if (pthread_create(&time_bomb_thread, NULL, time_bomb, (void *) tb)) {
uwsgi_error("pthread_create()");
uwsgi_log("unable to setup the time bomb, goodbye\n");
exit(exit_code);
}
else {
uwsgi_log_verbose("Fire in the hole !!! (%d seconds to detonation)\n", timeout);
}
}
+999 -1904
View File
File diff suppressed because it is too large Load Diff
+664 -471
View File
File diff suppressed because it is too large Load Diff
+359
View File
@@ -0,0 +1,359 @@
#include "uwsgi.h"
/*
uWSGI websockets functions
sponsored by 20Tab S.r.l. <info@20tab.com>
*/
extern struct uwsgi_server uwsgi;
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
if (len < 126) {
if (uwsgi_buffer_u8(ub, len)) goto error;
}
else if (len <= (uint16_t) 0xffff) {
if (uwsgi_buffer_u8(ub, 126)) goto error;
if (uwsgi_buffer_u16be(ub, len)) goto error;
}
else {
if (uwsgi_buffer_u8(ub, 127)) goto error;
if (uwsgi_buffer_u64be(ub, len)) goto error;
}
if (uwsgi_buffer_append(ub, msg, len)) goto error;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static int uwsgi_websockets_ping(struct wsgi_request *wsgi_req) {
if (uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_ping->buf, uwsgi.websockets_ping->pos)) {
return -1;
}
wsgi_req->websocket_last_ping = uwsgi_now();
return 0;
}
static int uwsgi_websockets_pong(struct wsgi_request *wsgi_req) {
return uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_pong->buf, uwsgi.websockets_pong->pos);
}
static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
time_t now = uwsgi_now();
// first round
if (wsgi_req->websocket_last_ping == 0) {
return uwsgi_websockets_ping(wsgi_req);
}
// pong not received ?
if (wsgi_req->websocket_last_pong < wsgi_req->websocket_last_ping) {
if (wsgi_req->websocket_last_ping - wsgi_req->websocket_last_pong > uwsgi.websockets_pong_tolerance) {
uwsgi_log("[uwsgi-websocket] no PONG received in %d seconds !!!\n", uwsgi.websockets_pong_tolerance);
return -1;
}
return 0;
}
// pong received, send anther ping
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
return uwsgi_websockets_ping(wsgi_req);
}
return 0;
}
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
if (!ub) return -1;
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return ret;
}
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
wsgi_req->websocket_opcode = byte1 & 0xf;
wsgi_req->websocket_has_mask = byte2 >> 7;
wsgi_req->websocket_size = byte2 & 0x7f;
}
static struct uwsgi_buffer *uwsgi_websockets_parse(struct wsgi_request *wsgi_req) {
// de-mask buffer
uint8_t *ptr = (uint8_t *) (wsgi_req->websocket_buf->buf + (wsgi_req->websocket_pktsize - wsgi_req->websocket_size));
size_t i;
if (wsgi_req->websocket_has_mask) {
uint8_t *mask = ptr-4;
for(i=0;i<wsgi_req->websocket_size;i++) {
ptr[i] = ptr[i] ^ mask[i%4];
}
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->websocket_size);
if (uwsgi_buffer_append(ub, (char *) ptr, wsgi_req->websocket_size)) goto error;
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) goto error;
wsgi_req->websocket_phase = 0;
wsgi_req->websocket_need = 2;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static ssize_t uwsgi_websockets_recv_pkt(struct wsgi_request *wsgi_req, int nb) {
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) {
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
return -1;
}
return 0;
}
goto wait;
}
uwsgi_error("uwsgi_websockets_recv_pkt()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.websockets_ping_freq);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_websockets_recv_pkt()");
return -1;
}
// send unsolicited pong
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
return -1;
}
}
return -1;
}
static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_req, int nb) {
if (!wsgi_req->websocket_buf) {
// this buffer will be destroyed on connection close
wsgi_req->websocket_buf = uwsgi_buffer_new(uwsgi.page_size);
// need 2 byte header
wsgi_req->websocket_need = 2;
}
for(;;) {
size_t remains = wsgi_req->websocket_buf->pos;
// i have data;
if (remains >= wsgi_req->websocket_need) {
switch(wsgi_req->websocket_phase) {
// header
case 0:
uwsgi_websocket_parse_header(wsgi_req);
wsgi_req->websocket_pktsize = 2 + (wsgi_req->websocket_has_mask*4);
if (wsgi_req->websocket_size == 126) {
wsgi_req->websocket_need += 2;
wsgi_req->websocket_phase = 1;
wsgi_req->websocket_pktsize += 2;
}
else if (wsgi_req->websocket_size == 127) {
wsgi_req->websocket_need += 8;
wsgi_req->websocket_phase = 1;
wsgi_req->websocket_pktsize += 8;
}
else {
wsgi_req->websocket_phase = 2;
}
break;
// size
case 1:
if (wsgi_req->websocket_size == 126) {
wsgi_req->websocket_size = uwsgi_be16(wsgi_req->websocket_buf->buf+2);
}
else if (wsgi_req->websocket_size == 127) {
wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2);
}
else {
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
return NULL;
}
if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) {
uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024);
return NULL;
}
wsgi_req->websocket_phase = 2;
break;
// mask check
case 2:
if (wsgi_req->websocket_has_mask) {
wsgi_req->websocket_need += 4;
wsgi_req->websocket_phase = 3;
}
else {
wsgi_req->websocket_need += wsgi_req->websocket_size;
wsgi_req->websocket_phase = 4;
}
break;
// mask
case 3:
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
wsgi_req->websocket_need += wsgi_req->websocket_size;
wsgi_req->websocket_phase = 4;
break;
// message
case 4:
switch (wsgi_req->websocket_opcode) {
// message
case 0:
case 1:
case 2:
return uwsgi_websockets_parse(wsgi_req);
// close
case 0x8:
return NULL;
// ping
case 0x9:
if (uwsgi_websockets_pong(wsgi_req)) {
return NULL;
}
break;
// pong
case 0xA:
wsgi_req->websocket_last_pong = uwsgi_now();
break;
default:
break;
}
// reset the status
wsgi_req->websocket_phase = 0;
wsgi_req->websocket_need = 2;
// decapitate the buffer
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) return NULL;
break;
// oops
default:
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
return NULL;
}
}
// need more data
else {
if (uwsgi_buffer_ensure(wsgi_req->websocket_buf, uwsgi.page_size)) return NULL;
ssize_t len = uwsgi_websockets_recv_pkt(wsgi_req, nb);
if (len <= 0) {
if (nb == 1 && len == 0) {
// return an empty buffer to signal blocking event
return uwsgi_buffer_new(0);
}
return NULL;
}
// update buffer size
wsgi_req->websocket_buf->pos+=len;
}
}
return NULL;
}
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *wsgi_req) {
if (wsgi_req->websocket_closed) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 0);
if (!ub) {
wsgi_req->websocket_closed = 1;
}
return ub;
}
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *wsgi_req) {
if (wsgi_req->websocket_closed) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 1);
if (!ub) {
wsgi_req->websocket_closed = 1;
}
return ub;
}
ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, ub->buf, ub->pos);
if (wsgi_req->write_errors > 0) {
return -1;
}
return len;
}
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
#ifdef UWSGI_SSL
char sha1[20];
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
if (origin_len > 0) {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
}
else {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
}
// generate websockets sha1 and encode it to base64
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
size_t b64_len = 0;
char *b64 = uwsgi_base64_encode(sha1, 20, &b64_len);
if (!b64) return -1;
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Accept", 20, b64, b64_len)) {
free(b64);
return -1;
}
free(b64);
wsgi_req->websocket_last_pong = uwsgi_now();
return uwsgi_response_write_headers_do(wsgi_req);
#else
uwsgi_log("you need to build uWSGI with SSL support to use the websocket handshake api function !!!\n");
return -1;
#endif
}
void uwsgi_websockets_init() {
uwsgi.websockets_pong = uwsgi_buffer_new(2);
uwsgi_buffer_append(uwsgi.websockets_pong, "\x8A\0", 2);
uwsgi.websockets_ping = uwsgi_buffer_new(2);
uwsgi_buffer_append(uwsgi.websockets_ping, "\x89\0", 2);
uwsgi.websockets_ping_freq = 30;
uwsgi.websockets_pong_tolerance = 3;
uwsgi.websockets_max_size = 1024;
}
+299
View File
@@ -0,0 +1,299 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
}
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || status_len < 3 || wsgi_req->write_errors) return -1;
if (!wsgi_req->headers) {
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->headers->limit = UMAX16;
}
// reset the buffer (could be useful for rollbacks...)
wsgi_req->headers->pos = 0;
struct uwsgi_buffer *hh = NULL;
if (status_len <= 4) {
char *new_sc = NULL;
size_t new_sc_len = 0;
uint16_t sc_len = 0;
const char *sc = uwsgi_http_status_msg(status, &sc_len);
if (sc) {
new_sc = uwsgi_concat3n(status, 3, " ", 1, (char *)sc, sc_len);
new_sc_len = 4+sc_len;
}
else {
new_sc = uwsgi_concat2n(status, 3, " Unknown", 8);
new_sc_len = 11;
}
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, new_sc, new_sc_len);
free(new_sc);
}
else {
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, status, status_len);
}
if (!hh) {wsgi_req->write_errors++; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
uwsgi_buffer_destroy(hh);
wsgi_req->status = uwsgi_str3_num(status);
return 0;
error:
uwsgi_buffer_destroy(hh);
wsgi_req->write_errors++;
return -1;
}
//each protocol has its header generator
int uwsgi_response_add_header(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
struct uwsgi_string_list *rh = uwsgi.remove_headers;
while(rh) {
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
return 0;
}
rh = rh->next;
}
rh = wsgi_req->remove_headers;
while(rh) {
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
return 0;
}
rh = rh->next;
}
if (!wsgi_req->headers) {
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->headers->limit = UMAX16;
}
struct uwsgi_buffer *hh = wsgi_req->socket->proto_add_header(wsgi_req, key, key_len, value, value_len);
if (!hh) { wsgi_req->write_errors++ ; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
wsgi_req->header_cnt++;
uwsgi_buffer_destroy(hh);
return 0;
error:
uwsgi_buffer_destroy(hh);
wsgi_req->write_errors++;
return -1;
}
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
return UWSGI_OK;
}
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
ah = ah->next;
}
ah = wsgi_req->additional_headers;
while(ah) {
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
ah = ah->next;
}
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
for(;;) {
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_headers_do()");
}
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_response_write_headers_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->headers_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
wsgi_req->headers_sent = 1;
return UWSGI_OK;
}
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
return -1;
}
sendbody:
if (len == 0) return UWSGI_OK;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_body_do()");
}
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_response_write_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
int can_close = 1;
if (fd == wsgi_req->sendfile_fd) can_close = 0;
if (wsgi_req->write_errors) return -1;
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendfile;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
len = st.st_size;
}
if (wsgi_req->socket->can_offload) {
// of we cannot close the socket (before the app will close it later)
// let's dup it
if (!can_close) {
int tmp_fd = dup(fd);
if (tmp_fd < 0) {
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
wsgi_req->write_errors++;
return -1;
}
fd = tmp_fd;
can_close = 1;
}
if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, len)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += len;
return 0;
}
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
wsgi_req->via = UWSGI_VIA_SENDFILE;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_sendfile_do()");
}
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
// close the file descriptor
if (can_close) close(fd);
return UWSGI_OK;
}
int uwsgi_simple_wait_write_hook(int fd, int timeout) {
struct pollfd upoll;
timeout = timeout * 1000;
upoll.fd = fd;
upoll.events = POLLOUT;
upoll.revents = 0;
int ret = poll(&upoll, 1, timeout);
if (ret > 0) {
if (upoll.revents & POLLOUT) {
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_write_hook()/poll()");
}
return ret;
}
+116 -108
View File
@@ -20,7 +20,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
char *xml_id;
char *xml_content;
int xml_size = 0;
size_t xml_size = 0;
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
@@ -36,22 +36,22 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
uwsgi_log("[uWSGI] using xml uwsgi id: %s\n", colon);
}
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
doc = xmlReadMemory(xml_content, xml_size, filename, NULL, 0);
if (doc == NULL) {
uwsgi_log( "[uWSGI] could not parse file %s.\n", filename);
uwsgi_log("[uWSGI] could not parse file %s.\n", filename);
exit(1);
}
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
uwsgi_log_initial("[uWSGI] parsing config file %s\n", filename);
element = xmlDocGetRootElement(doc);
if (element == NULL) {
uwsgi_log( "[uWSGI] invalid xml config file.\n");
uwsgi_log("[uWSGI] invalid xml config file.\n");
exit(1);
}
if (strcmp((char *) element->name, "uwsgi")) {
@@ -62,7 +62,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if ( strcmp(colon, xml_id) ) {
if (strcmp(colon, xml_id)) {
continue;
}
}
@@ -73,82 +73,82 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
if (!element) {
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
uwsgi_log("[uWSGI] invalid xml root element, <uwsgi> expected.\n");
exit(1);
}
}
// first check for options
for (node = element->children; node; node = node->next) {
// first check for options
for (node = element->children; node; node = node->next) {
node_mode = xmlGetProp(node, (const xmlChar *) "mode");
if (uwsgi.mode && node_mode) {
if (strcmp(uwsgi.mode, (char *) node_mode)) {
continue;
}
}
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if (strcmp(colon, xml_id)) {
continue;
}
}
if (node->type == XML_CDATA_SECTION_NODE) {
if (node->content) {
add_exported_option((char *) "eval", strdup((char *) node->content), 0);
}
}
else if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, (char *) "app")) {
char *mountpoint = (char *) xmlGetProp(node, (const xmlChar *) "mountpoint");
char *domain = (char *) xmlGetProp(node, (const xmlChar *) "domain");
if (!node->children) {
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->content && !node->children->next) {
char *opt_value = strdup((char *) node->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint,"=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain,"|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->next && node->children->next->children && node->children->next->children->content) {
char *opt_value = strdup((char *) node->children->next->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint,"=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain,"|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
}
else {
if (node->children) {
add_exported_option(strdup((char *) node->name), strdup((char *) node->children->content), 0);
}
else {
add_exported_option(strdup((char *) node->name), strdup("1"), 0);
}
}
}
node_mode = xmlGetProp(node, (const xmlChar *) "mode");
if (uwsgi.mode && node_mode) {
if (strcmp(uwsgi.mode, (char *) node_mode)) {
continue;
}
}
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
if (colon && xml_id) {
if (strcmp(colon, xml_id)) {
continue;
}
}
if (node->type == XML_CDATA_SECTION_NODE) {
if (node->content) {
add_exported_option((char *) "eval", strdup((char *) node->content), 0);
}
}
else if (node->type == XML_ELEMENT_NODE) {
if (!strcmp((char *) node->name, (char *) "app")) {
char *mountpoint = (char *) xmlGetProp(node, (const xmlChar *) "mountpoint");
char *domain = (char *) xmlGetProp(node, (const xmlChar *) "domain");
if (!node->children) {
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->content && !node->children->next) {
char *opt_value = strdup((char *) node->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint, "=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain, "|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
else if (node->children && node->children->next && node->children->next->children && node->children->next->children->content) {
char *opt_value = strdup((char *) node->children->next->children->content);
if (mountpoint) {
opt_value = uwsgi_concat3(mountpoint, "=", opt_value);
}
else if (domain) {
opt_value = uwsgi_concat3(domain, "|=", opt_value);
}
add_exported_option("mount", opt_value, 0);
add_exported_option("app", strdup(""), 0);
}
}
else {
if (node->children) {
add_exported_option(strdup((char *) node->name), strdup((char *) node->children->content), 0);
}
else {
add_exported_option(strdup((char *) node->name), strdup("1"), 0);
}
}
}
}
/* We can safely free resources */
xmlFreeDoc(doc);
@@ -166,17 +166,22 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
int uwsgi_xml_found_stanza = 0;
char *uwsgi_xml_found_opt_key = NULL;
static void startElement(void *xml_id, const XML_Char *name, const XML_Char **attrs) {
static void startElement(void *xml_id, const XML_Char * name, const XML_Char ** attrs) {
if (!uwsgi_xml_found_stanza) {
if (xml_id) {
if (!attrs[0]) return;
if (!attrs[1]) return;
if (strcmp("id", attrs[0])) return;
if (strcmp((char *)xml_id, attrs[1])) return;
if (!attrs[0])
return;
if (!attrs[1])
return;
if (strcmp("id", attrs[0]))
return;
if (strcmp((char *) xml_id, attrs[1]))
return;
}
if (!strcmp("uwsgi", name)) uwsgi_xml_found_stanza = 1;
if (!strcmp("uwsgi", name))
uwsgi_xml_found_stanza = 1;
}
else {
uwsgi_xml_found_opt_key = (char *) name;
@@ -186,23 +191,26 @@ static void startElement(void *xml_id, const XML_Char *name, const XML_Char **at
static void textElement(void *xml_id, const char *s, int len) {
if (!uwsgi_xml_found_stanza) return ;
if (!uwsgi_xml_found_stanza)
return;
if (uwsgi_xml_found_opt_key) {
add_exported_option(strdup(uwsgi_xml_found_opt_key), uwsgi_concat2n((char *)s, len, (char *)"", 0), 0);
add_exported_option(strdup(uwsgi_xml_found_opt_key), uwsgi_concat2n((char *) s, len, (char *) "", 0), 0);
uwsgi_xml_found_opt_key = NULL;
}
}
static void endElement(void *xml_id, const XML_Char *name) {
static void endElement(void *xml_id, const XML_Char * name) {
if (!uwsgi_xml_found_stanza) return ;
if (!uwsgi_xml_found_stanza)
return;
if (!strcmp(name, "uwsgi")) {
uwsgi_xml_found_stanza = 0;
return;
}
if (!uwsgi_xml_found_opt_key) return;
if (!uwsgi_xml_found_opt_key)
return;
add_exported_option(strdup(uwsgi_xml_found_opt_key), strdup("1"), 0);
uwsgi_xml_found_opt_key = NULL;
@@ -212,30 +220,30 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
char *colon;
char *xml_content;
int xml_size = 0;
char *xml_content;
size_t xml_size = 0;
int done = 0;
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(filename, ':');
}
if (colon) {
colon[0] = 0;
colon++;
if (*colon == 0) {
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
}
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(filename, ':');
}
if (colon) {
colon[0] = 0;
colon++;
if (*colon == 0) {
uwsgi_log("invalid xml id\n");
exit(1);
}
uwsgi_log("[uWSGI] using xml uwsgi id: %s\n", colon);
}
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
xml_content = uwsgi_open_and_read(filename, &xml_size, 0, magic_table);
uwsgi_log( "[uWSGI] parsing config file %s\n", filename);
uwsgi_log("[uWSGI] parsing config file %s\n", filename);
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetUserData(parser, NULL);
@@ -257,9 +265,9 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
}
} while(!done);
} while (!done);
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
}
+102 -96
View File
@@ -15,7 +15,7 @@ void yaml_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
for (i = strlen(line) - 1; i >= 0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
@@ -26,18 +26,18 @@ void yaml_rstrip(char *line) {
char *yaml_lstrip(char *line) {
off_t i;
char *ptr = line;
off_t i;
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
break;
}
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
break;
}
return ptr;
return ptr;
}
@@ -46,13 +46,13 @@ int yaml_get_depth(char *line) {
off_t i;
int depth = 0;
for(i=0;i< (int) strlen(line);i++) {
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ') {
depth++;
continue;
}
else if (line[i] == '\t' || line[i] == '\r') {
depth+=8;
depth += 8;
continue;
}
break;
@@ -61,17 +61,17 @@ int yaml_get_depth(char *line) {
return depth;
}
char *yaml_get_line(char *yaml, off_t size) {
char *yaml_get_line(char *yaml, size_t size) {
off_t i;
size_t i;
char *ptr = yaml;
int comment = 0;
for(i=0;i<size;i++) {
for (i = 0; i < size; i++) {
ptr++;
if (yaml[i] == '#') {
yaml[i] = 0;
comment = 1;
comment = 1;
}
else if (yaml[i] == '\n') {
yaml[i] = 0;
@@ -96,7 +96,7 @@ char *yaml_get_line(char *yaml, off_t size) {
void uwsgi_yaml_config(char *file, char *magic_table[]) {
int len = 0;
size_t len = 0;
char *yaml;
int in_uwsgi_section = 0;
@@ -108,101 +108,101 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon+1;
section_asked = colon + 1;
}
}
uwsgi_log("[uWSGI] getting YAML configuration from %s\n", file);
uwsgi_log_initial("[uWSGI] getting YAML configuration from %s\n", file);
yaml = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef UWSGI_LIBYAML
yaml_parser_t parser;
yaml_token_t token;
yaml_token_t token;
int status = 0;
int parsing = 1;
if(!yaml_parser_initialize(&parser)) {
if (!yaml_parser_initialize(&parser)) {
uwsgi_log("unable to initialize YAML parser (libyaml)\n");
exit(1);
}
yaml_parser_set_input_string(&parser, (const unsigned char *)yaml, (size_t) len-1);
yaml_parser_set_input_string(&parser, (unsigned char *) yaml, (size_t) len - 1);
while(parsing) {
while (parsing) {
if (!yaml_parser_scan(&parser, &token)) {
uwsgi_log("error parsing YAML file: %s (%c)\n", parser.problem, yaml[parser.problem_offset]);
exit(1);
}
switch(token.type) {
case YAML_STREAM_END_TOKEN:
switch (token.type) {
case YAML_STREAM_END_TOKEN:
parsing = 0;
break;
case YAML_KEY_TOKEN:
status = 1;
break;
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
if (!strcmp(section_asked, key)) {
in_uwsgi_section = 1;
}
}
}
break;
case YAML_BLOCK_END_TOKEN:
if (in_uwsgi_section) {
parsing = 0;
break;
case YAML_KEY_TOKEN:
status = 1;
break;
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
if (!strcmp(section_asked, key)) {
in_uwsgi_section = 1;
}
}
}
break;
case YAML_BLOCK_END_TOKEN:
if (in_uwsgi_section) {
parsing = 0;
break;
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
else if (status == 2) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
else if (status == 2) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;
break;
}
break;
default:
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;
break;
}
break;
default:
status = 0;
}
}
#else
int depth;
int current_depth = 0;
@@ -211,7 +211,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
char *section = "";
while(len) {
while (len) {
yaml_line = yaml_get_line(yaml, len);
if (yaml_line == NULL) {
break;
@@ -219,12 +219,14 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
lines++;
// skip empty line
if (yaml[0] == 0) goto next;
if (yaml[0] == 0)
goto next;
depth = yaml_get_depth(yaml);
if (depth <= current_depth) {
current_depth = depth;
// end the parsing cycle
if (in_uwsgi_section) return;
if (in_uwsgi_section)
return;
}
else if (depth > current_depth && !in_uwsgi_section) {
goto next;
@@ -232,40 +234,44 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
key = yaml_lstrip(yaml);
// skip empty line
if (key[0] == 0) goto next;
if (key[0] == 0)
goto next;
// skip list and {} defined dict
if (key[0] == '-' || key[0] == '[' || key[0] == '{') {
if (in_uwsgi_section) return;
if (in_uwsgi_section)
return;
goto next;
}
if (!in_uwsgi_section) {
section = strchr(key,':');
if (!section) goto next;
section = strchr(key, ':');
if (!section)
goto next;
section[0] = 0;
if (!strcmp(key, section_asked)) {
in_uwsgi_section = 1;
}
}
else {
// get dict value
// get dict value
val = strstr(key, ": ");
if (!val) {
val = strstr(key, ":\t");
}
if (!val) return;
if (!val)
return;
// get the right key
val[0] = 0;
// yeah overengeneering....
yaml_rstrip(key);
val = yaml_lstrip(val+2);
val = yaml_lstrip(val + 2);
yaml_rstrip(val);
//uwsgi_log("YAML: %s = %s\n", key, val);
add_exported_option((char *)key, val, 0);
add_exported_option((char *) key, val, 0);
}
next:
len -= (yaml_line - yaml);
+55
View File
@@ -0,0 +1,55 @@
#include <uwsgi.h>
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
z->opaque = Z_NULL;
if (deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY) != Z_OK) {
//if (deflateInit(z, Z_DEFAULT_COMPRESSION)) {
return -1;
}
if (dict && dict_len) {
if (deflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
return -1;
}
}
return 0;
}
char *uwsgi_deflate(z_stream *z, char *buf, size_t len, size_t *dlen) {
// calculate the amount of bytes needed for output (+30 should be enough)
Bytef *dbuf = uwsgi_malloc(len+30);
z->avail_in = len;
z->next_in = (Bytef *) buf;
z->avail_out = len+30;
z->next_out = dbuf;
if (len > 0) {
if (deflate(z, Z_SYNC_FLUSH) != Z_OK) {
free(dbuf);
return NULL;
}
}
else {
if (deflate(z, Z_FINISH) != Z_STREAM_END) {
free(dbuf);
return NULL;
}
deflateEnd(z);
}
*dlen = (z->next_out - dbuf);
return (char *) dbuf;
}
void uwsgi_crc32(uint32_t *ctx, char *buf, size_t len) {
if (!buf) {
*ctx = crc32(*ctx, Z_NULL, 0);
}
else {
*ctx = crc32(*ctx, (const Bytef *) buf, len);
}
}
View File
-90
View File
@@ -1,90 +0,0 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../">{% trans 'Home' %}</a> &rsaquo;
{% trans 'uWSGI' %}
</div>
{% endblock %}
{% block content %}
<div id="content-main">
<h1>uWSGI status</h1>
<b>masterpid:</b> {{masterpid}}<br/>
<b>started_on:</b> {{started_on}}<br/>
<b>buffer size:</b> {{buffer_size}}<br/>
<b>workers:</b> {{numproc}}<br/>
<b>total requests:</b> {{total_requests}}<br/>
<br/>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">workers</caption>
<thead>
<tr>
<th scope="row">id</th>
<th scope="row">pid</th>
<th scope="row">requests</th>
<th scope="row">running time (milliseconds)</th>
<th scope="row">load</th>
<th scope="row">last spawn</th>
<th scope="row">respawn count</th>
<th scope="row">address space (vsz)</th>
<th scope="row">resident memory (rss)</th>
</tr>
</thead>
<tbody>
{% for w in workers %}
<tr>
<td align="center">{{w.id}}</td>
<td align="center">{{w.pid}}</td>
<td align="right">{{w.requests}}</td>
<td align="right">{{w.running_time}}</td>
<td align="right">{{w.load|floatformat:2}} %</td>
<td align="right">{{w.last_spawn_str}}</td>
<td align="right">{{w.respawn_count}}</td>
<td align="right">{{w.vsz|filesizeformat}}</td>
<td align="right">{{w.rss|filesizeformat}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">spooler jobs</caption>
<thead>
<tr>
<th scope="row">job filename</th>
<th scope="row">environment</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr>
<td align="left">{{j.file}}</td>
<td align="left">{{j.env}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
{% csrf_token %}
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
</div>
{% endblock %}
-10
View File
@@ -1,10 +0,0 @@
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from django.conf.urls.defaults import *
urlpatterns = patterns('uwsgi_admin.views',
(r'^$', 'index'),
(r'^reload/$', 'reload')
)
-42
View File
@@ -1,42 +0,0 @@
import uwsgi
import time
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.admin.views.decorators import staff_member_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def index(request):
workers = uwsgi.workers()
total_load = time.time() - uwsgi.started_on
for w in workers:
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
jobs = []
if 'spooler' in uwsgi.opt:
spooler_jobs = uwsgi.spooler_jobs()
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
'jobs': jobs,
}, RequestContext(request, {}))
index = staff_member_required(index)
def reload(request):
if uwsgi.masterpid() > 0:
uwsgi.reload()
request.user.message_set.create(message="uWSGI reloaded")
else:
request.user.message_set.create(message="The uWSGI master process is not active")
return HttpResponseRedirect(reverse(index))
reload = staff_member_required(reload)
-29
View File
@@ -1,29 +0,0 @@
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.conf import settings
try:
import uwsgi
on_uwsgi = True
except:
on_uwsgi = False
class Loader(BaseLoader):
is_usable = on_uwsgi
def symbolize(self, name):
return name.replace('.','_').replace('/','_').replace('-','_')
def load_template_source(self, template_name, template_dirs=None):
filename = 'templates_' + self.symbolize(template_name)
for app in settings.INSTALLED_APPS:
try:
symbol = "%s_%s" % (self.symbolize(app), filename)
return (uwsgi.embedded_data(symbol), "sym://%s" % symbol)
except:
pass
raise TemplateDoesNotExist(template_name)
View File
View File
+77
View File
@@ -0,0 +1,77 @@
# to run the server
# uwsgi --plugin psgi,coroae --http-socket :9090 --http-socket-modifier1 5 --coroae 8 --psgi examples/corostream.pl --master
# to test it
# curl -D /dev/stdout -N --raw http://localhost:9090/
use Coro::AnyEvent;
use AnyEvent::HTTP;
my $signal_handler = sub {
my $signum = shift;
print "i am the signal ".$signum."\n" ;
};
my $signal_timer = sub {
my $signum = shift;
print "2 seconds elapsed\n";
};
uwsgi::register_signal(17, '', $signal_handler);
uwsgi::register_signal(30, '', $signal_timer);
# raise the signal 30 every 2 seconds
uwsgi::add_timer(30, 2);
sub streamer {
$responder = shift;
# generate the headers and start streaming the response
my $writer = $responder->( [200, ['Content-Type' => 'text/plain']]);
$writer->write("Hello, the streaming is starting...\n");
for(my $i=0;$i<5;$i++) {
Coro::AnyEvent::sleep 1;
$writer->write("[".$i."] one seconds elapsed...\n");
}
$writer->write("let me show you the coroae plugin source taken from github\n\n");
# this condvar will allow us to wait for the github response
my $w = AnyEvent->condvar;
my $uwsgi_coroae_src = '';
http_get 'https://raw.github.com/unbit/uwsgi/master/plugins/coroae/coroae.c', sub { $uwsgi_coroae_src = $_[0] ; $w->send;};
$w->recv;
$writer->write($uwsgi_coroae_src);
Coro::AnyEvent::sleep 1;
$writer->write("now let's raise a uwsgi signal...\n");
uwsgi::signal(17);
Coro::AnyEvent::sleep 1;
$writer->write("another one second elapsed, time to finish.\n");
Coro::AnyEvent::sleep 1;
$writer->write("Goodbye\n");
$writer->close;
print "the request ended, but we are still here\n";
Coro::AnyEvent::sleep 1;
print "another second elapsed, time to end (really)\n";
}
# our PSGI app
my $app = sub {
my $env = shift;
return \&streamer;
}
View File
View File

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