Compare commits

..
178 Commits
Author SHA1 Message Date
Unbit f387d27582 prepare for 1.9.15 2013-08-29 10:49:21 +02:00
Unbit 5d8e5d943f improved smartos support 2013-08-29 10:30:01 +00:00
Unbit 4046f76cb2 completed emperor hooks 2013-08-28 15:00:22 +02:00
Unbit 8baeb0af2f prepare for more emperor hooks 2013-08-28 13:25:52 +02:00
Unbit 63e0105a0f added interface waiting infrastructure 2013-08-28 12:43:26 +02:00
Unbit 70daa57caf Merge branch 'master' of github.com:unbit/uwsgi 2013-08-28 11:49:07 +02:00
Unbit db0f7951a9 added --exec-as-vassal and fixed 'fs' unshare 2013-08-28 11:48:51 +02:00
unbit 45a7a3066d Merge pull request #368 from Kapishin/master
Fix two typos in comments
2013-08-27 23:07:20 -07:00
Pavlo Kapyshin c73a6723d7 Fix two typos in comments 2013-08-28 08:57:58 +03:00
Unbit fb55f57531 added --emperor-use-clone 2013-08-27 21:47:00 +02:00
unbit 8cf4d5802a fixed FreeBSD support for pty plugin 2013-08-26 17:42:25 +02:00
Unbit e3c042e567 pty requires -lutil on linux 2013-08-26 15:44:31 +02:00
Unbit 5435f8927c added vassal's hooks 2013-08-26 10:13:08 +02:00
Unbit e1e65c46ac added --refork option 2013-08-26 10:05:41 +02:00
Unbit e1f3665a8e do not set sys,argv in pypy if already available 2013-08-26 05:38:19 +02:00
Unbit ef09a010cf allows pypy plugin to detect already available pypy environment 2013-08-26 05:01:28 +02:00
Unbit 3f5d79c755 added UWSGI_AS_LIB 2013-08-25 19:42:59 +02:00
unbit 3b5468f39f added FreeBSD support to pty plugin 2013-08-25 18:43:44 +02:00
Roberto De Ioris 5598c7cc22 added pty support to OpenBSD 2013-08-25 20:41:28 +02:00
Unbit d6fdb812a2 improved postfork() decorator 2013-08-25 18:35:56 +02:00
Unbit e6d5f6c612 fixed #366 2013-08-23 20:49:39 +02:00
Unbit 8f10daa2bf fixed pty binding 2013-08-23 19:16:38 +02:00
Unbit f027153452 exit on failed --pty-connect 2013-08-23 18:48:07 +02:00
Unbit 0ebda93a50 fixed #365 2013-08-23 18:41:10 +02:00
Unbit dc4e8950d2 sanitize pty options 2013-08-23 17:50:31 +02:00
Unbit 0f5336028f added OSX support for the pty plugin 2013-08-23 16:28:12 +02:00
Unbit e02341bffe include pty.h only on linux 2013-08-23 16:21:40 +02:00
Unbit ac92ff4079 added the pty plugin 2013-08-23 16:19:33 +02:00
Unbit a5da77bc54 added --add-gid 2013-08-23 14:46:06 +02:00
Unbit 0441e88b82 track unix sockets inode to reduce accidental removal on vacuum 2013-08-23 14:28:01 +02:00
Unbit 815f4abec0 fixed #364 2013-08-23 13:59:13 +02:00
Unbit 4f9e2ff3f6 added --perl-exec and --perl-exec-post-fork 2013-08-23 11:50:18 +02:00
Unbit ce8dd001bf ported uwsgi.cache_keys to pypy 2013-08-23 11:06:24 +02:00
Unbit d4e90f5215 added uwsgi.cache_keys function api 2013-08-23 10:43:13 +02:00
unbit da13562890 Merge pull request #362 from KLab/log-ftime
Add `%(ftime)` to logformat.
2013-08-20 00:58:20 -07:00
INADA Naoki d320075ab0 Add %(ftime) to logformat. 2013-08-20 16:45:59 +09:00
Unbit 4061826da4 try to fix python3 static files handling 2013-08-20 07:32:41 +02:00
Unbit 2854321891 improved python3 exceptions management 2013-08-16 07:09:50 +02:00
Unbit c4181cdc55 fixed type in pypy wsgi.input.read 2013-08-14 11:59:42 +02:00
Unbit 327582b695 added --worker-exec2 2013-08-14 10:16:39 +02:00
Unbit f56b9be4c5 allow post_fork hook on general plugins 2013-08-13 19:19:22 +02:00
Unbit 28ccace24f implemented --call hooks 2013-08-12 12:42:32 +02:00
Unbit 13f82176e3 added init_func support for plugins, and --need-plugin variant 2013-08-11 10:22:36 +02:00
Unbit be4d324f6b better symbol detection for pypy 2013-08-11 08:41:02 +02:00
Unbit 36486caabb sizeof on string includes NULL ... 2013-08-11 08:27:20 +02:00
Unbit b3af255727 Merge branch 'master' of github.com:unbit/uwsgi 2013-08-11 07:09:04 +02:00
Unbit a56f726f7d fixed a typo 2013-08-11 07:06:30 +02:00
unbit 24d6470f38 Merge pull request #359 from ryanpetrello/master
Add plugin support for the pecan WSGI framework (http://pecanpy.org).
2013-08-09 23:47:37 -07:00
Ryan Petrello 7e079e4c40 Add my name to the contributors list. 2013-08-10 01:00:12 -04:00
Ryan Petrello 0d9bc03c53 Add plugin support for the pecan WSGI framework (http://pecanpy.org). 2013-08-10 00:44:40 -04:00
Unbit 7598666768 added UWSGI_REMOVE_INCLUDES 2013-08-08 18:27:54 +02:00
Unbit cd6f027705 avoid unix nameclash on cygwin 2013-08-08 11:23:09 +02:00
Roberto De Ioris 0803a7f0b0 added router_expires 2013-08-07 08:14:38 +02:00
Roberto De Ioris 0eb956db4a example mv again 2013-08-06 07:39:20 +02:00
Roberto De Ioris 76c6ae6d16 mv again 2013-08-06 07:38:11 +02:00
Roberto De Ioris 40054e3494 another series of mv 2013-08-06 07:36:16 +02:00
Roberto De Ioris 8927dfd538 moved example files 2013-08-06 07:33:40 +02:00
Roberto De Ioris 68f734fcad announce legion's death on reload 2013-08-06 07:15:35 +02:00
Roberto De Ioris af4c7f74d5 fixed legion death 2013-08-06 07:08:42 +02:00
Roberto De Ioris 4581d1e7ce announce legion death on uwsgi exit 2013-08-06 06:58:04 +02:00
Unbit d465f61506 fix volfile report 2013-07-31 10:14:22 +02:00
Unbit 5cae9b9ba4 fixed glusterfs volfile support 2013-07-31 10:05:49 +02:00
unbit 428a2d9366 Merge pull request #350 from prymitive/matheval_fix
fix matheval check in build profiles
2013-07-30 19:52:39 -07:00
unbit 1c00b54b06 Merge pull request #351 from prymitive/dot_h
handle core/dot_h.c as other build objects
2013-07-30 08:57:39 -07:00
Unbit 6228fb91da preliminary async support for glusterfs 2013-07-30 16:42:56 +02:00
Łukasz Mierzwa 307cf3a0ef add autogenerated core/dot_h.c to .gitignore, so it won't be added by mistake to git, also remove it during make clean 2013-07-30 10:54:33 +02:00
Łukasz Mierzwa f723a804c0 fix matheval check in build profiles, currently matheval is always required while it should be only used if present or if requested by user 2013-07-30 10:27:02 +02:00
Unbit 24ac19e2d6 added last-modified to glusterfs 2013-07-29 17:40:06 +02:00
Unbit 38147d50ff check for matheval 2013-07-29 16:55:28 +02:00
Unbit 9f7db10582 first working glusterfs plugin prototype 2013-07-29 16:50:00 +02:00
Unbit ed35a50e6c rewrite ruby libdir on heroku 2013-07-29 08:49:25 +02:00
Unbit fae08f49cf another heroku workaround 2013-07-29 08:45:33 +02:00
Unbit 35f5b5b2eb improved ruby libdir detection for static builds 2013-07-29 08:25:06 +02:00
Unbit b785c8fccf added a check for ruby --enable-load-relative 2013-07-28 08:50:44 +02:00
Unbit 597c3cd7f1 try removing ruby_sysinit 2013-07-28 06:23:39 +02:00
Unbit bbbe01ef4b change ruby_process_options with ruby_options [5] 2013-07-27 23:49:49 +02:00
Unbit ea1e1cb65f change ruby_process_options with ruby_options [4] 2013-07-27 23:42:05 +02:00
Unbit a1d31ae954 change ruby_process_options with ruby_options [3] 2013-07-27 23:19:15 +02:00
Unbit fa0ed9489a change ruby_process_options with ruby_options [2] 2013-07-27 23:13:37 +02:00
Unbit 7bb7b351e0 change ruby_process_options with ruby_options 2013-07-27 23:01:09 +02:00
Unbit cb45f207a6 another attempt to make heroku happy [6] 2013-07-27 22:46:31 +02:00
Unbit 82ffb60bdd another attempt to make heroku happy [5] 2013-07-27 22:42:16 +02:00
Unbit ec38ce9a26 another attempt to make heroku happy [4] 2013-07-27 22:37:43 +02:00
Unbit 8279926bab another attempt to make heroku happy [3] 2013-07-27 22:18:18 +02:00
Unbit ac17b0910e another attempt to make heroku happy [2] 2013-07-27 22:09:29 +02:00
Unbit aae3e7ff17 another attempt to make heroku happy 2013-07-27 22:04:02 +02:00
Unbit 4cfff98cd1 try to workaround heroku 2013-07-27 22:01:21 +02:00
Unbit 19ee50949c skeleton for glusterfs plugin 2013-07-27 21:48:00 +02:00
Unbit ec27d624c3 fixed http-keepalive memleak 2013-07-26 12:17:23 +02:00
Unbit 0dc8803ff8 added --force-gateway 2013-07-26 12:03:38 +02:00
Unbit e8ea1a55f9 fixed #112 2013-07-25 21:56:29 +02:00
Unbit a0cb71ca78 added --strict mode 2013-07-25 21:24:04 +02:00
Unbit 5c5aef3827 1.9.15 development starts 2013-07-23 11:00:18 +02:00
Unbit 737a7f4d51 attempt to fix spooler's body in python 2013-07-23 08:40:11 +02:00
Unbit c3ee774d56 Merge branch 'master' of github.com:unbit/uwsgi 2013-07-23 06:28:29 +02:00
Unbit 2d5adacc65 preliminary python profiler for python3 2013-07-23 06:28:10 +02:00
unbit b7a8cc0297 Merge pull request #345 from pingswept/patch-1
Convert tabs to spaces to fix indentation error
2013-07-22 12:36:44 -07:00
Brandon Stafford 317b0f79a8 Convert tabs to spaces to fix indentation error
The uwsgi.websocket_handshake call on line 52 was not indented properly, causing the Python interpreter to choke. Converting the few tabs sprinkled through the document to spaces fixes that error.
2013-07-22 15:22:44 -04:00
Unbit 4644578276 file monitor support for OpenBSD,NetBSD,DragonFly 2013-07-21 16:38:48 +02:00
Unbit f1d450c12f updated gemspec 2013-07-21 08:08:48 +02:00
Roberto De Ioris 6624f75ec7 added kqueue support to the fsmon interface 2013-07-21 07:40:47 +02:00
Unbit 8941505ea0 inotify-based fsmon implementation 2013-07-21 07:34:56 +02:00
Unbit 18b177db25 added fsmon skel 2013-07-20 00:07:40 +02:00
Unbit 27421f3642 atexit hook is not needed in the xmldir router 2013-07-19 19:27:22 +02:00
unbit 30f9479e85 Merge pull request #343 from gber/master
Improvements to router_xmldir
2013-07-20 08:40:39 -07:00
Guido Berhoerster a9f7631ab4 Add example configuration and XSL stylesheet 2013-07-20 00:35:11 +02:00
Guido Berhoerster cb8519510f Fix style in router_xmldir 2013-07-20 00:35:11 +02:00
Guido Berhoerster f7881bfb78 Improve router_xmldir output
Root element is now <index> instead of <tree> since the output is not a tree.
Add a path attribute to <index> which contains the content of PATH_INFO.
Only show files and directories and add attributes for their mtime and size.
2013-07-20 00:35:11 +02:00
Guido Berhoerster 4cf4c75d5d Convert filenames from codeset of the current locale to UTF-8 encoding 2013-07-20 00:35:11 +02:00
Guido Berhoerster 91bcbc77b3 Include hidden files in router_xmldir directory listing
Hidden files can be filtered out through a XSL stylesheet if needed.
2013-07-20 00:35:11 +02:00
Guido Berhoerster b1db4d35c3 Return meaningful responses from router_xmldir in case of errors 2013-07-20 00:35:11 +02:00
Guido Berhoerster 060462b849 Fix portability issue in the router_xmldir plugin
Use the portable alphasort(3) insead of the versionsort(3) GNU extension.
2013-07-20 00:35:11 +02:00
Unbit 0e08c0211c Unbit-specific workaround for broken robust mutexes 2013-07-19 13:21:34 +02:00
Unbit e69cc2bcd5 fixed python modifier management 2013-07-18 16:43:37 +02:00
Unbit 996af7d46c fixed hex2num 2013-07-17 20:42:14 +02:00
Unbit e8e66f15da fixed check_hex 2013-07-17 20:41:07 +02:00
Unbit cd09b4a55d more user-friendly error message for undeletable unix sockets 2013-07-17 16:30:25 +02:00
Unbit f4a1d76396 try to fix auto chunking in http router 2013-07-17 16:21:13 +02:00
Unbit ab8cc168e5 fixed #339 2013-07-17 08:38:32 +02:00
Unbit 5e43ef6fae rbthreads improvements 2013-07-17 08:36:49 +02:00
Roberto De Ioris caa3614f78 rbthreads osx fixes 2013-07-17 07:22:58 +02:00
Unbit a81ca89ae9 use ruby2 profile when available 2013-07-17 07:14:45 +02:00
Unbit 5861705cd6 preliminary rbthreads support 2013-07-17 07:08:47 +02:00
Unbit 4e68dacad3 microoptimzation for --reload-on-fd 2013-07-16 10:22:06 +02:00
Unbit 4f8f15a3b6 fixed --safe-fd 2013-07-16 09:12:46 +02:00
Unbit aa6b86fbdf force the emperor to honour --safe-fd 2013-07-16 08:50:51 +02:00
Unbit 7a18ff48ba added --reload-on-fd and --brutal-reload-on-fd 2013-07-16 08:27:56 +02:00
Unbit e354de9f5e fixed sendfile and fastfile headers management 2013-07-15 10:49:28 +02:00
Unbit 10073bc4ae jsp prototype working 2013-07-15 10:06:33 +02:00
Unbit 6fd051b248 more servlet definitions 2013-07-15 07:20:43 +02:00
Unbit 1cf034881e more servlet definitions 2013-07-15 07:20:08 +02:00
Unbit 1393281c74 added prototype servlet plugin 2013-07-14 09:15:12 +02:00
Unbit edf95a4b0a added fastfile routing action 2013-07-13 17:37:26 +02:00
Unbit 8887f83f7f use the right sendfile abstraction 2013-07-13 17:26:43 +02:00
Unbit 7513d80440 added sendfile routing action 2013-07-13 17:21:13 +02:00
Unbit 67289b7cf1 added setdocroot 2013-07-13 11:26:24 +02:00
Unbit a88f478fac support for rb_reserved_fd_p 2013-07-13 05:55:40 +02:00
Roberto De Ioris d385661a93 removed typo on osx 2013-07-12 20:06:48 +02:00
Unbit e8895ba773 better thunder_lock usage on unbit 2013-07-11 09:39:30 +02:00
Unbit 5a23a8d457 better computation of listen queue load 2013-07-11 08:45:46 +02:00
Roberto De Ioris e01a3d8bd2 second attempt of Tiger support 2013-07-10 21:34:28 +02:00
Roberto De Ioris b270bd24d7 first attempt of Tiger support 2013-07-10 21:30:36 +02:00
unbit ab989ebf16 Merge pull request #336 from xrmx/debian-fixes
A couple of patches from debian packaging
2013-07-09 08:34:31 -07:00
Riccardo Magliocchetti 7c31b6657f uwsgiconfig: force no-format-security too
It may happen that a plugin is using -Wformat -Wformat-security so need to remove
both otherwise as seen in emperor_pg plugin:

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

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

From now on you just need to add `@spool[forever](pass_arguments=True)` to your
function.
2013-06-25 23:54:07 +02:00
anaconda bcd97f7247 Adding my name to CONTRIBUTORS, as requested in #327. 2013-06-25 23:38:46 +02:00
unbit 271e7f8f4c Merge pull request #327 from anaconda/fix-spooler-ordered
Fix --spooler-ordered, was actually reverse ordered.
2013-06-25 09:31:23 -07:00
Unbit e78d8594a8 avoid mess on 32bit 2013-06-25 18:28:30 +02:00
Unbit 659360b366 fixed php status line 2013-06-25 18:23:33 +02:00
anaconda 6c1c86ea79 --spooler-ordered was actually reverse ordered. 2013-06-25 16:58:22 +02:00
Unbit 5da36b7199 1.9.14 development cycle starts 2013-06-25 11:52:34 +02:00
Unbit 294452eef7 added support for retry in http router 2013-06-25 07:56:01 +02:00
Unbit 3ac0e28d9c added Natanael Copa to CONTRIBUTORS 2013-06-24 16:59:58 +02:00
Unbit ce22b69a2f completed uclibc support 2013-06-24 14:55:59 +00:00
unbit 8b31a998ed Merge pull request #325 from ncopa/master
Support for Lua 5.2
2013-06-24 07:44:24 -07:00
Natanael Copa dad97bc104 add support for lua5.2
The default is still lua5.1 but 5.2 can be picked at compile time
but setting UWSGICONFIG_LUAPC=lua5.2
2013-06-24 14:35:31 +00:00
Natanael Copa e20e43eee0 add support for pkg-config for lua
Allow select what pkg-config module to use with UWSGICONFIG_LUAPC but
let the old LUAINC/LUALIB and LUALIBPATH override the pkg-config
for backwards compatibility.
2013-06-24 14:35:31 +00:00
Unbit aafd4e757d another uclibc fix 2013-06-24 16:15:17 +02:00
Unbit 575fc26bd7 try to support uclibc correctly 2013-06-24 16:01:43 +02:00
Unbit 5743eb2575 refactored lua build 2013-06-24 15:05:34 +02:00
Unbit 31972ded93 moved opt login in core/config.c 2013-06-23 08:18:33 +02:00
Unbit 28321a0f94 more python api static functions 2013-06-23 07:59:36 +02:00
Unbit 406dfbc770 added setscheme routing action 2013-06-23 07:22:09 +02:00
Unbit c59595cefc updated gemspec 2013-06-22 12:10:40 +02:00
106 changed files with 4892 additions and 989 deletions
+2
View File
@@ -9,3 +9,5 @@
/uwsgibuild.*
/t/ring/target
core/dot_h.c
+3
View File
@@ -22,3 +22,6 @@ Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
Natanael Copa
Roberto Leandrini
Ryan Petrello
+2 -1
View File
@@ -6,6 +6,7 @@ zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
@@ -16,7 +17,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
as_shared_library = false
locking = auto
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack,rbthreads,fiber
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = jvm,servlet
inherit = base
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = v8
inherit = base
+1 -1
View File
@@ -368,7 +368,7 @@ void async_loop() {
uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_main) {
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
+10
View File
@@ -3,6 +3,9 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
#endif
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
if (len) {
@@ -270,6 +273,13 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
if (ub->freed) {
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
}
ub->freed = 1;
#endif
if (ub->buf)
free(ub->buf);
free(ub);
+55
View File
@@ -204,6 +204,7 @@ static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
next:
usl = usl->next;
}
}
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
@@ -498,6 +499,27 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
return NULL;
}
char *uwsgi_cache_get4(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize, uint64_t *hits) {
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
if (index) {
struct uwsgi_cache_item *uci = cache_item(index);
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
return NULL;
*valsize = uci->valsize;
if (hits)
*hits = uci->hits;
uci->hits++;
uc->hits++;
return uc->data + (uci->first_block * uc->blocksize);
}
uc->miss++;
return NULL;
}
int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t index, uint16_t flags) {
@@ -1899,3 +1921,36 @@ void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
}
}
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *uc, uint64_t *pos, struct uwsgi_cache_item **uci) {
// security check
if (*pos >= uc->hashsize) return NULL;
// iterate hashtable
uint64_t orig_pos = *pos;
for(;*pos<uc->hashsize;(*pos)++) {
// get the cache slot
uint64_t slot = uc->hashtable[*pos];
if (*pos == orig_pos && *uci) {
slot = (*uci)->next;
}
if (slot == 0) continue;
*uci = cache_item(slot);
return *uci;
}
(*pos)++;
return NULL;
}
void uwsgi_cache_rlock(struct uwsgi_cache *uc) {
uwsgi_rlock(uc->lock);
}
void uwsgi_cache_rwunlock(struct uwsgi_cache *uc) {
uwsgi_rwunlock(uc->lock);
}
char *uwsgi_cache_item_key(struct uwsgi_cache_item *uci) {
return uci->key;
}
+12 -9
View File
@@ -84,7 +84,7 @@ static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
char *ret;
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
@@ -96,14 +96,18 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
return wsgi_req->chunked_input_buf->buf;
}
if (wsgi_req->chunked_input_decapitate > 0) {
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
wsgi_req->chunked_input_decapitate = 0;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_fix(wsgi_req->chunked_input_buf, uwsgi.page_size)) return NULL;
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
@@ -122,6 +126,7 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
wsgi_req->chunked_input_need++;
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
@@ -139,19 +144,17 @@ char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
return ret;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
return wsgi_req->chunked_input_buf->buf;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
ret = wsgi_req->chunked_input_buf->buf;
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_chunk_len+2)) return NULL;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
wsgi_req->chunked_input_parser_status = 0;
return ret;
return wsgi_req->chunked_input_buf->buf;
}
}
+447
View File
@@ -31,3 +31,450 @@ struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(
return uc;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
uopt++;
}
return count;
}
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
op++;
}
return NULL;
}
void add_exported_option(char *key, char *value, int configured) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
else if (uwsgi.strict) {
uwsgi_log("[strict-mode] unknown config directive: %s\n", key);
exit(1);
}
}
void uwsgi_fallback_config() {
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
char *argv[3];
argv[0] = uwsgi.binary_path;
argv[1] = uwsgi.fallback_config;
argv[2] = NULL;
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
}
}
+189 -35
View File
@@ -234,11 +234,18 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(de->d_name))
continue;
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(de->d_name, &st))
continue;
if (!S_ISLNK(st.st_mode) && !S_ISREG(st.st_mode))
continue;
}
else {
if (stat(de->d_name, &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(de->d_name);
@@ -294,16 +301,30 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -328,11 +349,18 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
continue;
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
if (uwsgi.emperor_nofollow) {
if (lstat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
continue;
}
else {
if (stat(g.gl_pathv[i], &st))
continue;
if (!S_ISREG(st.st_mode))
continue;
}
ui_current = emperor_get(g.gl_pathv[i]);
@@ -389,16 +417,30 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(filename, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (uwsgi.emperor_nofollow) {
if (lstat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
}
}
c_ui = c_ui->ui_next;
@@ -748,15 +790,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *);
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
@@ -780,9 +817,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// TODO pre-start hook
// a new uWSGI instance will start
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
if (uwsgi.emperor_clone) {
char stack[PTHREAD_STACK_MIN];
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
}
else {
#endif
pid = fork();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
}
#endif
if (pid < 0) {
uwsgi_error("fork()")
uwsgi_error("uwsgi_emperor_spawn_vassal()/fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
@@ -812,9 +859,72 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// once the config is sent we can run hooks (they can fail)
// exec hooks have access to all of the currently defined vars + UWSGI_VASSAL_PID, UWSGI_VASSAL_UID, UWSGI_VASSAL_GID, UWSGI_VASSAL_CONFIG
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
uwsgi_log("running \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
char *argv[4];
argv[0] = uwsgi_concat2("UWSGI_VASSAL_CONFIG=", n_ui->name);
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", n_ui->pid); argv[1] = argv_pid;
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", n_ui->uid); argv[2] = argv_uid;
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", n_ui->gid); argv[3] = argv_gid;
int ret = uwsgi_run_command_putenv_and_wait(NULL, usl->value, argv, 4);
uwsgi_log("command \"%s\" exited with code: %d\n", usl->value, ret);
free(argv[0]);
}
// 4 call hooks
// config / config + pid / config + pid + uid + gid
// call
uwsgi_foreach(usl, uwsgi.call_as_emperor) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func();
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor2) {
void (*func)(char *, pid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor4) {
void (*func)(char *, pid_t, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
}
}
return 0;
}
else {
uwsgi_emperor_spawn_vassal(n_ui);
}
return -1;
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
@@ -837,7 +947,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
char *uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
@@ -863,15 +973,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
free(uef);
}
uenvs = environ;
char **uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
#ifdef UNSETENV_VOID
unsetenv(oe);
#else
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
#endif
free(oe);
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
@@ -896,17 +1010,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
close(n_ui->pipe_config[0]);
}
counter = 4;
int counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while (uct) {
counter += 2;
uct = uct->next;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
if (colon) {
@@ -991,7 +1107,9 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
// close all of the unneded fd
int i;
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
@@ -1001,6 +1119,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// run start hook (can fail)
if (uwsgi.vassals_start_hook) {
uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (uwsgi.emperor_absolute_dir) {
@@ -1012,6 +1131,44 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
// run exec hooks (cannot fail)
uwsgi_foreach(usl, uwsgi.exec_as_vassal) {
uwsgi_log("running \"%s\" (as-vassal)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
}
// run low-level hooks
uwsgi_foreach(usl, uwsgi.call_as_vassal) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func();
}
uwsgi_foreach(usl, uwsgi.call_as_vassal1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name);
}
uwsgi_foreach(usl, uwsgi.call_as_vassal3) {
void (*func)(char *, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name, n_ui->uid, n_ui->gid);
}
// start !!!
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
@@ -1019,9 +1176,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
// never here
exit(UWSGI_EXILE_CODE);
}
return -1;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
+213
View File
@@ -0,0 +1,213 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
#include <sys/inotify.h>
#endif
#endif
void uwsgi_fsmon_setup() {
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
char *copy = uwsgi_str(usl->value);
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
goto next;
}
*space = 0;
usl->value = copy;
usl->len = strlen(copy);
usl->custom_ptr = space+1;
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
next:
usl = usl->next;
}
}
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
static int inotify_fd = -1;
if (inotify_fd == -1) {
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
return -1;
}
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
return -1;
}
}
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
if (wd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
return -1;
}
usl->custom = inotify_fd;
usl->custom2 = wd;
return 0;
#endif
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
struct kevent kev;
int fd = open(usl->value, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(usl->value);
uwsgi_error("uwsgi_register_fsmon()/open()");
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("uwsgi_register_fsmon()/kevent()");
return -1;
}
usl->custom = fd;
usl->custom2 = fd;
return 0;
#endif
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
return 1;
}
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
int found_fd = -1;
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
found:
if (found_fd == -1) return NULL;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
unsigned int isize = 0;
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
return 0;
}
if (isize == 0) return NULL;
struct inotify_event *ie = uwsgi_malloc(isize);
// read from the inotify descriptor
ssize_t len = read(found_fd, ie, isize);
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
found_fd = ie->wd;
free(ie);
#endif
#endif
// search for the item id and print it
usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_brutal_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return usl;
}
usl = usl->next;
}
return NULL;
}
int uwsgi_fsmon_event(int interesting_fd) {
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
if (!usl) return 0;
if (usl == uwsgi.fs_reload) {
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 1;
}
if (usl == uwsgi.fs_brutal_reload) {
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 1;
}
// fallback to signal
uwsgi_route_signal(atoi(usl->custom_ptr));
return 1;
}
+1 -1
View File
@@ -41,7 +41,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process)
if (!uwsgi.master_process && !uwsgi.force_gateway)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
+8
View File
@@ -387,6 +387,8 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
return uwsgi.mypid;
}
@@ -449,6 +451,12 @@ void sanitize_args() {
exit(1);
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
uwsgi.use_thunder_lock = 1;
}
#endif
}
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
+25 -2
View File
@@ -79,6 +79,9 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
ul->scroll = value;
ul->scroll_len = vallen;
}
else if (!uwsgi_strncmp(key, keylen, "dead", 4)) {
ul->dead = 1;
}
}
// this function is called when a node is added or removed (heavy locking is needed)
@@ -611,6 +614,14 @@ static void *legion_loop(void *foobar) {
usl = usl->next;
}
}
// remove node announcing death
else if (legion_msg.dead) {
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s announced its death to Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_wlock(ul->lock);
uwsgi_legion_remove_node(ul, node);
uwsgi_rwunlock(ul->lock);
continue;
}
node->last_seen = uwsgi_now();
node->lord_valor = legion_msg.lord_valor;
@@ -752,8 +763,11 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
goto err;
}
#ifdef UWSGI_UUID
#endif
if (ul->dead) {
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
goto err;
}
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
@@ -1122,6 +1136,14 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
}
}
void uwsgi_legion_announce_death(void) {
struct uwsgi_legion *legion = uwsgi.legions;
while (legion) {
legion->dead = 1;
uwsgi_legion_announce(legion);
legion = legion->next;
}
}
void uwsgi_legion_atexit(void) {
struct uwsgi_legion *legion = uwsgi.legions;
@@ -1140,6 +1162,7 @@ next:
legion = legion->next;
}
uwsgi_legion_announce_death();
}
int uwsgi_legion_i_am_the_lord(char *name) {
+34
View File
@@ -610,6 +610,32 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
#ifdef UNBIT
/*
Unbit-specific workaround for robust-mutexes
*/
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
}
return NULL;
}
void uwsgi_robust_mutexes_watchdog() {
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 32K should be more than enough...
pthread_attr_setstacksize(&attr, 32 * 1024);
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
exit(1);
}
}
#endif
void uwsgi_setup_locking() {
@@ -689,6 +715,14 @@ ready:
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
#ifdef UNBIT
// we have a serious bug on Unbit (and very probably on older libc)
// when all of the workers die in the same moment the pthread robust mutes is left
// in inconsistent state and we have no way to recover
// we span a thread in the master constantly ensuring the lock is ok
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
uwsgi_robust_mutexes_watchdog();
#endif
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
+22 -4
View File
@@ -45,7 +45,7 @@ void uwsgi_log(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -97,7 +97,7 @@ void uwsgi_log_verbose(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -616,7 +616,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
break;
}
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request);
@@ -1035,7 +1035,7 @@ static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_malloc(26);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf);
@@ -1060,6 +1060,19 @@ static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
return ret;
}
static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
if (!uwsgi.log_strftime) {
return uwsgi_lf_ltime(wsgi_req, buf);
}
*buf = uwsgi_malloc(64);
time_t now = wsgi_req->start_of_request / 1000000;
size_t ret = strftime(*buf, 64, uwsgi.log_strftime, localtime(&now));
if (ret == 0) {
*buf[0] = 0;
return 0;
}
return ret;
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
@@ -1246,6 +1259,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ftime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
+13 -1
View File
@@ -375,6 +375,8 @@ int master_loop(char **argv, char **environ) {
uwsgi_start_legions();
#endif
uwsgi_add_reload_fds();
uwsgi_cache_start_sweepers();
uwsgi_cache_start_sync_servers();
@@ -391,7 +393,7 @@ int master_loop(char **argv, char **environ) {
}
if (uwsgi.stats) {
char *tcp_port = strchr(uwsgi.stats, ':');
char *tcp_port = strrchr(uwsgi.stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
@@ -498,6 +500,9 @@ int master_loop(char **argv, char **environ) {
}
uwsgi_check_touches(uwsgi.touch_signal);
// fsmon
uwsgi_fsmon_setup();
// setup cheaper algos (can be stacked)
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
if (uwsgi.requested_cheaper_algo) {
@@ -698,6 +703,7 @@ int master_loop(char **argv, char **environ) {
// get listen_queue status
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
int tmp_queue = 0;
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_INET) {
uwsgi_sock->queue = uwsgi_get_tcp_info(uwsgi_sock->fd);
@@ -709,8 +715,14 @@ int master_loop(char **argv, char **environ) {
}
#endif
#endif
if (uwsgi_sock->queue > tmp_queue) {
tmp_queue = uwsgi_sock->queue;
}
uwsgi_sock = uwsgi_sock->next;
}
// fix queue size on multiple sockets
uwsgi.shared->load = tmp_queue;
// check if some worker has to die (harakiri, evil checks...)
uwsgi_master_check_workers_deadline();
+73
View File
@@ -42,6 +42,79 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
if (uwsgi_fsmon_event(interesting_fd)) {
return 0;
}
// reload on fd
if (uwsgi.reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 0;
}
usl = usl->next;
}
}
// brutal reload on fd
if (uwsgi.brutal_reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[brutal-reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 0;
}
usl = usl->next;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
+27
View File
@@ -1458,3 +1458,30 @@ int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int
}
static void add_reload_fds(struct uwsgi_string_list *list, char *type) {
struct uwsgi_string_list *usl = list;
while(usl) {
char *strc = uwsgi_str(usl->value);
char *space = strchr(strc, ' ');
if (space) {
*space = 0;
usl->custom_ptr = space+1;
}
char *colon = strchr(strc, ':');
if (colon) {
*colon = 0;
usl->custom2 = strtoul(colon+1, NULL, 10);
}
usl->custom = strtoul(strc, NULL, 10);
if (!usl->custom2) usl->custom2 = 1;
event_queue_add_fd_read(uwsgi.master_queue, usl->custom);
uwsgi_add_safe_fd(usl->custom);
uwsgi_log("added %s reload monitor for fd %d (read size: %llu)\n", type, (int) usl->custom, usl->custom2);
usl = usl->next;
}
}
void uwsgi_add_reload_fds() {
add_reload_fds(uwsgi.reload_on_fd, "graceful");
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
}
+1 -1
View File
@@ -345,7 +345,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
}
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t len = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
// transfer finished
+24 -5
View File
@@ -24,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
}
#endif
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -33,7 +33,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.p[i]->alias) {
@@ -41,7 +41,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
@@ -53,7 +53,7 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
if (uwsgi.gp[i]->alias) {
@@ -61,14 +61,21 @@ int plugin_already_loaded(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return 1;
return uwsgi.p[i];
}
}
}
return NULL;
}
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
if (up) return 1;
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
@@ -91,6 +98,12 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
colon[0] = ':';
}
char *init_func = strchr(plugin_name, '|');
if (init_func) {
init_func[0] = 0;
init_func++;
}
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
@@ -150,6 +163,12 @@ success:
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
if (init_func) {
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
if (plugin_init_func) {
plugin_init_func();
}
}
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
+51
View File
@@ -936,6 +936,30 @@ static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
ur->data_len = strlen(arg);
return 0;
}
// setdocroot route
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "DOCUMENT_ROOT", 13, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->document_root = ptr;
wsgi_req->document_root_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setdocroot(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setdocroot_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setpathinfo route
static int uwsgi_router_setpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -961,6 +985,31 @@ static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
return 0;
}
// setscheme route
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub) return UWSGI_ROUTE_BREAK;
char *ptr = uwsgi_req_append(wsgi_req, "UWSGI_SCHEME", 12, ub->buf, ub->pos);
if (!ptr) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
wsgi_req->scheme = ptr;
wsgi_req->scheme_len = ub->pos;
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_setscheme_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setuser route
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -1593,6 +1642,8 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
uwsgi_register_router("alarm", uwsgi_router_alarm);
+2 -1
View File
@@ -10,7 +10,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t sf_len = len;
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
@@ -71,5 +71,6 @@ int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, siz
return -1;
}
}
return 0;
}
+5 -1
View File
@@ -74,7 +74,7 @@ int bind_to_unix_dgram(char *socket_name) {
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
uwsgi_error("unlink()");
uwsgi_error("error removing unix socket, unlink()");
}
uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
@@ -1714,6 +1714,10 @@ void uwsgi_bind_sockets() {
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
}
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
struct stat st;
if (uwsgi_sock->name[0] != '@' && !stat(uwsgi_sock->name, &st)) {
uwsgi_sock->inode = st.st_ino;
}
}
else {
#ifdef AF_INET6
+18 -4
View File
@@ -227,20 +227,33 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
if (write(fd, &uh, 4) != 4) {
uwsgi_log("[spooler] unable to write header for %s\n", filename);
goto clear;
}
if (write(fd, buffer, size) != size) {
uwsgi_log("[spooler] unable to write args for %s\n", filename);
goto clear;
}
if (body && body_len > 0) {
if ((size_t) write(fd, body, body_len) != body_len) {
uwsgi_log("[spooler] unable to write body for %s\n", filename);
goto clear;
}
}
if (at > 0) {
#ifdef __UCLIBC__
struct timespec ts[2];
ts[0].tv_sec = at;
ts[0].tv_nsec = 0;
ts[1].tv_sec = at;
ts[1].tv_nsec = 0;
if (futimens(fd, ts)) {
uwsgi_error("futimens()");
}
#else
struct timeval tv[2];
tv[0].tv_sec = at;
tv[0].tv_usec = 0;
@@ -253,6 +266,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
uwsgi_error("futimes()");
}
#endif
}
// here the file will be unlocked too
@@ -380,7 +394,7 @@ void spooler(struct uwsgi_spooler *uspool) {
static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
struct dirent **tasklist;
int n;
int n, i;
if (!dir)
dir = uspool->dir;
@@ -391,9 +405,9 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
return;
}
while (n--) {
spooler_manage_task(uspool, dir, tasklist[n]->d_name);
free(tasklist[n]);
for (i = 0; i < n; i++) {
spooler_manage_task(uspool, dir, tasklist[i]->d_name);
free(tasklist[i]);
}
free(tasklist);
+41
View File
@@ -1,5 +1,46 @@
#include <uwsgi.h>
char *uwsgi_str_split_nget(char *str, size_t len, char what, size_t pos, size_t *rlen) {
size_t i;
size_t current = 0;
char *choosen = str;
size_t choosen_len = 0;
*rlen = 0;
for(i=0;i<len;i++) {
if (!choosen) choosen = str + i;
if (str[i] == what) {
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
current++;
choosen = NULL;
choosen_len = 0;
}
else {
choosen_len ++;
}
}
if (current == pos) {
if (choosen_len == 0) return NULL;
*rlen = choosen_len;
return choosen;
}
return NULL;
}
size_t uwsgi_str_occurence(char *str, size_t len, char what) {
size_t count = 0;
size_t i;
for(i=0;i<len;i++) {
if (str[i] == what) count++;
}
return count;
}
// check if a string_list contains an item
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
struct uwsgi_string_list *usl = list;
+266 -458
View File
@@ -191,6 +191,8 @@ void daemonize(char *logfile) {
// get current working directory
char *uwsgi_get_cwd() {
if (uwsgi.force_cwd) return uwsgi.force_cwd;
// set this to static to avoid useless reallocations in stats mode
static size_t newsize = 256;
@@ -370,18 +372,49 @@ void uwsgi_as_root() {
#endif
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.wait_for_interface) {
if (!uwsgi.wait_for_interface_timeout) {
uwsgi.wait_for_interface_timeout = 60;
}
uwsgi_log("waiting for interface %s (max %d seconds) ...\n", usl->value, uwsgi.wait_for_interface_timeout);
int counter = 0;
for(;;) {
if (counter > uwsgi.wait_for_interface_timeout) {
uwsgi_log("interface %s unavailable after %d seconds\n", usl->value, counter);
exit(1);
}
unsigned int index = if_nametoindex(usl->value);
if (index > 0) {
uwsgi_log("interface %s found with index %u\n", usl->value, index);
break;
}
else {
sleep(1);
counter++;
}
}
}
// now run the scripts needed by root
struct uwsgi_string_list *usl = uwsgi.exec_as_root;
while (usl) {
uwsgi_foreach(usl, uwsgi.exec_as_root) {
uwsgi_log("running \"%s\" (as root)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_root) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
if (uwsgi.gidname) {
struct group *ugroup = getgrnam(uwsgi.gidname);
if (ugroup) {
@@ -480,6 +513,31 @@ void uwsgi_as_root() {
exit(1);
}
}
struct uwsgi_string_list *usl;
size_t ags = 0;
uwsgi_foreach(usl, uwsgi.additional_gids) ags++;
if (ags > 0) {
gid_t *ags_list = uwsgi_calloc(sizeof(gid_t) * ags);
size_t g_pos = 0;
uwsgi_foreach(usl, uwsgi.additional_gids) {
ags_list[g_pos] = atoi(usl->value);
if (!ags_list[g_pos]) {
struct group *g = getgrnam(usl->value);
if (g) {
ags_list[g_pos] = g->gr_gid;
}
else {
uwsgi_log("unable to find group %s\n", usl->value);
exit(1);
}
}
g_pos++;
}
if (setgroups(ags, ags_list)) {
uwsgi_error("setgroups()");
exit(1);
}
}
int additional_groups = getgroups(0, NULL);
if (additional_groups > 0) {
gid_t *gids = uwsgi_calloc(sizeof(gid_t) * additional_groups);
@@ -536,18 +594,42 @@ void uwsgi_as_root() {
}
#endif
if (uwsgi.refork) {
uwsgi_log("re-fork()ing...\n");
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid > 0) {
// block all signals
sigset_t smask;
sigfillset(&smask);
sigprocmask(SIG_BLOCK, &smask, NULL);
int status;
if (waitpid(pid, &status, 0) < 0) {
uwsgi_error("waitpid()");
}
_exit(0);
}
}
// now run the scripts needed by the user
usl = uwsgi.exec_as_user;
while (usl) {
uwsgi_foreach(usl, uwsgi.exec_as_user) {
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_user) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
// we could now patch the binary
if (uwsgi.unprivileged_binary_patch) {
uwsgi.argv[0] = uwsgi.unprivileged_binary_patch;
@@ -1241,34 +1323,6 @@ int uwsgi_get_app_id(struct wsgi_request *wsgi_req, char *key, uint16_t key_len,
return -1;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
uopt++;
}
return count;
}
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
op++;
}
return NULL;
}
char *uwsgi_substitute(char *src, char *what, char *with) {
int count = 0;
@@ -1347,408 +1401,6 @@ int uwsgi_is_link(char *filename) {
return 0;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
void add_exported_option(char *key, char *value, int configured) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
}
void *uwsgi_malloc(size_t size) {
char *ptr = malloc(size);
@@ -1987,6 +1639,9 @@ static char hex2num(char *str) {
else if (str[0] >= 'A' && str[0] <= 'F') {
val += (str[0] & 0x0F) + 9;
}
else if (str[0] >= 'a' && str[0] <= 'f') {
val += (str[0] & 0x0F) + 9;
}
else {
return 0;
}
@@ -1999,6 +1654,9 @@ static char hex2num(char *str) {
else if (str[1] >= 'A' && str[1] <= 'F') {
val += (str[1] & 0x0F) + 9;
}
else if (str[1] >= 'a' && str[1] <= 'f') {
val += (str[1] & 0x0F) + 9;
}
else {
return 0;
}
@@ -2356,23 +2014,9 @@ void uwsgi_exec_command_with_args(char *cmdline) {
exit(1);
}
int uwsgi_run_command_and_wait(char *command, char *arg) {
static int uwsgi_run_command_do(char *command, char *arg) {
char *argv[4];
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
@@ -2400,6 +2044,54 @@ int uwsgi_run_command_and_wait(char *command, char *arg) {
exit(1);
}
int uwsgi_run_command_and_wait(char *command, char *arg) {
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
return uwsgi_run_command_do(command, arg);
}
int uwsgi_run_command_putenv_and_wait(char *command, char *arg, char **envs, unsigned int nenvs) {
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
unsigned int i;
for(i=0;i<nenvs;i++) {
if (putenv(envs[i])) {
uwsgi_error("uwsgi_run_command_putenv_and_wait()/putenv()");
exit(1);
}
}
return uwsgi_run_command_do(command, arg);
}
pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
char *argv[4];
@@ -2597,11 +2289,13 @@ char *uwsgi_get_binary_path(char *argvzero) {
uint32_t len = uwsgi.page_size;
if (_NSGetExecutablePath(buf, &len) == 0) {
// return only absolute path
#ifndef OLD_REALPATH
char *newbuf = realpath(buf, NULL);
if (newbuf) {
free(buf);
return newbuf;
}
#endif
}
free(buf);
#elif defined(__sun__)
@@ -2741,9 +2435,6 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
#ifdef CLONE_FILES
{"files", CLONE_FILES},
#endif
#ifdef CLONE_FS
{"fs", CLONE_FS},
#endif
#ifdef CLONE_NEWIPC
{"ipc", CLONE_NEWIPC},
#endif
@@ -2755,6 +2446,7 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
#endif
#ifdef CLONE_NEWNS
{"ns", CLONE_NEWNS},
{"fs", CLONE_NEWNS},
{"mount", CLONE_NEWNS},
#endif
#ifdef CLONE_SYSVSEM
@@ -2778,7 +2470,7 @@ static int uwsgi_get_unshare_id(char *name) {
return -1;
}
void uwsgi_build_unshare(char *what) {
void uwsgi_build_unshare(char *what, int *mask) {
char *list = uwsgi_str(what);
@@ -2786,7 +2478,7 @@ void uwsgi_build_unshare(char *what) {
while (p != NULL) {
int u_id = uwsgi_get_unshare_id(p);
if (u_id != -1) {
uwsgi.unshare |= u_id;
*mask |= u_id;
}
p = strtok(NULL, ",");
}
@@ -3263,10 +2955,14 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
}
char *uwsgi_chomp(char *str) {
size_t i;
for (i = 0; i < strlen(str); i++) {
ssize_t slen = (ssize_t) strlen(str), i ;
if (!slen) return str;
slen--;
for (i = slen; i >= 0; i--) {
if (str[i] == '\r' || str[i] == '\n') {
str[i] = 0;
}
else {
return str;
}
}
@@ -3274,6 +2970,24 @@ char *uwsgi_chomp(char *str) {
return str;
}
char *uwsgi_chomp2(char *str) {
ssize_t slen = (ssize_t) strlen(str), i ;
if (!slen) return str;
slen--;
for (i = slen; i >= 0; i--) {
if (str[i] == '\r' || str[i] == '\n' || str[i] == '\t' || str[i] == ' ') {
str[i] = 0;
}
else {
return str;
}
}
return str;
}
int uwsgi_tmpfd() {
char *tmpdir = getenv("TMPDIR");
if (!tmpdir) {
@@ -3704,6 +3418,13 @@ error:
return -1;
}
int uwsgi_call_symbol(char *symbol) {
void (*func)(void) = dlsym(RTLD_DEFAULT, symbol);
if (!func) return -1;
func();
return 0;
}
int uwsgi_plugin_modifier1(char *plugin) {
int ret = -1;
char *symbol_name = uwsgi_concat2(plugin, "_plugin");
@@ -4055,3 +3776,90 @@ void create_msg_pipe(int *fd, int bufsize) {
char *uwsgi_binary_path() {
return uwsgi.binary_path ? uwsgi.binary_path : "uwsgi";
}
void uwsgi_envdir(char *edir) {
DIR *d = opendir(edir);
if (!d) {
uwsgi_error("[uwsgi-envdir] opendir()");
exit(1);
}
struct dirent *de;
while ((de = readdir(d)) != NULL) {
// skip hidden files
if (de->d_name[0] == '.') continue;
struct stat st;
char *filename = uwsgi_concat3(edir, "/", de->d_name);
if (stat(filename, &st)) {
uwsgi_log("[uwsgi-envdir] error stating %s\n", filename);
uwsgi_error("[uwsgi-envdir] stat()");
exit(1);
}
if (!S_ISREG(st.st_mode)) {
free(filename);
continue;
}
// unsetenv
if (st.st_size == 0) {
#ifdef UNSETENV_VOID
unsetenv(de->d_name);
#else
if (unsetenv(de->d_name)) {
uwsgi_log("[uwsgi-envdir] unable to unset %s\n", de->d_name);
uwsgi_error("[uwsgi-envdir] unsetenv");
exit(1);
}
#endif
free(filename);
continue;
}
// read the content of the file
size_t size = 0;
char *content = uwsgi_open_and_read(filename, &size, 1, NULL);
if (!content) {
uwsgi_log("[uwsgi-envdir] unable to open %s\n", filename);
uwsgi_error_open(filename);
exit(1);
}
free(filename);
// HACK, envdir states we only need to strip the end of the string ....
uwsgi_chomp2(content);
// ... and substitute 0 with \n
size_t slen = strlen(content);
size_t i;
for(i=0;i<slen;i++) {
if (content[i] == 0) {
content[i] = '\n';
}
}
if (setenv(de->d_name, content, 1)) {
uwsgi_log("[uwsgi-envdir] unable to set %s\n", de->d_name);
uwsgi_error("[uwsgi-envdir] setenv");
exit(1);
}
free(content);
}
}
void uwsgi_envdirs(struct uwsgi_string_list *envdirs) {
struct uwsgi_string_list *usl = envdirs;
while(usl) {
uwsgi_envdir(usl->value);
usl = usl->next;
}
}
void uwsgi_opt_envdir(char *opt, char *value, void *foobar) {
uwsgi_envdir(value);
}
void uwsgi_exit(int status) {
uwsgi.last_exit_code = status;
// disable macro expansion
(exit)(status);
}
+186 -20
View File
@@ -59,7 +59,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possibie)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI, 0},
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose, 0},
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
@@ -72,6 +72,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
{"fallback-config", required_argument, 0, "re-exec uwsgi with the specified config when exit code is 1", uwsgi_opt_set_str, &uwsgi.fallback_config, UWSGI_OPT_IMMEDIATE},
{"strict", no_argument, 0, "enable strict mode (placeholder cannot be used)", uwsgi_opt_true, &uwsgi.strict, UWSGI_OPT_IMMEDIATE},
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
@@ -171,6 +173,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
@@ -191,6 +194,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
#endif
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
@@ -203,6 +209,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
@@ -221,8 +228,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
{"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"fd-safe", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
{"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0},
{"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0},
@@ -283,6 +290,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
{"add-gid", required_argument, 0, "add the specified group id to the process credentials", uwsgi_opt_add_string_list, &uwsgi.additional_gids, 0},
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
@@ -290,8 +298,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
#endif
#ifdef __linux__
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0},
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
#endif
{"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
{"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
{"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0},
{"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0},
@@ -300,6 +311,42 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
{"exec-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.exec_as_vassal, 0},
{"exec-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.exec_as_emperor, 0},
{"wait-for-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-for-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-for-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-for-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
{"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0},
{"call-as-root", required_argument, 0, "call the specified function before privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_root, 0},
{"call-as-user", required_argument, 0, "call the specified function after privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_user, 0},
{"call-as-user-atexit", required_argument, 0, "call the specified function before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.call_as_user_atexit, 0},
{"call-pre-app", required_argument, 0, "call the specified function before app loading", uwsgi_opt_add_string_list, &uwsgi.call_pre_app, 0},
{"call-post-app", required_argument, 0, "call the specified function after app loading", uwsgi_opt_add_string_list, &uwsgi.call_post_app, 0},
{"call-as-vassal", required_argument, 0, "call the specified function() before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal, 0},
{"call-as-vassal1", required_argument, 0, "call the specified function(char *) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal1, 0},
{"call-as-vassal3", required_argument, 0, "call the specified function(char *, uid_t, gid_t) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal3, 0},
{"call-as-emperor", required_argument, 0, "call the specified function() in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor, 0},
{"call-as-emperor1", required_argument, 0, "call the specified function(char *) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor1, 0},
{"call-as-emperor2", required_argument, 0, "call the specified function(char *, pid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor2, 0},
{"call-as-emperor4", required_argument, 0, "call the specified function(char *, pid_t, uid_t, gid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor4, 0},
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
#ifdef UWSGI_YAML
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
@@ -335,6 +382,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
#ifdef __linux__
#ifdef MADV_MERGEABLE
{"ksm", optional_argument, 0, "enable Linux KSM", uwsgi_opt_set_int, &uwsgi.linux_ksm, 0},
@@ -351,6 +401,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"touch-logreopen", required_argument, 0, "trigger log reopen if the specified file is modified/touched", uwsgi_opt_add_string_list, &uwsgi.touch_logreopen, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"touch-exec", required_argument, 0, "run command when the specified file is modified/touched (syntax: file command)", uwsgi_opt_add_string_list, &uwsgi.touch_exec, UWSGI_OPT_MASTER},
{"touch-signal", required_argument, 0, "signal when the specified file is modified/touched (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.touch_signal, UWSGI_OPT_MASTER},
{"fs-reload", required_argument, 0, "graceful reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_reload, UWSGI_OPT_MASTER},
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
@@ -501,6 +556,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
{"force-cwd", required_argument, 0, "force the initial working directory to the specified value", uwsgi_opt_set_str, &uwsgi.force_cwd, 0},
{"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
{"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
@@ -641,6 +697,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
{"envdir", required_argument, 0, "load a daemontools compatible envdir", uwsgi_opt_add_string_list, &uwsgi.envdirs, 0},
{"early-envdir", required_argument, 0, "load a daemontools compatible envdir ASAP", uwsgi_opt_envdir, NULL, UWSGI_OPT_IMMEDIATE},
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum, 0},
{"file-write", required_argument, 0, "write the specified content to the specified file (syntax: file=value) before privileges drop", uwsgi_opt_add_string_list, &uwsgi.file_write_list, 0},
@@ -677,6 +735,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
@@ -688,6 +747,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"need-plugins", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"need-plugin", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"plugin-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"plugins-list", no_argument, 0, "list enabled plugins", uwsgi_opt_true, &uwsgi.plugins_list, 0},
@@ -1092,6 +1153,10 @@ void grace_them_all(int signum) {
uwsgi_log("...gracefully killing workers...\n");
#ifdef UWSGI_SSL
uwsgi_legion_announce_death();
#endif
if (uwsgi.unsubscribe_on_graceful_reload) {
uwsgi_unsubscribe_all();
}
@@ -1161,6 +1226,10 @@ void reap_them_all(int signum) {
uwsgi_log("...brutally killing workers...\n");
#ifdef UWSGI_SSL
uwsgi_legion_announce_death();
#endif
// unsubscribe if needed
uwsgi_unsubscribe_all();
@@ -1242,7 +1311,7 @@ void what_i_am_doing() {
for (i = 0; i < uwsgi.cores; i++) {
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req;
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
@@ -1259,7 +1328,7 @@ void what_i_am_doing() {
else {
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[0].req;
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
@@ -1298,15 +1367,21 @@ struct uwsgi_plugin unconfigured_plugin = {
void uwsgi_exec_atexit(void) {
if (getpid() == masterpid) {
// now run exit scripts needed by the user
struct uwsgi_string_list *usl = uwsgi.exec_as_user_atexit;
while (usl) {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_as_user_atexit) {
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_user_atexit) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
}
}
@@ -1348,6 +1423,13 @@ static void vacuum(void) {
}
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_UNIX && uwsgi_sock->name[0] != '@') {
struct stat st;
if (!stat(uwsgi_sock->name, &st)) {
if (st.st_ino != uwsgi_sock->inode) {
uwsgi_log("VACUUM WARNING: unix socket %s changed inode. Skip removal\n", uwsgi_sock->name);
goto next;
}
}
if (unlink(uwsgi_sock->name)) {
uwsgi_error("unlink()");
}
@@ -1355,6 +1437,7 @@ static void vacuum(void) {
uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
}
}
next:
uwsgi_sock = uwsgi_sock->next;
}
}
@@ -1412,14 +1495,17 @@ void signal_pidfile(int sig, char *filename) {
exit(0);
}
void fixup_argv_and_environ(int argc, char **argv, char **environ) {
static void fixup_argv_and_environ(int argc, char **argv, char **environ, char **envp) {
uwsgi.orig_argv = argv;
uwsgi.argv = argv;
uwsgi.argc = argc;
uwsgi.environ = environ;
// avoid messing with fake environ
if (envp && *environ != *envp) return;
#if defined(__linux__) || defined(__sun__)
int i;
@@ -1493,7 +1579,7 @@ void uwsgi_plugins_atexit(void) {
void uwsgi_backtrace(int depth) {
#if defined(__linux__) || defined(__APPLE__) || defined(UWSGI_HAS_EXECINFO)
#if defined(__linux__) || (defined(__APPLE__) && !defined(NO_EXECINFO)) || defined(UWSGI_HAS_EXECINFO)
#include <execinfo.h>
@@ -1750,6 +1836,8 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_register_clock(&uwsgi_unix_clock);
uwsgi_set_clock("unix");
// fallback config
atexit(uwsgi_fallback_config);
// manage/flush logs
atexit(uwsgi_flush_logs);
// clear sockets, pidfiles...
@@ -1831,7 +1919,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
// ok we can now safely play with argv and environ
fixup_argv_and_environ(argc, argv, environ);
fixup_argv_and_environ(argc, argv, environ, envp);
if (gethostname(uwsgi.hostname, 255)) {
uwsgi_error("gethostname()");
@@ -1894,6 +1982,9 @@ int main(int argc, char *argv[], char *envp[]) {
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
// manage envdirs ASAP
uwsgi_envdirs(uwsgi.envdirs);
// --get management
struct uwsgi_string_list *get_list = uwsgi.get_list;
while(get_list) {
@@ -1928,7 +2019,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
// setup master logging
if (uwsgi.log_master)
if (uwsgi.log_master && !uwsgi.daemonize2)
uwsgi_setup_log_master();
// setup offload engines
@@ -2090,6 +2181,12 @@ int main(int argc, char *argv[], char *envp[]) {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
// we could now patch the binary
if (uwsgi.privileged_binary_patch) {
uwsgi.argv[0] = uwsgi.privileged_binary_patch;
@@ -2142,6 +2239,23 @@ int uwsgi_start(void *v_argv) {
}
#endif
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_in_jail) {
uwsgi_log("running \"%s\" (in-jail)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
}
uwsgi_foreach(usl, uwsgi.call_in_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
uwsgi_file_write_do(uwsgi.file_write_list);
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
@@ -2451,6 +2565,11 @@ int uwsgi_start(void *v_argv) {
else if (!uwsgi.sockets && ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.master_process) {
// here we will have a zombie... sorry
uwsgi_log("...you should enable the master process... really...\n");
if (uwsgi.force_gateway) {
struct uwsgi_gateway *ug = &ushared->gateways[0];
ug->loop(0, ug->data);
// when we are here the gateway is dead :(
}
exit(0);
}
@@ -2585,7 +2704,7 @@ unsafe:
}
}
// initialize locks and socket as soon as possibile, as the master could enqueue tasks
// initialize locks and socket as soon as possible, as the master could enqueue tasks
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
@@ -2806,7 +2925,7 @@ next2:
exit(1);
}
if (uwsgi.sockets->fd != 0) {
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
if (dup2(uwsgi.sockets->fd, 0) < 0) {
uwsgi_error("dup2()");
}
@@ -2844,6 +2963,34 @@ next2:
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->post_fork) {
uwsgi.gp[i]->post_fork();
}
}
if (uwsgi.worker_exec2) {
char *w_argv[2];
w_argv[0] = uwsgi.worker_exec2;
w_argv[1] = NULL;
uwsgi.sockets->arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.sockets->fd, F_SETFL, uwsgi.sockets->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
if (dup2(uwsgi.sockets->fd, 0) < 0) {
uwsgi_error("dup2()");
}
}
execvp(w_argv[0], w_argv);
// never here
uwsgi_error("execvp()");
exit(1);
}
uwsgi_worker_run();
// never here
_exit(0);
@@ -3141,7 +3288,7 @@ void build_options() {
/*
this function build the help output from the uwsgi.options structure
this function builds the help output from the uwsgi.options structure
*/
void uwsgi_help(char *opt, char *val, void *none) {
@@ -3195,6 +3342,12 @@ void uwsgi_init_all_apps() {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_pre_app) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_apps) {
@@ -3254,6 +3407,11 @@ void uwsgi_init_all_apps() {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_post_app) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
}
@@ -3650,8 +3808,8 @@ void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
}
#endif
#ifdef __linux__
void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
uwsgi_build_unshare(value);
void uwsgi_opt_set_unshare(char *opt, char *value, void *mask) {
uwsgi_build_unshare(value, (int *) mask);
}
#endif
@@ -3662,9 +3820,13 @@ void uwsgi_opt_set_env(char *opt, char *value, void *none) {
}
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
#ifdef UNSETENV_VOID
unsetenv(value);
#else
if (unsetenv(value)) {
uwsgi_error("unsetenv()");
}
#endif
}
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
@@ -3692,6 +3854,10 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
if (uwsgi_load_plugin(-1, p, NULL)) {
build_options();
}
else if (!uwsgi_startswith(opt, "need-", 5)) {
uwsgi_log("unable to load plugin \"%s\"\n", p);
exit(1);
}
p = strtok(NULL, ",");
}
free(p);
@@ -4077,7 +4243,7 @@ void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
}
char *uwsgi_get_cflags() {
size_t len = sizeof(UWSGI_CFLAGS);
size_t len = sizeof(UWSGI_CFLAGS) -1;
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
View File
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:html="http://www.w3.org/TR/html4/"
xmlns="http://www.w3.org/TR/html4/"
exclude-result-prefixes="html">
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Strict//EN"
indent="yes" doctype-system="http://www.w3.org/TR/html4/strict.dtd"
encoding="UTF-8" />
<xsl:template name="format-date">
<xsl:param name="date" />
<xsl:value-of select="substring-before($date, 'T')" />
<xsl:text> </xsl:text>
<xsl:value-of select="substring-after($date, 'T')" />
</xsl:template>
<xsl:template match="index">
<html>
<head>
<xsl:choose>
<xsl:when test="$stylesheet">
<link rel="stylesheet" type="text/css" media="all" href="{$stylesheet}" />
</xsl:when>
<xsl:otherwise>
<style type="text/css">
html {
color: #000000;
background-color: #fefefe;
font-family: sans-serif;
}
h1 {
font-size: 1.5em;
font-weight: bold;
margin: .67em 0;
}
th {
text-align: left;
}
td {
font-family: mono;
}
td, th {
padding: 0 1em;
}
td.size {
text-align: right;
}
:link, :visited {
text-decoration: none;
}
:link {
color: #000099;
}
:visited {
color: #6600cc;
}
:link:hover,
:visited:hover {
text-decoration: underline;
}
:link:focus,
:visited:focus {
text-decoration: underline;
}
:link:active,
:visited:active {
text-decoration: underline;
}
</style>
</xsl:otherwise>
</xsl:choose>
<title>Index of <xsl:value-of select="@path" /></title>
</head>
<body>
<h1>Index of <xsl:value-of select="@path" /></h1>
<table>
<tr>
<th class="name">Name</th>
<th class="mtime">Last Modified</th>
<th class="size">Size</th>
</tr>
<tr>
<td class="name" colspan="3"><a href=".." title="Parent">Parent directory</a></td>
</tr>
<xsl:apply-templates select="directory" />
<xsl:apply-templates select="file" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="directory">
<tr class="directory">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:attribute>
<xsl:value-of select="." />
<xsl:text>/</xsl:text>
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
<xsl:template match="file">
<tr class="file">
<td class="name">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:value-of select="." />
</xsl:element>
</td>
<td class="mtime">
<xsl:call-template name="format-date">
<xsl:with-param name="date" select="@mtime" />
</xsl:call-template>
</td>
<td class="size">
<xsl:value-of select="@size" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
+17
View File
@@ -0,0 +1,17 @@
[uwsgi]
plugin = 0:notfound, router_xmldir, xslt
http-socket = :8080
docroot = .
check-static = %(docroot)
route-if = isdir:%(docroot)/${PATH_INFO} goto:index
route-run = last:
route-label = index
; uncomment to link CSS stylesheet /css/default.css
;route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=/css/default.css,content_type=text/html
; use embedded CSS
route-run = toxslt:stylesheet=examples/xmlindex-html.xsl,params=stylesheet=,content_type=text/html
route-run = xmldir:%(docroot)/${PATH_INFO}
+8 -1
View File
@@ -7,7 +7,14 @@ Net::HTTP.start("uwsgi.it") do |http|
end
end
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
major,minor = RUBY_VERSION.split('.')
if major.to_i >= 2 or (major.to_i == 1 and minor.to_i >= 9)
# a trick for installations with messy PATH
ENV['UWSGICONFIG_RUBYPATH'] = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
system("bash install.sh ruby2 #{Dir.pwd}/uwsgi.ruby")
else
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
end
open("Makefile", "w") do |file|
file.write("all:\n")
-54
View File
@@ -1,54 +0,0 @@
import uwsgi
if uwsgi.loop == 'gevent':
import gevent
from threading import Thread
import time
from uwsgidecorators import postfork
def foobar():
while True:
time.sleep(3)
print "threee second elapsed in worker %d" % uwsgi.worker_id()
@postfork
def spawn_thread():
t = Thread(target=foobar)
t.daemon = True
t.start()
@postfork
def spawn_thread2():
t = Thread(target=foobar)
t.daemon = True
t.start()
def gl_func():
while True:
gevent.sleep(2)
print "i am a greenltet running in worker %d" % uwsgi.worker_id()
@postfork
def spawn_greenlet():
gevent.spawn(gl_func)
print uwsgi.version
print uwsgi.workers()
try:
uwsgi.cache_set('foo', "Hello World from cache")
except:
pass
def application(env, start_response):
print env['wsgi.input'].read()
if uwsgi.loop == 'gevent':
gevent.sleep()
start_response('200 OK', [('Content-Type', 'text/html')])
yield "foobar<br/>"
if uwsgi.loop == 'gevent':
gevent.sleep(3)
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
try:
yield uwsgi.cache_get('foo')
except:
pass
-31
View File
@@ -1,31 +0,0 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
return 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
+6
View File
@@ -82,6 +82,12 @@ void linux_namespace_start(void *argv) {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_post_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
+11 -2
View File
@@ -1,6 +1,15 @@
import os
NAME='alarm_speech'
CFLAGS = []
uwsgi_os = os.uname()[0]
LDFLAGS = []
LIBS = ['-framework appkit']
if uwsgi_os == "Darwin":
CFLAGS = []
LIBS = ['-framework appkit']
else:
CFLAGS = ['-I /usr/include/GNUstep']
LIBS = []
GCC_LIST = ['alarm_speech.m']
+1 -1
View File
@@ -10,7 +10,7 @@
*/
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
+17 -2
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include "cr.h"
@@ -9,13 +9,28 @@ int uwsgi_cr_map_use_void(struct uwsgi_corerouter *ucr, struct corerouter_peer *
}
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
uint64_t hits = 0;
uwsgi_rlock(ucr->cache->lock);
peer->instance_address = uwsgi_cache_get2(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len);
char *value = uwsgi_cache_get4(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len, &hits);
if (!value) goto end;
peer->tmp_socket_name = uwsgi_concat2n(value, peer->instance_address_len, "", 0);
size_t nodes = uwsgi_str_occurence(peer->tmp_socket_name, peer->instance_address_len, '|');
if (nodes > 0) {
size_t choosen_node = hits % (nodes+1);
size_t choosen_node_len = 0;
peer->instance_address = uwsgi_str_split_nget(peer->tmp_socket_name, peer->instance_address_len, '|', choosen_node, &choosen_node_len);
if (!peer->instance_address) goto end;
peer->instance_address_len = choosen_node_len;
}
else {
peer->instance_address = peer->tmp_socket_name;
}
char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
if (cs_mod) {
peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
peer->instance_address_len = (cs_mod - peer->instance_address);
}
end:
uwsgi_rwunlock(ucr->cache->lock);
return 0;
}
+12 -9
View File
@@ -201,7 +201,18 @@ edge:
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
wsgi_req->start_of_request = uwsgi_micros();
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
goto edge;
}
// in case of errors (or thundering herd, just rest it)
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
goto clear;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
@@ -209,14 +220,6 @@ edge:
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
goto edge;
}
goto clear;
}
// here we spawn an async {} block
CV *async_xs_call = newXS(NULL, XS_coroae_accept_request, "uwsgi::coroae");
+7 -2
View File
@@ -2,7 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
extern struct uwsgi_plugin rack_plugin;
static struct uwsgi_plugin *rack_plugin;
struct ufib {
int enabled;
@@ -53,7 +53,7 @@ static void fiber_schedule_to_req() {
}
if (error) {
rack_plugin.exception_log(NULL);
rack_plugin->exception_log(NULL);
rb_gc_unregister_address(&ufiber.fib[id]);
}
@@ -72,6 +72,11 @@ static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
}
static int fiber_init() {
rack_plugin = uwsgi_plugin_get("rack");
if (!rack_plugin) {
uwsgi_log("[ruby-fiber] rack plugin is not loaded !!!\n");
exit(1);
}
return 0;
}
+8 -8
View File
@@ -164,14 +164,6 @@ edge:
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
@@ -183,6 +175,14 @@ edge:
goto clear;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// hack to easily pass wsgi_req pointer to the greenlet
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
+299
View File
@@ -0,0 +1,299 @@
#include <uwsgi.h>
#include <api/glfs.h>
#ifdef UWSGI_MATHEVAL
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
#endif
extern struct uwsgi_server uwsgi;
/*
Author: Roberto De Ioris
--glusterfs-mount mountpoint=/foo,server=192.168.173.13:24007;192.168.173.17:0,volfile=foo.vol;volume=unbit001
*/
struct uwsgi_plugin glusterfs_plugin;
struct uwsgi_glusterfs {
int timeout;
struct uwsgi_string_list *mountpoints;
} uglusterfs;
static struct uwsgi_option uwsgi_glusterfs_options[] = {
{"glusterfs-mount", required_argument, 0, "virtual mount the specified glusterfs volume in a uri", uwsgi_opt_add_string_list, &uglusterfs.mountpoints, UWSGI_OPT_MIME},
{"glusterfs-timeout", required_argument, 0, "timeout for glusterfs async mode", uwsgi_opt_set_int, &uglusterfs.timeout, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static int uwsgi_glusterfs_read_sync(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
while(remains > 0) {
char buf[8192];
ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0);
if (rlen <= 0) return -1;
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) return -1;
remains -= rlen;
}
return 0;
}
/*
async read of a resource
the uwsgi_glusterfs_async_io structure is passed between threads
the callback simply signal the main core about the availability of data
*/
struct uwsgi_glusterfs_async_io {
int fd[2];
ssize_t rlen;
};
static void uwsgi_glusterfs_read_async_cb(glfs_fd_t *fd, ssize_t rlen, void *data) {
struct uwsgi_glusterfs_async_io *aio = (struct uwsgi_glusterfs_async_io *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("[glusterfs-cb] rlen = %d\n", rlen);
#endif
aio->rlen = rlen;
// signal the core
if (write(aio->fd[1], "\1", 1) <= 0) {
uwsgi_error("uwsgi_glusterfs_read_async_cb()/write()");
}
}
static int uwsgi_glusterfs_read_async(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
char buf[8192];
struct uwsgi_glusterfs_async_io aio;
int ret = -1;
if (pipe(aio.fd)) {
uwsgi_error("uwsgi_glusterfs_read_async()/pipe()");
return -1;
}
aio.rlen = -1;
while(remains > 0) {
// trigger an async read
if (glfs_read_async(fd, buf, 8192, 0, uwsgi_glusterfs_read_async_cb, &aio)) goto end;
// wait for the callback to be executed
if (uwsgi.wait_read_hook(aio.fd[0], uglusterfs.timeout) <= 0) goto end;
if (aio.rlen <= 0) goto end;
if (uwsgi_response_write_body_do(wsgi_req, buf, aio.rlen)) goto end;
remains -= aio.rlen;
}
ret = 0;
end:
close(aio.fd[0]);
close(aio.fd[1]);
return ret;
}
static int uwsgi_glusterfs_try(struct uwsgi_app *ua, char *node) {
int ret = -1;
char *colon = strchr(node, ':');
// unix socket
if (!colon) {
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "unix", node, 0)) {
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
return -1;
}
goto connect;
}
*colon = 0;
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "tcp", node, atoi(colon+1))) {
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
return -1;
}
connect:
ret = glfs_init((glfs_t *)ua->interpreter);
if (ret) { uwsgi_error("[glusterfs] glfs_init()"); }
else {
if (colon) *colon = ':';
uwsgi_log("[glusterfs] worker %d connected to %s\n", uwsgi.mywid, node);
}
return ret;
}
static void uwsgi_glusterfs_connect_do(struct uwsgi_app *ua) {
char *servers = uwsgi_str(ua->callable);
char *p = strtok(servers, ";");
while(p) {
uwsgi_log("[glusterfs] try connect to %s for mountpoint %.*s on worker %d ...\n", p, ua->mountpoint_len, ua->mountpoint, uwsgi.mywid);
if (uwsgi_glusterfs_try(ua, p)) {
goto end;
}
p = strtok(NULL, ";");
}
end:
free(servers);
}
static void uwsgi_glusterfs_connect() {
int i;
// search for all of the glusterfs apps and connect to the server-based ones
for (i = 0; i < uwsgi_apps_cnt; i++) {
if (uwsgi_apps[i].modifier1 != glusterfs_plugin.modifier1) continue;
if (!uwsgi_apps[i].callable) {
if (glfs_init((glfs_t *)uwsgi_apps[i].interpreter)) {
uwsgi_error("[glusterfs] glfs_init()");
exit(1);
}
uwsgi_log("[glusterfs] worker %d connected using volfile\n", uwsgi.mywid);
continue;
}
uwsgi_glusterfs_connect_do(&uwsgi_apps[i]);
}
}
static void uwsgi_glusterfs_add_mountpoint(char *arg, size_t arg_len) {
char *ugfs_mountpoint = NULL;
char *ugfs_server = NULL;
char *ugfs_volfile = NULL;
char *ugfs_volume = NULL;
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
"mountpoint", &ugfs_mountpoint,
"server", &ugfs_server,
"servers", &ugfs_server,
"volfile", &ugfs_volfile,
"volume", &ugfs_volume,
NULL)) {
uwsgi_log("unable to parse glusterfs mountpoint definition\n");
exit(1);
}
if (!ugfs_mountpoint || (!ugfs_server && !ugfs_volfile) || !ugfs_volume) {
uwsgi_log("[glusterfs] mount requires a mountpoint, a volume and at least one server or volfile\n");
exit(1);
}
int id = uwsgi_apps_cnt;
time_t now = uwsgi_now();
uwsgi_log("[glusterfs] mounting %s ...\n", ugfs_mountpoint);
// this should fail only if memory is not available
glfs_t *volume = glfs_new(ugfs_volume);
if (!volume) {
uwsgi_error("unable to initialize glusterfs mountpoint: glfs_new()");
exit(1);
}
if (ugfs_volfile) {
if (glfs_set_volfile(volume, ugfs_volfile)) {
uwsgi_error("unable to set glusterfs volfile: glfs_set_volfile\n");
exit(1);
}
}
/*
here we pass ugfs_server as the callable field.
After fork() if this field is defined we will start trying to connect to each one of the configuratio nodes
This is required to have fallback management
*/
struct uwsgi_app *ua = uwsgi_add_app(id, glusterfs_plugin.modifier1, ugfs_mountpoint, strlen(ugfs_mountpoint), volume, ugfs_server);
if (!ua) {
uwsgi_log("[glusterfs] unable to mount %s\n", ugfs_mountpoint);
exit(1);
}
ua->started_at = now;
ua->startup_time = uwsgi_now() - now;
uwsgi_log("GlusterFS app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, ugfs_mountpoint, (int) ua->startup_time, volume);
}
// we translate the string list to an app representation
// this happens before fork() if not in lazy/lazy-apps mode
static void uwsgi_glusterfs_setup() {
if (!uglusterfs.timeout) {
uglusterfs.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
struct uwsgi_string_list *usl = uglusterfs.mountpoints;
while(usl) {
uwsgi_glusterfs_add_mountpoint(usl->value, usl->len);
usl = usl->next;
}
}
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) {
char filename[PATH_MAX+1];
/* Standard GlusterFS request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Empty GlusterFS request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
// blocks empty paths
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1);
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
if (wsgi_req->app_id == -1) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
filename[wsgi_req->path_info_len] = 0;
glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY);
if (!fd) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct stat st;
if (glfs_fstat(fd, &st)) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
}
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end;
// skip body on HEAD
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
size_t remains = st.st_size;
if (uwsgi.async > 1) {
if (uwsgi_glusterfs_read_async(wsgi_req, fd, remains)) goto end;
}
else {
if (uwsgi_glusterfs_read_sync(wsgi_req, fd, remains)) goto end;
}
}
end:
glfs_close(fd);
return UWSGI_OK;
}
struct uwsgi_plugin glusterfs_plugin = {
.name = "glusterfs",
.modifier1 = 27,
.options = uwsgi_glusterfs_options,
.post_fork = uwsgi_glusterfs_setup,
.fixup = uwsgi_glusterfs_connect,
.request = uwsgi_glusterfs_request,
.after_request = log_request,
};
+7
View File
@@ -0,0 +1,7 @@
import os
NAME='glusterfs'
CFLAGS = os.popen('pkg-config --cflags glusterfs-api').read().rstrip().split()
LDFLAGS = []
LIBS = os.popen('pkg-config --libs glusterfs-api').read().rstrip().split()
GCC_LIST = ['glusterfs']
+57 -5
View File
@@ -10,6 +10,7 @@ struct uwsgi_http uhttp;
struct uwsgi_option http_options[] = {
{"http", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
{"httprouter", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
#ifdef UWSGI_SSL
{"https", required_argument, 0, "add an https router/server on the specified address with specified certificate and key", uwsgi_opt_https, &uhttp, 0},
{"https2", required_argument, 0, "add an https/spdy router/server using keyval options", uwsgi_opt_https2, &uhttp, 0},
@@ -207,8 +208,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
// PATH_INFO must be url-decoded !!!
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
if (!hr->path_info) {
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
}
else {
size_t new_path_info = ptr - base;
if (new_path_info > hr->path_info_len) {
char *tmp_buf = realloc(hr->path_info, new_path_info);
if (!tmp_buf) return -1;
hr->path_info = tmp_buf;
}
hr->path_info_len = new_path_info;
}
http_url_decode(base, &hr->path_info_len, hr->path_info);
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
query_string = ptr + 1;
@@ -219,8 +231,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
if (uwsgi_buffer_append_keyval(out, "REQUEST_URI", 11, base, ptr - base)) return -1;
if (!query_string) {
// PATH_INFO must be url-decoded !!!
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
if (!hr->path_info) {
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
}
else {
size_t new_path_info = ptr - base;
if (new_path_info > hr->path_info_len) {
char *tmp_buf = realloc(hr->path_info, new_path_info);
if (!tmp_buf) return -1;
hr->path_info = tmp_buf;
}
hr->path_info_len = new_path_info;
}
http_url_decode(base, &hr->path_info_len, hr->path_info);
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, "", 0)) return -1;
@@ -430,6 +453,9 @@ ssize_t hr_instance_connected(struct corerouter_peer* peer) {
cr_peer_connected(peer, "hr_instance_connected()");
// we are connected, we cannot retry anymore
peer->can_retry = 0;
// prepare for write
peer->out_pos = 0;
@@ -566,8 +592,10 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
}
#endif
else if (hr->force_chunked) {
peer->in->limit = 0;
if (uwsgi_buffer_insert_chunked(peer->in, 0, len)) return -1;
if (uwsgi_buffer_append(peer->in, "\r\n", 2)) return -1;
peer->in->len = UMIN(peer->in->len, UMAX16);
}
}
@@ -705,7 +733,7 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
hr->raw_body = 1;
}
new_peer->can_retry = 1;
cr_connect(new_peer, hr_instance_connected);
break;
}
@@ -775,7 +803,31 @@ ssize_t hr_recv_stud4(struct corerouter_peer * main_peer) {
}
// retry connection to the backend
static int hr_retry(struct corerouter_peer *peer) {
struct uwsgi_corerouter *ucr = peer->session->corerouter;
if (peer->instance_address_len > 0) goto retry;
if (ucr->mapper(ucr, peer)) {
return -1;
}
if (peer->instance_address_len == 0) {
return -1;
}
retry:
// start async connect (again)
cr_connect(peer, hr_instance_connected);
return 0;
}
int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
// set the retry hook
cs->retry = hr_retry;
struct http_session *hr = (struct http_session *) cs;
// set the modifier1
cs->main_peer->modifier1 = uhttp.modifier1;
+2
View File
@@ -568,6 +568,8 @@ static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
new_peer->can_retry = 1;
cr_connect(new_peer, hr_instance_connected);
return 1;
+2
View File
@@ -28,6 +28,7 @@ struct uwsgi_jvm {
jclass list_class;
jclass set_class;
jclass iterator_class;
jclass bool_class;
jclass runtime_exception;
jclass io_exception;
@@ -101,6 +102,7 @@ int uwsgi_jvm_call_bool(jobject, jmethodID, ...);
int uwsgi_jvm_consume_input_stream(struct wsgi_request *, size_t, jobject);
jobject uwsgi_jvm_num(long);
jobject uwsgi_jvm_request_body_input_stream(void);
jobject uwsgi_jvm_bool(long);
size_t uwsgi_jvm_array_len(jobject);
jobject uwsgi_jvm_array_get(jobject, long);
+19 -3
View File
@@ -896,6 +896,19 @@ jobject uwsgi_jvm_num(long num) {
return o;
}
jobject uwsgi_jvm_bool(long b) {
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.int_class, "<init>", "(I)V");
if (!mid) return NULL;
}
jobject o = (*ujvm_env)->NewObject(ujvm_env, ujvm.bool_class, mid, b);
if (uwsgi_jvm_exception()) {
return NULL;
}
return o;
}
jobject uwsgi_jvm_str(char *str, size_t len) {
jobject new_str;
if (len > 0) {
@@ -1063,6 +1076,9 @@ static void uwsgi_jvm_create(void) {
ujvm.int_class = uwsgi_jvm_class("java/lang/Integer");
if (!ujvm.int_class) exit(1);
ujvm.bool_class = uwsgi_jvm_class("java/lang/Boolean");
if (!ujvm.bool_class) exit(1);
ujvm.long_class = uwsgi_jvm_class("java/lang/Long");
if (!ujvm.long_class) exit(1);
@@ -1116,7 +1132,7 @@ static void uwsgi_jvm_create(void) {
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(j_opt_value, (jobject) 1);
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
@@ -1126,7 +1142,7 @@ static void uwsgi_jvm_create(void) {
jobject ll = uwsgi_jvm_list();
uwsgi_jvm_list_add(ll, j_opt_value);
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(ll, (jobject) 1);
uwsgi_jvm_list_add(ll, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
@@ -1136,7 +1152,7 @@ static void uwsgi_jvm_create(void) {
}
else {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, (jobject) 1);
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
+8 -3
View File
@@ -4,6 +4,11 @@
#include <lualib.h>
#include <lauxlib.h>
#if LUA_VERSION_NUM < 502
# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
# define lua_rawlen lua_objlen
#endif
extern struct uwsgi_server uwsgi;
struct uwsgi_lua {
@@ -347,7 +352,7 @@ static int uwsgi_api_unlock(lua_State *L) {
return 0;
}
static const luaL_reg uwsgi_api[] = {
static const luaL_Reg uwsgi_api[] = {
{"log", uwsgi_api_log},
{"connection_fd", uwsgi_api_req_fd},
@@ -411,7 +416,7 @@ static void uwsgi_lua_app() {
for(i=0;i<uwsgi.cores;i++) {
ulua.L[i] = luaL_newstate();
luaL_openlibs(ulua.L[i]);
luaL_register(ulua.L[i], "uwsgi", uwsgi_api);
luaL_newlib(ulua.L[i], uwsgi_api);
lua_pushstring(ulua.L[i], UWSGI_VERSION);
lua_setfield(ulua.L[i], -2, "version");
@@ -711,7 +716,7 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
static void uwsgi_lua_configurator_array(lua_State *L) {
int i;
int n = luaL_getn(L, -3);
int n = lua_rawlen(L, -3);
for(i=1;i<=n;i++) {
lua_rawgeti(L, 1, i);
+26 -15
View File
@@ -1,22 +1,33 @@
import os,sys
try:
LUALIB = os.environ['UWSGICONFIG_LUALIB']
except:
LUALIB = 'lua5.1'
LUAINC = os.environ.get('UWSGICONFIG_LUAINC')
LUALIB = os.environ.get('UWSGICONFIG_LUALIB')
LUALIBPATH = os.environ.get('UWSGICONFIG_LUALIBPATH')
LUAPC = os.environ.get('UWSGICONFIG_LUAPC', 'lua5.1')
try:
LUAINC = os.environ['UWSGICONFIG_LUAINC']
except:
LUAINC = '/usr/include/lua5.1'
# we LUAINC/LUALIB/LUALIBPATH override the LUAPC for backwards compat
if LUAINC:
CFLAGS = ['-I%s' % LUAINC]
else:
try:
CFLAGS = os.popen('pkg-config --cflags %s' % LUAPC).read().rstrip().split()
except:
CFLAGS = ['-I/usr/include/lua5.1']
try:
LUALIBPATH = os.environ['UWSGICONFIG_LUALIBPATH']
except:
LUALIBPATH = '/usr/lib/lua5.1'
if LUALIB:
LIBS = ['-l%s' % LUALIB]
else:
try:
LIBS = os.popen('pkg-config --libs %s' % LUAPC).read().rstrip().split()
except:
LIBS = ['-llua5.1']
if LUALIBPATH:
LDFLAGS = ['-L%s' % LUALIBPATH]
else:
LDFLAGS = []
NAME='lua'
CFLAGS = ['-I%s' % LUAINC]
LDFLAGS = ['-L%s' % LUALIBPATH]
GCC_LIST = ['lua_plugin']
LIBS = ['-l%s' % LUALIB]
+1 -1
View File
@@ -77,7 +77,7 @@ struct uwsgi_mono {
struct uwsgi_option uwsgi_mono_options[] = {
{"mono-app", required_argument, 0, "load a Mono asp.net app from the specified directory", uwsgi_opt_add_string_list, &umono.app, 0},
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default, run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default: run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
{"mono-key", required_argument, 0, "select the ApplicationHost based on the specified CGI var", uwsgi_opt_add_string_list, &umono.key, 0},
{"mono-version", required_argument, 0, "set the Mono jit version", uwsgi_opt_set_str, &umono.version, 0},
{"mono-config", required_argument, 0, "set the Mono config file", uwsgi_opt_set_str, &umono.config, 0},
+1 -1
View File
@@ -96,7 +96,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
}
else {
char *sl = SG(sapi_headers).http_status_line;
uwsgi_response_prepare_headers(wsgi_req, sl + 8 , strlen(sl) - 8);
uwsgi_response_prepare_headers(wsgi_req, sl + 9 , strlen(sl + 9));
}
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+5 -1
View File
@@ -1,5 +1,5 @@
#undef __USE_GNU
#include "../../uwsgi.h"
#include <uwsgi.h>
#ifdef __APPLE__
#define HAS_BOOL 1
@@ -50,6 +50,9 @@ struct uwsgi_perl {
SV *atexit;
int loaded;
struct uwsgi_string_list *exec;
struct uwsgi_string_list *exec_post_fork;
};
void init_perl_embedded_module(void);
@@ -66,3 +69,4 @@ int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
PerlInterpreter *uwsgi_perl_new_interpreter(void);
int uwsgi_perl_mule(char *);
void uwsgi_perl_run_hook(SV *);
void uwsgi_perl_exec(char *);
+17
View File
@@ -483,6 +483,16 @@ void uwsgi_psgi_app() {
//load app in the main interpreter list
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
}
// create a perl environment (if needed)
else if (uperl.exec) {
PERL_SET_CONTEXT(uperl.main[0]);
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec) {
uwsgi_perl_exec(usl->value);
}
}
@@ -502,3 +512,10 @@ int uwsgi_perl_mule(char *opt) {
}
void uwsgi_perl_exec(char *filename) {
size_t size = 0;
char *buf = uwsgi_open_and_read(filename, &size, 1, NULL);
perl_eval_pv(buf, 0);
free(buf);
}
+7
View File
@@ -21,6 +21,8 @@ struct uwsgi_option uwsgi_perl_options[] = {
#endif
{"perl-args", required_argument, 0, "add items (space separated) to @ARGV", uwsgi_opt_set_str, &uperl.argv_items, 0},
{"perl-arg", required_argument, 0, "add an item to @ARGV", uwsgi_opt_add_string_list, &uperl.argv_item, 0},
{"perl-exec", required_argument, 0, "exec the specified perl file before fork()", uwsgi_opt_add_string_list, &uperl.exec, 0},
{"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -588,6 +590,11 @@ void uwsgi_perl_post_fork() {
SvREADONLY_on(GvSV(tmpgv));
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec_post_fork) {
uwsgi_perl_exec(usl->value);
}
if (uperl.postfork) {
uwsgi_perl_run_hook(uperl.postfork);
}
+308
View File
@@ -0,0 +1,308 @@
#include <uwsgi.h>
#ifdef __linux__
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
#endif
#ifndef __FreeBSD__
#include <utmp.h>
#endif
extern struct uwsgi_server uwsgi;
struct uwsgi_pty_client {
int fd;
struct uwsgi_pty_client *prev;
struct uwsgi_pty_client *next;
};
static struct uwsgi_pty {
char *addr;
char *remote;
int queue;
int server_fd;
int master_fd;
int slave_fd;
int log;
int original_log;
int input;
int original_input;
int no_isig;
char *command;
pid_t command_pid;
struct uwsgi_pty_client *head;
struct uwsgi_pty_client *tail;
} upty;
static struct uwsgi_pty_client *uwsgi_pty_client_new(int fd) {
struct uwsgi_pty_client *upc = uwsgi_calloc(sizeof(struct uwsgi_pty_client));
upc->fd = fd;
if (upty.tail) {
upc->prev = upty.tail;
upty.tail->next = upc;
}
upty.tail = upc;
if (!upty.head) upty.head = upc;
return upc;
}
static void uwsgi_pty_client_remove(struct uwsgi_pty_client *upc) {
struct uwsgi_pty_client *prev = upc->prev;
struct uwsgi_pty_client *next = upc->next;
if (prev) {
prev->next = next;
}
if (next) {
next->prev = prev;
}
if (upc == upty.head) {
upty.head = next;
}
if (upc == upty.tail) {
upty.tail = prev;
}
close(upc->fd);
free(upc);
}
static struct uwsgi_option uwsgi_pty_options[] = {
{"pty-socket", required_argument, 0, "bind the pty server on the specified address", uwsgi_opt_set_str, &upty.addr, 0},
{"pty-log", no_argument, 0, "send stdout/stderr to the log engine too", uwsgi_opt_true, &upty.log, 0},
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
{"pty-exec", no_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void uwsgi_pty_setterm(int fd) {
struct termios tio;
tcgetattr(fd, &tio);
tio.c_iflag |= IGNPAR;
tio.c_iflag &= ~(ISTRIP | IMAXBEL | BRKINT | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
#ifdef IUCLC
tio.c_iflag &= ~IUCLC;
#endif
tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
if (upty.no_isig) {
tio.c_lflag &= ~(ISIG);
}
#ifdef IEXTEN
tio.c_lflag &= ~IEXTEN;
#endif
tio.c_oflag &= ~OPOST;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
#ifdef B38400
cfsetispeed(&tio, B38400);
cfsetospeed(&tio, B38400);
#endif
tcsetattr(fd, TCSANOW, &tio);
}
static void *uwsgi_pty_loop(void *arg) {
/*
if slave is ready there is something to send to the clients (and logs)
if client is ready we have something to write to the master pty
*/
for(;;) {
char buf[8192];
int interesting_fd = -1;
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
if (ret == 0) continue;
if (ret < 0) continue;
if (upty.input && interesting_fd == upty.original_input) {
ssize_t rlen = read(upty.original_input, buf, 8192);
if (rlen <= 0) continue;
if (write(upty.master_fd, buf, rlen) != rlen) {
// what to do ?
}
continue;
}
if (interesting_fd == upty.master_fd) {
ssize_t rlen = read(upty.master_fd, buf, 8192);
if (rlen == 0) exit(1);
if (rlen < 0) {
uwsgi_error("uwsgi_pty_loop()/read()");
}
if (upty.log && upty.original_log >= 0) {
if (write(upty.original_log, buf, rlen) != rlen) {
// what to do ?
}
}
struct uwsgi_pty_client *upc = upty.head;
while(upc) {
if (write(upc->fd, buf, rlen) != rlen) {
struct uwsgi_pty_client *tmp_upc = upc->next;
uwsgi_pty_client_remove(upc);
upc = tmp_upc;
continue;
}
upc = upc->next;
}
continue;
}
if (interesting_fd == upty.server_fd) {
struct sockaddr_un client_src;
memset(&client_src, 0, sizeof(struct sockaddr_un));
socklen_t client_src_len = 0;
int client_fd = accept(upty.server_fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
continue;
}
struct uwsgi_pty_client *upc = uwsgi_pty_client_new(client_fd);
event_queue_add_fd_read(upty.queue, upc->fd);
continue;
}
struct uwsgi_pty_client *upc = upty.head;
while(upc) {
if (interesting_fd == upc->fd) {
ssize_t rlen = read(upc->fd, buf, 8192);
if (rlen <= 0) {
uwsgi_pty_client_remove(upc);
break;
}
if (write(upty.master_fd, buf, rlen) != rlen) {
}
break;
}
upc = upc->next;
}
continue;
}
}
static void uwsgi_pty_init() {
if (!upty.addr) return;
if (!uwsgi.master_process) return;
if (uwsgi.mywid > 1) return;
char *tcp_port = strrchr(upty.addr, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
upty.server_fd = bind_to_tcp(upty.addr, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
upty.server_fd = bind_to_unix(upty.addr, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
if (upty.log) {
upty.original_log = dup(1);
}
if (upty.input) {
upty.original_input = dup(0);
}
if (openpty(&upty.master_fd, &upty.slave_fd, NULL, NULL, NULL)) {
uwsgi_error("uwsgi_pty_init()/openpty()");
exit(1);
}
uwsgi_log("pty server %s (fd: %d) enabled on %s master: %d slave: %d\n", upty.addr, upty.server_fd, ttyname(upty.slave_fd), upty.master_fd, upty.slave_fd);
upty.queue = event_queue_init();
event_queue_add_fd_read(upty.queue, upty.master_fd);
event_queue_add_fd_read(upty.queue, upty.server_fd);
if (upty.input) {
event_queue_add_fd_read(upty.queue, upty.original_input);
uwsgi_pty_setterm(upty.original_input);
}
login_tty(upty.slave_fd);
if (upty.command) {
upty.command_pid = uwsgi_run_command(upty.command, NULL, -1);
}
pthread_t t;
pthread_create(&t, NULL, uwsgi_pty_loop, NULL);
}
static int uwsgi_pty_client() {
if (!upty.remote) return 0;
uwsgi_log("[pty] connecting to %s ...\n", upty.remote);
// save current terminal settings
if (!tcgetattr(0, &uwsgi.termios)) {
uwsgi.restore_tc = 1;
}
upty.server_fd = uwsgi_connect(upty.remote, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (upty.server_fd < 0) {
uwsgi_error("uwsgi_pty_client()/connect()");
exit(1);
}
uwsgi_socket_nb(upty.server_fd);
uwsgi_socket_nb(0);
uwsgi_log("[pty] connected.\n");
uwsgi_pty_setterm(0);
upty.queue = event_queue_init();
event_queue_add_fd_read(upty.queue, upty.server_fd);
event_queue_add_fd_read(upty.queue, 0);
for(;;) {
char buf[8192];
int interesting_fd = -1;
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
if (ret <= 0) break;
if (interesting_fd == 0) {
ssize_t rlen = read(0, buf, 8192);
if (rlen <= 0) break;
if (write(upty.server_fd, buf, rlen) != rlen) break;
continue;
}
if (interesting_fd == upty.server_fd) {
ssize_t rlen = read(upty.server_fd, buf, 8192);
if (rlen <= 0) break;
if (write(0, buf, rlen) != rlen) break;
continue;
}
}
exit(0);
// never here
return 0;
}
struct uwsgi_plugin pty_plugin = {
.name = "pty",
.options = uwsgi_pty_options,
.init = uwsgi_pty_client,
.post_fork = uwsgi_pty_init,
};
+12
View File
@@ -0,0 +1,12 @@
NAME='pty'
import os
uwsgi_os = os.uname()[0]
CFLAGS = []
LDFLAGS = []
if uwsgi_os in ('Linux', 'FreeBSD'):
LIBS = ['-lutil']
else:
LIBS = []
GCC_LIST = ['pty']
+52 -38
View File
@@ -25,11 +25,11 @@ struct uwsgi_pypy {
} upypy;
// the functions exposed by libpypy-c
char *(*rpython_startup_code)(void);
int (*pypy_setup_home)(char *, int);
int (*pypy_execute_source)(char *);
void (*pypy_thread_attach)(void);
void (*pypy_init_threads)(void);
char *(*u_rpython_startup_code)(void);
int (*u_pypy_setup_home)(char *, int);
int (*u_pypy_execute_source)(char *);
void (*u_pypy_thread_attach)(void);
void (*u_pypy_init_threads)(void);
// the hooks you can override with pypy
void (*uwsgi_pypy_hook_loader)(char *);
@@ -52,12 +52,18 @@ static int uwsgi_pypy_init() {
exit(1);
}
if (upypy.lib) {
if (dlsym(RTLD_DEFAULT, "rpython_startup_code")) {
uwsgi_log("PyPy runtime detected, skipping libpypy-c loading\n");
goto ready;
}
else if (upypy.lib) {
upypy.handler = dlopen(upypy.lib, RTLD_NOW | RTLD_GLOBAL);
}
else {
if (upypy.home) {
#ifdef __APPLE__
#ifdef __CYGWIN__
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
#elif defined(__APPLE__)
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
#else
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
@@ -69,7 +75,9 @@ static int uwsgi_pypy_init() {
}
// fallback to standard library search path
if (!upypy.handler) {
#ifdef __APPLE__
#ifdef __CYGWIN__
upypy.handler = dlopen("libpypy-c.dll", RTLD_NOW | RTLD_GLOBAL);
#elif defined(__APPLE__)
upypy.handler = dlopen("libpypy-c.dylib", RTLD_NOW | RTLD_GLOBAL);
#else
upypy.handler = dlopen("libpypy-c.so", RTLD_NOW | RTLD_GLOBAL);
@@ -82,35 +90,24 @@ static int uwsgi_pypy_init() {
exit(1);
}
rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!rpython_startup_code) {
u_rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!u_rpython_startup_code) {
uwsgi_log("unable to find rpython_startup_code() symbol\n");
exit(1);
}
pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!pypy_setup_home) {
u_pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!u_pypy_setup_home) {
uwsgi_log("unable to find pypy_setup_home() symbol\n");
exit(1);
}
pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!pypy_init_threads) {
u_pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!u_pypy_init_threads) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_init_threads, multithreading will not work !!!\n");
}
rpython_startup_code();
u_rpython_startup_code();
if (!upypy.home) {
upypy.home = getenv("PYPY_HOME");
@@ -120,11 +117,11 @@ static int uwsgi_pypy_init() {
}
}
if (pypy_setup_home(upypy.home, 0)) {
if (u_pypy_setup_home(upypy.home, 0)) {
char *retry = uwsgi_concat2(upypy.home, "/lib_pypy");
if (uwsgi_is_dir(retry)) {
// this time we use debug
if (!pypy_setup_home(retry, 1)) {
if (!u_pypy_setup_home(retry, 1)) {
free(retry);
goto ready;
}
@@ -134,12 +131,29 @@ static int uwsgi_pypy_init() {
}
ready:
u_pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!u_pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
u_pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!u_pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
if (upypy.setup) {
buffer = uwsgi_open_and_read(upypy.setup, &rlen, 1, NULL);
}
else {
char *start = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_start");
if (!start) {
start = dlsym(RTLD_DEFAULT, "_uwsgi_pypy_setup_start");
}
char *end = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_end");
if (!end) {
end = dlsym(RTLD_DEFAULT, "_uwsgi_pypy_setup_end");
}
if (start && end) {
buffer = uwsgi_concat2n(start, end-start, "", 0);
}
@@ -149,7 +163,7 @@ ready:
uwsgi_log("you have to load a pypy setup file with --pypy-setup\n");
exit(1);
}
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -170,7 +184,7 @@ static void uwsgi_pypy_preinit_apps() {
struct uwsgi_string_list *usl = upypy.eval;
while(usl) {
if (pypy_execute_source(usl->value)) {
if (u_pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
@@ -180,7 +194,7 @@ static void uwsgi_pypy_preinit_apps() {
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -243,14 +257,14 @@ static struct uwsgi_option uwsgi_pypy_options[] = {
};
static void uwsgi_pypy_enable_threads() {
if (pypy_init_threads) {
pypy_init_threads();
if (u_pypy_init_threads) {
u_pypy_init_threads();
}
}
static void uwsgi_pypy_init_thread() {
if (pypy_thread_attach) {
pypy_thread_attach();
if (u_pypy_thread_attach) {
u_pypy_thread_attach();
}
}
@@ -274,7 +288,7 @@ static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t a
static void uwsgi_pypy_post_fork() {
struct uwsgi_string_list *usl = upypy.eval_post_fork;
while(usl) {
if (pypy_execute_source(usl->value)) {
if (u_pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
@@ -283,7 +297,7 @@ static void uwsgi_pypy_post_fork() {
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -306,7 +320,7 @@ static int uwsgi_pypy_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(opt, &rlen, 1, NULL);
pypy_execute_source(buffer);
u_pypy_execute_source(buffer);
free(buffer);
return 1;
}
+41 -6
View File
@@ -125,6 +125,20 @@ struct uwsgi_buffer {
...;
};
struct uwsgi_lock_item {
...;
};
struct uwsgi_cache {
struct uwsgi_lock_item *lock;
...;
};
struct uwsgi_cache_item {
uint64_t keysize;
...;
};
struct uwsgi_server {
char hostname[];
int mywid;
@@ -152,7 +166,7 @@ struct uwsgi_server {
};
struct uwsgi_server uwsgi;
struct uwsgi_plugin *pypy_plugin;
struct uwsgi_plugin pypy_plugin;
const char *uwsgi_pypy_version;
@@ -184,6 +198,11 @@ int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t
int uwsgi_cache_magic_del(char *, uint16_t, char *);
int uwsgi_cache_magic_exists(char *, uint16_t, char *);
int uwsgi_cache_magic_clear(char *);
struct uwsgi_cache *uwsgi_cache_by_name(char *);
void uwsgi_cache_rlock(struct uwsgi_cache *);
void uwsgi_cache_rwunlock(struct uwsgi_cache *);
char *uwsgi_cache_item_key(struct uwsgi_cache_item *);
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *, uint64_t *, struct uwsgi_cache_item **);
int uwsgi_add_file_monitor(uint8_t, char *);
int uwsgi_add_timer(uint8_t, int);
@@ -228,7 +247,7 @@ const char *uwsgi_pypy_version = UWSGI_VERSION;
%s
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin *pypy_plugin;
extern struct uwsgi_plugin pypy_plugin;
%s
''' % ('\n'.join(uwsgi_defines), uwsgi_dot_h, hooks)
@@ -244,8 +263,9 @@ it sucks, i will fix it in the near future...
"""
wsgi_application = None
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
# fix argv if needed
if len(sys.argv) == 0:
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
"""
@@ -332,7 +352,7 @@ class WSGIinput(object):
self.wsgi_req = wsgi_req
def read(self, size=0):
rlen = ffi.new('int64_t*')
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
@@ -473,7 +493,7 @@ def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
uwsgi_gc.append(cb)
if lib.uwsgi_register_rpc(ffi.new("char[]", name), lib.pypy_plugin, argc, cb) < 0:
if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
@@ -540,6 +560,21 @@ def uwsgi_pypy_uwsgi_cache_del(key, cache=ffi.NULL):
raise Exception('unable to delete item from the cache')
uwsgi.cache_del = uwsgi_pypy_uwsgi_cache_del
def uwsgi_pypy_uwsgi_cache_keys(cache=ffi.NULL):
uc = lib.uwsgi_cache_by_name(cache)
if uc == ffi.NULL:
raise Exception('no local uWSGI cache available')
l = []
lib.uwsgi_cache_rlock(uc)
pos = ffi.new('uint64_t *')
uci = ffi.new('struct uwsgi_cache_item **')
while True:
uci[0] = lib.uwsgi_cache_keys(uc, pos, uci)
if uci[0] == ffi.NULL: break
l.append(ffi.string(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize))
lib.uwsgi_cache_rwunlock(uc)
return l
uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys
def uwsgi_pypy_uwsgi_add_timer(signum, secs):
if lib.uwsgi_add_timer(signum, secs) < 0:
+1 -1
View File
@@ -2,7 +2,7 @@ NAME='pypy'
LDFLAGS = []
LIBS = []
GCC_LIST = ['pypy_plugin']
BINARY_LIST = [ ('uwsgi_pypy_setup','pypy_setup.py')]
BINARY_LIST = [ ('_uwsgi_pypy_setup','pypy_setup.py')]
CFLAGS = []
try:
import __pypy__
+9
View File
@@ -13,6 +13,15 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
}
#endif
#ifdef PYTHREE
#undef PyString_AsString
static char *PyString_AsString(PyObject *o) {
PyObject *zero = PyUnicode_AsLatin1String(o);
if (!zero) return "";
return PyBytes_AsString(zero);
}
#endif
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
static uint64_t last_ts = 0;
+48 -1
View File
@@ -10,6 +10,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern char **environ;
@@ -94,6 +95,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi = &uwsgi_apps[id];
memset(wi, 0, sizeof(struct uwsgi_app));
wi->modifier1 = python_plugin.modifier1;
wi->mountpoint_len = wsgi_req->appid_len < 0xff ? wsgi_req->appid_len : (0xff-1);
strncpy(wi->mountpoint, wsgi_req->appid, wi->mountpoint_len);
@@ -605,6 +607,52 @@ PyObject *uwsgi_file_loader(void *arg1) {
}
PyObject *uwsgi_pecan_loader(void *arg1) {
char *pecan = (char *) arg1;
PyObject *pecan_module, *pecan_dict, *pecan_deploy;
PyObject *pecan_arg, *pecan_app;
uwsgi_log( "Loading pecan environment: %s\n", pecan);
pecan_module = PyImport_ImportModule("pecan.deploy");
if (!pecan_module) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_dict = PyModule_GetDict(pecan_module);
if (!pecan_dict) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_deploy = PyDict_GetItemString(pecan_dict, "deploy");
if (!pecan_deploy) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_arg = PyTuple_New(1);
if (!pecan_arg) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
if (PyTuple_SetItem(pecan_arg, 0, UWSGI_PYFROMSTRING(pecan))) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_app = PyEval_CallObject(pecan_deploy, pecan_arg);
if (!pecan_app) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
return pecan_app;
}
PyObject *uwsgi_paste_loader(void *arg1) {
char *paste = (char *) arg1;
@@ -666,7 +714,6 @@ PyObject *uwsgi_paste_loader(void *arg1) {
exit(UWSGI_FAILED_APP_CODE);
}
return paste_app;
}
+10 -3
View File
@@ -121,6 +121,9 @@ struct uwsgi_option uwsgi_python_options[] = {
{"pyargv", required_argument, 0, "manually set sys.argv", uwsgi_opt_set_str, &up.argv, 0},
{"optimize", required_argument, 'O', "set python optimization level", uwsgi_opt_set_int, &up.optimize, 0},
{"pecan", required_argument, 0, "load a pecan config file", uwsgi_opt_set_str, &up.pecan, 0},
{"paste", required_argument, 0, "load a paste.deploy config file", uwsgi_opt_set_str, &up.paste, 0},
{"paste-logger", no_argument, 0, "enable paste fileConfig logger", uwsgi_opt_true, &up.paste_logger, 0},
@@ -1058,6 +1061,7 @@ void uwsgi_python_init_apps() {
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
up.loaders[LOADER_FILE] = uwsgi_file_loader;
up.loaders[LOADER_PECAN] = uwsgi_pecan_loader;
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
up.loaders[LOADER_EVAL] = uwsgi_eval_loader;
up.loaders[LOADER_MOUNT] = uwsgi_mount_loader;
@@ -1123,6 +1127,9 @@ next:
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.pecan != NULL) {
init_uwsgi_app(LOADER_PECAN, up.pecan, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
@@ -1732,7 +1739,7 @@ int uwsgi_python_mule_msg(char *message, size_t len) {
return 1;
}
void uwsgi_python_harakiri(int wid) {
static void uwsgi_python_harakiri(int wid) {
if (up.tracebacker) {
@@ -1762,7 +1769,7 @@ void uwsgi_python_harakiri(int wid) {
import logging
logging.basicConfig(filename='/tmp/pippo.log')
*/
ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
static ssize_t uwsgi_python_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!Py_IsInitialized()) return -1;
UWSGI_GET_GIL
@@ -1800,7 +1807,7 @@ clear:
return -1;
}
void uwsgi_python_on_load() {
static void uwsgi_python_on_load() {
uwsgi_register_logger("python", uwsgi_python_logger);
}
+58
View File
@@ -27,9 +27,20 @@ char *uwsgi_python_get_exception_type(PyObject *exc) {
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
if (module_name) {
#ifdef PYTHREE
char *mod_name = NULL;
PyObject *zero = PyUnicode_AsUTF8String(module_name);
if (zero) {
mod_name = PyString_AsString(zero);
}
#else
char *mod_name = PyString_AsString(module_name);
#endif
if (mod_name && strcmp(mod_name, "exceptions") ) {
char *ret = uwsgi_concat3(mod_name, ".", class_name);
#ifdef PYTHREE
Py_DECREF(zero);
#endif
Py_DECREF(module_name);
return ret;
}
@@ -81,6 +92,38 @@ struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
int64_t line_no = PyInt_AsLong(tb_lineno);
#ifdef PYTHREE
PyObject *zero = PyUnicode_AsUTF8String(tb_filename);
if (!zero) goto end0;
// filename
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
// lineno
if (uwsgi_buffer_append_valnum(ub, line_no)) goto end0;
zero = PyUnicode_AsUTF8String(tb_function);
if (!zero) goto end0;
// function
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
zero = PyUnicode_AsUTF8String(tb_text);
if (!zero) goto end0;
// text
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
#else
// filename
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_filename))) goto end0;
if (uwsgi_buffer_append(ub, PyString_AsString(tb_filename), PyString_Size(tb_filename))) goto end0;
@@ -95,6 +138,7 @@ struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
// text
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_text))) goto end0;
if (uwsgi_buffer_append(ub, PyString_AsString(tb_text), PyString_Size(tb_text))) goto end0;
#endif
// custom (unused)
if (uwsgi_buffer_u16le(ub, 0)) goto end0;
@@ -152,15 +196,29 @@ struct uwsgi_buffer *uwsgi_python_exception_msg(struct wsgi_request *wsgi_req) {
// value could be NULL ?
if (!value) goto end;
#ifdef PYTHREE
char *msg = NULL;
PyObject *zero = PyUnicode_AsUTF8String( PyObject_Str(value) );
if (zero) {
msg = PyString_AsString( zero );
}
#else
char *msg = PyString_AsString( PyObject_Str(value) );
#endif
if (msg) {
size_t msg_len = strlen(msg);
ub = uwsgi_buffer_new(msg_len);
if (uwsgi_buffer_append(ub, msg, msg_len)) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
#ifdef PYTHREE
Py_DECREF(zero);
#endif
}
end:
PyErr_Restore(type, value, traceback);
+44 -9
View File
@@ -4,7 +4,7 @@ extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
int wait_for_specific_signal = 0;
@@ -41,7 +41,7 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
return PyString_FromString("");
}
PyObject *py_uwsgi_signal_received(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_signal_received(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = py_current_wsgi_req();
@@ -172,12 +172,12 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
}
PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
return PyInt_FromLong(uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
}
PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
int fd;
@@ -193,7 +193,7 @@ PyObject *py_uwsgi_close(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int minute, hour, day, month, week;
@@ -211,7 +211,7 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
static PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
uint8_t uwsgi_signal;
int secs;
@@ -819,7 +819,7 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
}
#ifdef PYTHREE
else if (PyUnicode_Check(what)) {
filename = PyBytes_AsString(PyUnicode_AsASCIIString(what));
filename = PyBytes_AsString(PyUnicode_AsLatin1String(what));
fd = open(filename, O_RDONLY);
if (fd < 0) {
@@ -1805,6 +1805,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
if (PyString_Check(pybody)) {
body = PyString_AsString(pybody);
body_len = PyString_Size(pybody);
Py_INCREF(pybody);
uwsgi_py_dict_del(spool_dict, "body");
}
}
@@ -1896,6 +1897,10 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
UWSGI_GET_GIL
if (pybody) {
Py_DECREF(pybody);
}
if (priority) {
free(priority);
@@ -3104,6 +3109,35 @@ PyObject *py_uwsgi_cache_num(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_cache_keys(PyObject * self, PyObject * args) {
char *cache = NULL;
struct uwsgi_cache_item *uci = NULL;
uint64_t pos = 0;
if (!PyArg_ParseTuple(args, "|s:cache_keys", &cache)) {
return NULL;
}
struct uwsgi_cache *uc = uwsgi_cache_by_name(cache);
if (!uc) {
return PyErr_Format(PyExc_ValueError, "no local uWSGI cache available");
}
PyObject *l = PyList_New(0);
uwsgi_rlock(uc->lock);
for(;;) {
uci = uwsgi_cache_keys(uc, &pos, &uci);
if (!uci) break;
PyObject *ci = PyString_FromStringAndSize(uci->key, uci->keysize);
PyList_Append(l, ci);
Py_DECREF(ci);
}
uwsgi_rwunlock(uc->lock);
return l;
}
static PyMethodDef uwsgi_cache_methods[] = {
{"cache_get", py_uwsgi_cache_get, METH_VARARGS, ""},
{"cache_set", py_uwsgi_cache_set, METH_VARARGS, ""},
@@ -3116,6 +3150,7 @@ static PyMethodDef uwsgi_cache_methods[] = {
{"cache_mul", py_uwsgi_cache_mul, METH_VARARGS, ""},
{"cache_div", py_uwsgi_cache_div, METH_VARARGS, ""},
{"cache_num", py_uwsgi_cache_num, METH_VARARGS, ""},
{"cache_keys", py_uwsgi_cache_keys, METH_VARARGS, ""},
{NULL, NULL},
};
@@ -3477,7 +3512,7 @@ clear:
return Py_None;
}
PyObject *py_snmp_decr_gauge(PyObject * self, PyObject * args) {
static PyObject *py_snmp_decr_gauge(PyObject * self, PyObject * args) {
uint8_t oid_num;
uint64_t oid_val = 1;
@@ -3510,7 +3545,7 @@ clear:
return Py_None;
}
PyObject *py_snmp_set_community(PyObject * self, PyObject * args) {
static PyObject *py_snmp_set_community(PyObject * self, PyObject * args) {
char *snmp_community;
+5 -1
View File
@@ -81,8 +81,9 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LOADER_CALLABLE 5
#define LOADER_STRING_CALLABLE 6
#define LOADER_MOUNT 7
#define LOADER_PECAN 8
#define LOADER_MAX 8
#define LOADER_MAX 9
typedef struct uwsgi_Input {
PyObject_HEAD
@@ -124,6 +125,8 @@ struct uwsgi_python {
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
char *pecan;
char *wsgi_config;
char *file_config;
char *paste;
@@ -218,6 +221,7 @@ PyObject *uwsgi_uwsgi_loader(void *);
PyObject *uwsgi_dyn_loader(void *);
PyObject *uwsgi_file_loader(void *);
PyObject *uwsgi_eval_loader(void *);
PyObject *uwsgi_pecan_loader(void *);
PyObject *uwsgi_paste_loader(void *);
PyObject *uwsgi_callable_loader(void *);
PyObject *uwsgi_string_callable_loader(void *);
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern PyTypeObject uwsgi_InputType;
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
@@ -29,7 +30,7 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->uh->modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh->modifier1 = 0;
wsgi_req->uh->modifier1 = python_plugin.modifier1;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
+3
View File
@@ -468,6 +468,9 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
if (wsgi_req->sendfile_fd >= 0) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
}
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
+3 -3
View File
@@ -61,7 +61,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *zero = NULL;
PyObject *zero2 = NULL;
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(head);
zero = PyUnicode_AsLatin1String(head);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http status string must be encodable in latin1");
}
@@ -135,7 +135,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero = PyUnicode_AsASCIIString(h_key);
zero = PyUnicode_AsLatin1String(h_key);
if (!zero) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
@@ -153,7 +153,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
zero2 = PyUnicode_AsASCIIString(h_value);
zero2 = PyUnicode_AsLatin1String(h_value);
if (!zero2) {
return PyErr_Format(PyExc_TypeError, "http header must be encodable in latin1");
}
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern PyTypeObject uwsgi_InputType;
/*
@@ -71,7 +72,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
}
if (wsgi_req->uh->modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
wsgi_req->uh->modifier1 = 0;
wsgi_req->uh->modifier1 = python_plugin.modifier1;
pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
if (pydictkey) {
if (PyString_Check(pydictkey)) {
+54 -15
View File
@@ -28,6 +28,11 @@ struct uwsgi_option uwsgi_rack_options[] = {
{"ruby-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
{"rb-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
#ifdef RUBY19
{"rb-lib", required_argument, 0, "add a directory to the ruby libdir search path", uwsgi_opt_add_string_list, &ur.libdir, 0},
{"ruby-lib", required_argument, 0, "add a directory to the ruby libdir search path", uwsgi_opt_add_string_list, &ur.libdir, 0},
#endif
{"rb-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"ruby-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"rbrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
@@ -48,12 +53,6 @@ struct uwsgi_option uwsgi_rack_options[] = {
{"rbshell", optional_argument, 0, "run a ruby/irb shell", uwsgi_opt_rbshell, NULL, 0},
{"rbshell-oneshot", no_argument, 0, "set ruby/irb shell (one shot)", uwsgi_opt_rbshell, NULL, 0},
#ifdef RUBY19
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
{"rbthreads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
{"ruby-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
#endif
{0, 0, 0, 0, 0, 0 ,0},
};
@@ -462,9 +461,9 @@ static void rack_hack_dollar_zero(VALUE name, ID id) {
int uwsgi_rack_init(){
#ifdef RUBY19
int argc = 2;
char *sargv[] = { (char *) "uwsgi", (char *) "-e0" };
char **argv = sargv;
int argc = 2;
char *sargv[] = { (char *) "uwsgi", (char *) "-e0" };
char **argv = sargv;
#endif
if (ur.gemset) {
@@ -473,13 +472,37 @@ int uwsgi_rack_init(){
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK
RUBY_INIT_STACK
#ifdef UWSGI_RUBY_HEROKU
uwsgi_log("*** Heroku system detected ***\n");
#endif
#ifdef RUBY_EXEC_PREFIX
if (!strcmp(RUBY_EXEC_PREFIX, "")) {
uwsgi_log("*** detected a ruby vm built with --enable-load-relative ***\n");
uwsgi_log("*** if you get errors about rubygems.rb, you can:\n");
uwsgi_log("*** 1) add a directory to the libdir search path using --ruby-libdir ***\n");
uwsgi_log("*** 2) force the RUBY_EXEC_PREFIX with --chdir ***\n");
#ifdef UWSGI_RUBY_LIBDIR
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_LIBDIR);
#endif
#ifdef UWSGI_RUBY_ARCHDIR
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_ARCHDIR);
#endif
}
#endif
ruby_init();
ruby_process_options(argc, argv);
struct uwsgi_string_list *usl = ur.libdir;
while(usl) {
ruby_incpush(usl->value);
uwsgi_log("[ruby-libdir] pushed %s\n", usl->value);
usl = usl->next;
}
ruby_options(argc, argv);
#else
ruby_init();
ruby_init_loadpath();
#endif
ruby_show_version();
ruby_script("uwsgi");
@@ -493,7 +516,6 @@ int uwsgi_rack_init(){
rb_gc_register_address(&ur.signals_protector);
rb_gc_register_address(&ur.rpc_protector);
uwsgi_rack_init_api();
return 0;
@@ -861,6 +883,10 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
rb_hash_aset(env, rb_str_new2("uwsgi.core"), INT2NUM(wsgi_req->async_id));
rb_hash_aset(env, rb_str_new2("uwsgi.version"), rb_str_new2(UWSGI_VERSION));
rb_hash_aset(env, rb_str_new2("uwsgi.node"), rb_str_new2(uwsgi.hostname));
// remove HTTP_CONTENT_LENGTH and HTTP_CONTENT_TYPE
rb_hash_delete(env, rb_str_new2("HTTP_CONTENT_LENGTH"));
rb_hash_delete(env, rb_str_new2("HTTP_CONTENT_TYPE"));
@@ -1240,11 +1266,22 @@ void uwsgi_ruby_init_thread(int core_id) {
}
void uwsgi_rack_postinit_apps(void) {
if (ur.rb_threads > 1) {
}
}
/*
If the ruby VM has rb_reserved_fd_p, we avoid closign the filedescriptor needed by
modern ruby (the Matz ones) releases.
*/
static void uwsgi_ruby_cleanup() {
int (*uptr_rb_reserved_fd_p)(int) = dlsym(RTLD_DEFAULT, "rb_reserved_fd_p");
if (!uptr_rb_reserved_fd_p) return;
int i;
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uptr_rb_reserved_fd_p(i)) {
uwsgi_add_safe_fd(i);
}
}
}
struct uwsgi_plugin rack_plugin = {
@@ -1287,5 +1324,7 @@ struct uwsgi_plugin rack_plugin = {
.exception_repr = uwsgi_ruby_exception_repr,
.exception_log = uwsgi_ruby_exception_log,
.backtrace = uwsgi_ruby_backtrace,
.master_cleanup = uwsgi_ruby_cleanup,
};
+1 -5
View File
@@ -41,9 +41,6 @@ struct uwsgi_rack {
VALUE dispatcher;
VALUE rb_uwsgi_io_class;
ID call;
VALUE fibers[200];
pthread_mutex_t gvl;
char *rbshell;
int rb_shell_oneshot;
@@ -57,8 +54,7 @@ struct uwsgi_rack {
char *gemset;
int rb_threads;
struct uwsgi_string_list *libdir;
};
void uwsgi_rack_init_api(void);
+14
View File
@@ -47,5 +47,19 @@ if has_shared == 'yes':
os.environ['LD_RUN_PATH'] = libpath
LIBS.append(os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip())
else:
rubylibdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['rubylibdir']\"").read().rstrip()
rubyarchdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['archdir']\"").read().rstrip()
# detect Heroku system
heroku = False
if rubylibdir.startswith('/tmp/build_'):
heroku = True
rubylibdir = '/app/' + '/'.join(rubylibdir.split('/')[3:])
if rubyarchdir.startswith('/tmp/build_'):
heroku = True
rubyarchdir = '/app/' + '/'.join(rubyarchdir.split('/')[3:])
if heroku:
CFLAGS.append('-DUWSGI_RUBY_HEROKU')
CFLAGS.append('-DUWSGI_RUBY_LIBDIR="\\"%s\\""' % rubylibdir)
CFLAGS.append('-DUWSGI_RUBY_ARCHDIR="\\"%s\\""' % rubyarchdir)
GCC_LIST.append("%s/%s" % (libpath, os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LIBRUBY_A']\"" % rbconfig).read().rstrip()))
+194
View File
@@ -0,0 +1,194 @@
#include <uwsgi.h>
#include <ruby.h>
/*
Author: Roberto De Ioris
Why a loop engine ???
The ruby 1.9/2.x threading model is very unique
First of all we cannot attach to already spawned pthread, for this reason
the "rbthreads" loop engine must create pthreads with rb_thread_create()
The second reason is for how the GVL is managed. We do not have
functions (like in CPython) to explicitely release and acquire it.
All happens via a function (rb_thread_call_without_gvl) calling the specified hook
whenever the code blocks.
Fortunately, thanks to the 1.9 async api, we can "patch" all of the server blocking parts
with 2 simple hooks: uwsgi.wait_write_hook and uwsgi.wait_read_hook
in addition to this we need to release the GVL in the accept() loop (but this is really easy)
*/
extern struct uwsgi_server uwsgi;
/*
for some strange reason, some version of ruby 1.9 does not expose this declaration...
*/
void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
rb_unblock_function_t *ubf, void *data2);
struct uwsgi_rbthreads {
int rbthreads;
int (*orig_wait_write_hook) (int, int);
int (*orig_wait_read_hook) (int, int);
} urbts;
static struct uwsgi_option rbthreads_options[] = {
{"rbthreads", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rb-threads", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rbthread", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{"rb-thread", no_argument, 0, "enable ruby native threads", uwsgi_opt_true, &urbts.rbthreads, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
// this structure is passed between threads
struct uwsgi_rbthread {
int queue;
int core_id;
struct wsgi_request *wsgi_req;
// return value
int ret;
// fd to monitor
int fd;
// non-blockign timeout
int timeout;
};
// this is called without the gvl
static void * uwsgi_rb_thread_accept(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = 0;
if (wsgi_req_accept(urbt->queue, urbt->wsgi_req)) {
urbt->ret = -1;
}
return NULL;
}
static VALUE uwsgi_rb_thread_core(void *arg) {
long core_id = (long) arg;
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
uwsgi_setup_thread_req(core_id, wsgi_req);
struct uwsgi_rbthread *urbt = uwsgi_malloc(sizeof(struct uwsgi_rbthread));
// initialize the main event queue to monitor sockets
urbt->queue = event_queue_init();
urbt->wsgi_req = wsgi_req;
uwsgi_add_sockets_to_queue(urbt->queue, (int)core_id);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(urbt->queue, uwsgi.signal_socket);
event_queue_add_fd_read(urbt->queue, uwsgi.my_signal_socket);
}
// ok we are ready, let's start managing requests and signals
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
wsgi_req_setup(wsgi_req, (int)core_id, NULL);
rb_thread_call_without_gvl(uwsgi_rb_thread_accept, urbt, NULL, NULL);
// accept failed ?
if (urbt->ret) continue;
if (wsgi_req_recv(urbt->queue, wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
uwsgi_close_request(wsgi_req);
}
return Qnil;
}
static void rbthread_noop0() {
}
static void rbthread_noop(int core_id) {
}
static void *rbthreads_wait_fd_write_do(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = urbts.orig_wait_write_hook(urbt->fd, urbt->timeout);
return NULL;
}
static int rbthreads_wait_fd_write(int fd, int timeout) {
struct uwsgi_rbthread urbt;
urbt.fd = fd;
urbt.timeout = timeout;
rb_thread_call_without_gvl(rbthreads_wait_fd_write_do, &urbt, NULL, NULL);
return urbt.ret;
}
static void *rbthreads_wait_fd_read_do(void *arg) {
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
urbt->ret = urbts.orig_wait_read_hook(urbt->fd, urbt->timeout);
return NULL;
}
static int rbthreads_wait_fd_read(int fd, int timeout) {
struct uwsgi_rbthread urbt;
urbt.fd = fd;
urbt.timeout = timeout;
rb_thread_call_without_gvl(rbthreads_wait_fd_read_do, &urbt, NULL, NULL);
return urbt.ret;
}
static void rbthreads_loop() {
struct uwsgi_plugin *rup = uwsgi_plugin_get("rack");
// disable init_thread warning
if (rup) {
rup->init_thread = rbthread_noop;
}
// override read/write nb hooks
urbts.orig_wait_write_hook = uwsgi.wait_write_hook;
urbts.orig_wait_read_hook = uwsgi.wait_read_hook;
uwsgi.wait_write_hook = rbthreads_wait_fd_write;
uwsgi.wait_read_hook = rbthreads_wait_fd_read;
int i;
for(i=1;i<uwsgi.threads;i++) {
long y = i;
rb_thread_create(uwsgi_rb_thread_core, (void *) y);
}
long y = 0;
uwsgi_rb_thread_core((void *) y);
// never here
}
static void rbthreads_setup() {
uwsgi_register_loop( (char *) "rbthreads", rbthreads_loop);
}
static int rbthreads_init() {
if (urbts.rbthreads) {
if (uwsgi.threads < 2) {
uwsgi_log("you have to spawn at least 2 threads for effective rbthreads support\n");
exit(1);
}
struct uwsgi_plugin *rup = uwsgi_plugin_get("rack");
// disable enable_threads warning
if (rup) {
rup->enable_threads = rbthread_noop0;
}
// set loop engine
uwsgi.loop = "rbthreads";
}
return 0;
}
struct uwsgi_plugin rbthreads_plugin = {
.name = "rbthreads",
.on_load = rbthreads_setup,
.init = rbthreads_init,
.options = rbthreads_options,
};
+31
View File
@@ -0,0 +1,31 @@
import os
NAME='rbthreads'
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = []
LIBS = []
GCC_LIST = ['rbthreads']
+2 -2
View File
@@ -2,7 +2,7 @@
#ifdef UWSGI_ROUTING
#ifdef __linux__
#if defined(__linux__) && !defined(__UCLIBC__)
#include <crypt.h>
#elif defined(__CYGWIN__)
#include <crypt.h>
@@ -34,7 +34,7 @@ static uint16_t htpasswd_check(char *filename, char *auth) {
if (clen > 13) cpwd[13] = 0;
#ifdef __linux__
#if defined(__linux__) && !defined(__UCLIBC__)
struct crypt_data cd;
cd.initialized = 0;
// we do as nginx here
+125
View File
@@ -0,0 +1,125 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
/*
by Unbit
syntax:
route = /^foobar1(.*)/ expires:filename=foo$1poo,value=30
route = /^foobar1(.*)/ expires:unix=${time[unix]},value=30
*/
struct uwsgi_router_expires_conf {
char *filename;
size_t filename_len;
char *unixt;
size_t unixt_len;
char *value;
size_t value_len;
};
static int uwsgi_routing_func_expires(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_expires_conf *urec = (struct uwsgi_router_expires_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t expires = 0;
if (urec->filename) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->filename, urec->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
struct stat st;
if (stat(ub->buf, &st)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
expires = st.st_mtime;
uwsgi_buffer_destroy(ub);
}
else if (urec->unixt) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->unixt, urec->unixt_len);
if (!ub) return UWSGI_ROUTE_BREAK;
expires = strtoul(ub->buf, NULL, 10);
uwsgi_buffer_destroy(ub);
}
if (urec->value) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->value, urec->value_len);
if (!ub) return UWSGI_ROUTE_BREAK;
expires += atoi(ub->buf);
uwsgi_buffer_destroy(ub);
}
char expires_str[7 + 2 + 31];
int len = uwsgi_http_date((time_t) expires, expires_str + 9);
if (!len) return UWSGI_ROUTE_BREAK;
memcpy(expires_str, "Expires: ", 9);
uwsgi_additional_header_add(wsgi_req, expires_str, 9 + len);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_expires(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_expires;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_expires_conf *urec = uwsgi_calloc(sizeof(struct uwsgi_router_expires_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"filename", &urec->filename,
"file", &urec->filename,
"unix", &urec->unixt,
"value", &urec->value,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (urec->filename) {
urec->filename_len = strlen(urec->filename);
}
if (urec->unixt) {
urec->unixt_len = strlen(urec->unixt);
}
if (urec->value) {
urec->value_len = strlen(urec->value);
}
ur->data2 = urec;
return 0;
}
static void router_expires_register() {
uwsgi_register_router("expires", uwsgi_router_expires);
}
struct uwsgi_plugin router_expires_plugin = {
.name = "router_expires",
.on_load = router_expires_register,
};
#else
struct uwsgi_plugin router_expires_plugin = {
.name = "router_expires",
};
#endif
+6
View File
@@ -0,0 +1,6 @@
NAME='router_expires'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['expires']
+17 -10
View File
@@ -9,14 +9,16 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
// mark a route request
wsgi_req->via = UWSGI_VIA_ROUTE;
// get the http address from the route
char *addr = ur->data;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_addr) return UWSGI_ROUTE_BREAK;
struct uwsgi_buffer *ub_url = NULL;
if (ur->data3_len) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
ub_url = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data3, ur->data3_len);
uwsgi_buffer_destroy(ub_addr);
if (!ub_url) return UWSGI_ROUTE_BREAK;
}
@@ -25,7 +27,8 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
if (!ub) {
if (ub_url) uwsgi_buffer_destroy(ub_url);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
@@ -37,7 +40,8 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
if (wsgi_req->proto_parser_remains > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
wsgi_req->proto_parser_remains = 0;
@@ -49,22 +53,25 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
uwsgi_buffer_destroy(ub);
uwsgi_log("unable to generate http request for %s\n", addr);
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_NEXT;
}
}
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->status = 202;
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_BREAK;
}
}
if (uwsgi_proxy_nb(wsgi_req, addr, ub, remains, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_log("error routing request to http server %s\n", addr);
if (uwsgi_proxy_nb(wsgi_req, ub_addr->buf, ub, remains, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
uwsgi_log("error routing request to http server %s\n", ub_addr->buf);
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_BREAK;
+165
View File
@@ -94,6 +94,142 @@ end:
return ret;
}
int uwsgi_routing_func_sendfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct stat st;
int ret = UWSGI_ROUTE_BREAK;
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
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, urfc->filename, urfc->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
int fd = open(ub->buf, O_RDONLY);
if (fd < 0) {
if (ur->custom)
ret = UWSGI_ROUTE_NEXT;
goto end;
}
if (fstat(fd, &st)) {
goto end2;
}
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
if (!ub_s) goto end2;
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
uwsgi_buffer_destroy(ub_s);
goto end2;
}
uwsgi_buffer_destroy(ub_s);
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
if (urfc->mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
if (!wsgi_req->headers_sent) {
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
}
if (!uwsgi_simple_sendfile(wsgi_req, fd, 0, st.st_size)) {
wsgi_req->via = UWSGI_VIA_SENDFILE;
wsgi_req->response_size += st.st_size;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct stat st;
int ret = UWSGI_ROUTE_BREAK;
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
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, urfc->filename, urfc->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
int fd = open(ub->buf, O_RDONLY);
if (fd < 0) {
if (ur->custom)
ret = UWSGI_ROUTE_NEXT;
goto end;
}
if (fstat(fd, &st)) {
goto end2;
}
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
if (!ub_s) goto end2;
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
uwsgi_buffer_destroy(ub_s);
goto end2;
}
uwsgi_buffer_destroy(ub_s);
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
if (urfc->mime) {
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
}
else {
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
}
if (!wsgi_req->headers_sent) {
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
}
if (wsgi_req->socket->can_offload) {
if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, st.st_size)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += st.st_size;
// the fd will be closed by the offload engine
goto end;
}
}
if (!uwsgi_simple_sendfile(wsgi_req, fd, 0, st.st_size)) {
wsgi_req->via = UWSGI_VIA_SENDFILE;
wsgi_req->response_size += st.st_size;
}
end2:
close(fd);
end:
uwsgi_buffer_destroy(ub);
return ret;
}
static int uwsgi_router_static(struct uwsgi_route *ur, char *args) {
@@ -143,12 +279,41 @@ static int uwsgi_router_file_next(struct uwsgi_route *ur, char *args) {
return uwsgi_router_file(ur, args);
}
static int uwsgi_router_sendfile(struct uwsgi_route *ur, char *args) {
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_sendfile;
return ret;
}
static int uwsgi_router_sendfile_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_sendfile;
return ret;
}
static int uwsgi_router_fastfile(struct uwsgi_route *ur, char *args) {
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_fastfile;
return ret;
}
static int uwsgi_router_fastfile_next(struct uwsgi_route *ur, char *args) {
ur->custom = 1;
int ret = uwsgi_router_file(ur, args);
ur->func = uwsgi_routing_func_fastfile;
return ret;
}
static void router_static_register(void) {
uwsgi_register_router("static", uwsgi_router_static);
uwsgi_register_router("file", uwsgi_router_file);
uwsgi_register_router("file-next", uwsgi_router_file_next);
uwsgi_register_router("sendfile", uwsgi_router_sendfile);
uwsgi_register_router("sendfile-next", uwsgi_router_sendfile_next);
uwsgi_register_router("fastfile", uwsgi_router_fastfile);
uwsgi_register_router("fastfile-next", uwsgi_router_fastfile_next);
}
struct uwsgi_plugin router_static_plugin = {
+221 -38
View File
@@ -1,4 +1,27 @@
/*
* Copyright (C) 2013 Unbit S.a.s. <info@unbit.it>
* Copyright (C) 2013 Guido Berhoerster <guido+uwsgi@berhoerster.name>
*
* 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.
*
*/
#include <uwsgi.h>
#include <locale.h>
#include <iconv.h>
#include <langinfo.h>
#ifndef UWSGI_XML_LIBXML2
#error you need a libxml2-enabled build of uWSGI to use the router_xmldir plugin
@@ -6,67 +29,227 @@
#include <libxml/tree.h>
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
static struct router_xmldir_conf {
char *codeset;
} conf;
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;
void *xrealloc(void *ptr, size_t size) {
void *tmp;
struct dirent **tasklist;
int n = scandir(ub->buf, &tasklist, 0, versionsort);
uwsgi_buffer_destroy(ub);
if (n < 0) return UWSGI_ROUTE_BREAK;
int i;
xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
xmlNode *rtree = xmlNewNode(NULL, BAD_CAST "tree");
xmlDocSetRootElement(rdoc, rtree);
tmp = realloc(ptr, size);
if (tmp == NULL) {
uwsgi_error("realloc()");
exit(1);
}
for(i=0;i<n;i++) {
if (tasklist[i]->d_name[0] == '.') goto next;
switch (tasklist[i]->d_type) {
case DT_DIR:
xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST tasklist[i]->d_name);
return (tmp);
}
char *to_utf8(char *codeset, char *in) {
size_t buf_size;
size_t buf_offset;
size_t in_remaining;
size_t buf_remaining;
size_t ret;
char *buf = NULL;
char *buf_ptr;
char *in_ptr = in;
static iconv_t cd = (iconv_t)-1;
/* UTF-8 encoded Unicode replacement char (U+FFFD) */
const char repl[] = "\xef\xbf\xbd";
if (cd == (iconv_t)-1) {
if ((cd = iconv_open("UTF-8", codeset)) == (iconv_t)-1) {
uwsgi_error("iconv_open");
return (NULL);
}
}
in_remaining = strlen(in) + 1;
buf_size = buf_remaining = in_remaining;
buf = buf_ptr = uwsgi_malloc(buf_size);
while (in_remaining > (size_t)0) {
ret = iconv(cd, &in_ptr, &in_remaining, &buf_ptr,
&buf_remaining);
if (ret == (size_t)-1) {
switch (errno) {
case EINVAL:
/* truncate */
in_remaining = 0;
*buf_ptr = '\0';
break;
case DT_LNK:
xmlNewTextChild(rtree, NULL, BAD_CAST "link", BAD_CAST tasklist[i]->d_name);
case EILSEQ:
/*
* insert a replacement character for each
* illegal sequence
*/
in_ptr++;
in_remaining--;
if (buf_remaining < sizeof (repl)) {
buf_size += in_remaining +
sizeof (repl) - 1;
buf_remaining += in_remaining +
sizeof (repl) - 1;
buf_offset = buf_ptr - buf;
buf = xrealloc(buf, buf_size);
buf_ptr = buf + buf_offset;
}
strcat(buf_ptr, repl);
buf_ptr += sizeof (repl) - 1;
buf_remaining -= sizeof (repl) - 1;
break;
case DT_REG:
xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST tasklist[i]->d_name);
case E2BIG:
buf_size += in_remaining;
buf_remaining += in_remaining;
buf_offset = buf_ptr - buf;
buf = xrealloc(buf, buf_size);
buf_ptr = buf + buf_offset;
break;
default:
xmlNewTextChild(rtree, NULL, BAD_CAST "unknown", BAD_CAST tasklist[i]->d_name);
break;
uwsgi_error("iconv");
free(buf);
return (NULL);
}
}
next:
free(tasklist[i]);
}
}
free(tasklist);
buf = xrealloc(buf, strlen(buf) + 1);
return (buf);
}
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
char **subject;
uint16_t *subject_len;
char *dirname;
struct uwsgi_buffer *ub;
char *name = NULL;
char *path = NULL;
int i;
int n;
struct dirent **tasklist;
xmlDoc *rdoc;
xmlNode *rtree;
xmlNodePtr entrynode;
char *path_info = NULL;
struct stat sb;
size_t sizebuf_len;
char *sizebuf;
char timebuf[20];
int xlen = 0;
subject = (char **) (((char *)(wsgi_req))+ur->subject);
subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len,
ur->data, ur->data_len);
if (!ub) {
uwsgi_500(wsgi_req);
return UWSGI_ROUTE_BREAK;
}
dirname = ub->buf;
path_info = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len,
"", 1);
n = scandir(dirname, &tasklist, 0, alphasort);
if (n < 0) {
uwsgi_404(wsgi_req);
goto out;
}
rdoc = xmlNewDoc(BAD_CAST "1.0");
rtree = xmlNewNode(NULL, BAD_CAST "index");
xmlNewProp(rtree, BAD_CAST "path", BAD_CAST path_info);
xmlDocSetRootElement(rdoc, rtree);
for(i = 0; i < n; i++) {
if ((strcmp(tasklist[i]->d_name, ".") == 0) ||
(strcmp(tasklist[i]->d_name, "..") == 0)) {
goto next_entry;
}
path = uwsgi_concat3(dirname, "/", tasklist[i]->d_name);
if (lstat(path, &sb) == -1) {
goto next_entry;
}
name = to_utf8(conf.codeset, tasklist[i]->d_name);
if (name == NULL) {
goto next_entry;
}
if (S_ISDIR(sb.st_mode)) {
entrynode = xmlNewTextChild(rtree, NULL,
BAD_CAST "directory", BAD_CAST name);
} else if (S_ISREG(sb.st_mode)) {
entrynode = xmlNewTextChild(rtree, NULL,
BAD_CAST "file", BAD_CAST name);
} else {
/* skip everything but directories and regular files */
goto next_entry;
}
sizebuf_len = snprintf(NULL, 0, "%jd", (intmax_t) sb.st_size);
sizebuf = uwsgi_malloc(sizebuf_len + 1);
snprintf(sizebuf, sizebuf_len + 1, "%jd", (intmax_t) sb.st_size);
xmlNewProp(entrynode, BAD_CAST "size", BAD_CAST sizebuf);
free(sizebuf);
strftime(timebuf, sizeof (timebuf), "%Y-%m-%dT%H:%M:%S",
localtime(&sb.st_mtime));
xmlNewProp(entrynode, BAD_CAST "mtime", BAD_CAST timebuf);
next_entry:
free(path);
path = NULL;
free(tasklist[i]);
free(name);
name = NULL;
}
free(tasklist);
xmlChar *xmlbuf;
int xlen = 0;
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
xmlFreeDoc(rdoc);
xmlFree(xmlbuf);
out:
uwsgi_buffer_destroy(ub);
free(path_info);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xmldir(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
ur->func = uwsgi_routing_func_xmldir;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static void router_xmldir_register() {
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
static void router_xmldir_register(void) {
char *codeset;
uwsgi_register_router("xmldir", uwsgi_router_xmldir);
setlocale(LC_ALL, "");
if ((codeset = nl_langinfo(CODESET)) == '\0') {
codeset = "ASCII";
}
conf.codeset = uwsgi_str(codeset);
if (conf.codeset == NULL) {
uwsgi_error("strdup()");
exit(1);
}
}
struct uwsgi_plugin router_xmldir_plugin = {
+65
View File
@@ -399,6 +399,61 @@ end:
return ret;
}
static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
// this is the list of args
char *argv[UMAX8];
// this is the size of each argument
uint16_t argvs[UMAX8];
// this is a placeholder for tmp uwsgi_buffers
struct uwsgi_buffer *ubs[UMAX8];
char **r_argv = (char **) ur->data2;
uint16_t *r_argvs = (uint16_t *) ur->data3;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t i;
for(i=0;i<ur->custom;i++) {
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
if (!ubs[i]) goto end;
argv[i] = ubs[i]->buf;
argvs[i] = ubs[i]->pos;
}
// ok we now need to check it it is a local call or a remote one
char *func = uwsgi_str(ur->data);
char *remote = NULL;
char *at = strchr(func, '@');
if (at) {
*at = 0;
remote = at+1;
}
uint16_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
ret = UWSGI_ROUTE_BREAK;
if (size == 0) goto end;
if (!uwsgi_req_append(wsgi_req, ur->data4, ur->data4_len, response, size)) {
free(response);
goto end;
}
free(response);
ret = UWSGI_ROUTE_NEXT;
end:
for(i=0;i<ur->custom;i++) {
if (ubs[i] != NULL) {
uwsgi_buffer_destroy(ubs[i]);
}
}
return ret;
}
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
@@ -497,6 +552,7 @@ end:
ur->custom = the number of arguments
ur->data2 = the pointer to the args
ur->data3 = the pointer to the args sizes
ur->data4 = func specific
*/
static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
ur->custom = 0;
@@ -552,6 +608,14 @@ static int uwsgi_router_rpc_raw(struct uwsgi_route *ur, char *args) {
return uwsgi_router_rpc_base(ur, args);
}
static int uwsgi_router_rpc_var(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_rpc_var;
char *space = strchr(args, ' ');
if (!space) return -1;
ur->data4 = args;
ur->data4_len = space - args;
return uwsgi_router_rpc_base(ur, space+1);
}
static void router_rpc_register() {
uwsgi_register_router("call", uwsgi_router_rpc);
@@ -560,6 +624,7 @@ static void router_rpc_register() {
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcraw", uwsgi_router_rpc_raw);
uwsgi_register_router("rpcvar", uwsgi_router_rpc_var);
}
#endif
+1 -1
View File
@@ -73,7 +73,7 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
// drop newline
if (message[len-1] == '\n') len--;
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r(&current_time, ctime_storage, 26);
#else
ctime_r(&current_time, ctime_storage);
+90
View File
@@ -0,0 +1,90 @@
#include <jvm.h>
/*
Servlet 2.5 JVM handler
*/
#define UWSGI_JVM_REQUEST_HANDLER_SERVLET 2
extern struct uwsgi_jvm ujvm;
struct uwsgi_servlet {
} uservlet;
static struct uwsgi_option uwsgi_servlet_options[] = {
{0, 0, 0, 0},
};
// the request handler
static int uwsgi_servlet_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
static int uwsgi_servlet_setup() {
uwsgi_log("loading servlet environment...\n");
jclass servlet = uwsgi_jvm_class("org/apache/jasper/servlet/JspServlet");
uwsgi_log("jclass = %p\n", servlet);
jmethodID mid = uwsgi_jvm_get_method_id(servlet, "<init>", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
jobject instance = (*ujvm_env)->NewObject(ujvm_env, servlet, mid);
if (uwsgi_jvm_exception() || !instance) exit(1);
uwsgi_log("done\n");
jclass uwsgi_servlet_config = uwsgi_jvm_class("uWSGIServletConfig");
mid = uwsgi_jvm_get_method_id(uwsgi_servlet_config, "<init>", "()V");
jobject config = (*ujvm_env)->NewObject(ujvm_env, uwsgi_servlet_config, mid);
mid = uwsgi_jvm_get_method_id(servlet, "init", "(Ljavax/servlet/ServletConfig;)V");
uwsgi_jvm_call_object(instance, mid, config );
uwsgi_log("SERVLET initialized\n");
jclass uwsgi_request = uwsgi_jvm_class("uWSGIServletRequest");
jclass uwsgi_response = uwsgi_jvm_class("uWSGIServletResponse");
uwsgi_log("%p %p\n", uwsgi_request, uwsgi_response);
mid = uwsgi_jvm_get_method_id(uwsgi_request , "<init>", "()V");
uwsgi_jvm_exception();
jobject request = (*ujvm_env)->NewObject(ujvm_env, uwsgi_request, mid);
mid = uwsgi_jvm_get_method_id(uwsgi_response , "<init>", "()V");
uwsgi_jvm_exception();
jobject response = (*ujvm_env)->NewObject(ujvm_env, uwsgi_response, mid);
uwsgi_log("%p %p\n", request, response);
mid = uwsgi_jvm_get_method_id(servlet, "service", "(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V");
if (uwsgi_jvm_exception() || !mid) exit(1);
uwsgi_jvm_call_object(instance, mid, request, response);
uwsgi_log("done\n");
mid = uwsgi_jvm_get_method_id(uwsgi_response, "flushBuffer", "()V");
if (uwsgi_jvm_exception() || !mid) exit(1);
uwsgi_jvm_call_object(response, mid);
uwsgi_log("servlet loaded\n");
return 0;
}
static int uwsgi_servlet_init() {
if (uwsgi_jvm_register_request_handler(UWSGI_JVM_REQUEST_HANDLER_SERVLET, uwsgi_servlet_setup, uwsgi_servlet_request)) {
exit(1);
}
return 0;
}
struct uwsgi_plugin servlet_plugin = {
.name = "servlet",
.options = uwsgi_servlet_options,
.init = uwsgi_servlet_init,
};
+636
View File
@@ -0,0 +1,636 @@
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
import java.net.*;
/*
uWSGI Servlet 2.5 Container implementation
*/
class uWSGIServletContext implements ServletContext {
public Object getAttribute(String name) {
System.out.println("uWSGIServletContext getAttribute " + name);
return null;
}
public ServletContext getContext(String uripath) {
return this;
}
public String getContextPath() {
System.out.println("uWSGIServletContext getContextPath");
return "/root/uwsgi";
}
public int getMajorVersion() {
return 2;
}
public int getMinorVersion() {
return 5;
}
public String getMimeType(java.lang.String file) {
System.out.println("uWSGIServletContext getMimeType " + file);
return "text/plain";
}
public java.util.Set getResourcePaths(java.lang.String path) {
System.out.println("uWSGIServletContext getResourcePaths " + path);
return null;
}
public java.net.URL getResource(java.lang.String path) {
System.out.println("uWSGIServletContext getResource " + path);
try {
File myFile;
if (path.equals("/WEB-INF/web.xml")) {
myFile = new File("/root/uwsgi/WEB-INF/web.xml");
}
else {
myFile = new File("/root/uwsgi/foo.jsp");
}
return myFile.toURI().toURL();
}
catch(MalformedURLException e) {
System.out.println("uWSGIServletContext ERROR !!!");
return null;
}
}
public RequestDispatcher getNamedDispatcher(java.lang.String name) {
System.out.println("uWSGIServletContext getNamedDispatcher " + name);
return null;
}
public java.io.InputStream getResourceAsStream(java.lang.String path) {
System.out.println("uWSGIServletContext getResourceAsStream " + path);
try {
FileInputStream fis = new FileInputStream(path);
return fis;
}
catch(FileNotFoundException e) {
return null;
}
}
public RequestDispatcher getRequestDispatcher(java.lang.String path) {
System.out.println("uWSGIServletContext getRequestDispatcher " + path);
return null;
}
public Servlet getServlet(java.lang.String name) {
System.out.println("uWSGIServletContext getServlet");
return null;
}
public java.util.Enumeration getServletNames() {
return null;
}
public java.util.Enumeration getServlets() {
return null;
}
public void log(java.lang.String message, java.lang.Throwable throwable) {
System.out.println("LOG " + message);
}
public void log(java.lang.Exception exception, java.lang.String msg) {
System.out.println("LOG " + msg);
}
public void log(java.lang.String msg) {
System.out.println("LOG " + msg);
}
public String getRealPath(java.lang.String path) {
System.out.println("uWSGIServletContext getRealPath " + path);
return path;
}
public String getServerInfo() {
return "uWSGI";
}
public String getInitParameter(java.lang.String name) {
return null;
}
public Enumeration getInitParameterNames() {
System.out.println("uWSGIServletContext getInitParameterNames()");
return null;
}
public java.util.Enumeration getAttributeNames() {
System.out.println("uWSGIServletContext getAttributeNames");
return null;
}
public String getServletContextName() {
System.out.println("uWSGIServletContext getServletContextName");
return "/jsp";
}
public void removeAttribute(java.lang.String name) {
}
public void setAttribute(java.lang.String name, java.lang.Object object) {
System.out.println("uWSGIServletContext setAttribute " + name);
}
}
class uWSGIServletConfig implements ServletConfig {
uWSGIServletContext context;
public uWSGIServletConfig() {
super();
System.out.println("uWSGIServletConfig allocation");
this.context = new uWSGIServletContext();
}
public String getInitParameter(String name) {
System.out.println("ServletConfig getInitParameter " + name);
return null;
}
public Enumeration<java.lang.String> getInitParameterNames() {
System.out.println("ServletConfig getInitParameterNames");
Vector pNames = new Vector();
return pNames.elements();
}
public ServletContext getServletContext() {
System.out.println("ServletConfig getServletContext");
return this.context;
}
public String getServletName() {
return "/jsp";
}
}
class uWSGIServletOutputStream extends ServletOutputStream {
// append a byte to the writing buffer
public void write(int n) {
System.out.print((char)n);
}
// send them to the client
public void flush() {
System.out.println("FLUSHING");
}
}
class uWSGIServletSession implements HttpSession {
HashMap<String,Object> hm;
public uWSGIServletSession() {
this.hm = new HashMap<String,Object>();
}
public String getId() {
return "uwsgi";
}
public int getMaxInactiveInterval() {
return 3600;
}
public long getLastAccessedTime() {
return 1373874485;
}
public long getCreationTime() {
return 1373874485;
}
public void setMaxInactiveInterval(int interval) {
System.out.println("SESSION INTERVAL " + interval );
}
public HttpSessionContext getSessionContext() {
return null;
}
public ServletContext getServletContext() {
return null;
}
public String[] getValueNames() {
return (String[]) this.hm.keySet().toArray();
}
public void invalidate() {
}
public void removeAttribute(String name) {
this.hm.remove(name);
}
public void removeValue(String name) {
this.hm.remove(name);
}
public void putValue(String name, Object value) {
this.hm.put(name, value);
}
public void setAttribute(String name, Object value) {
this.hm.put(name, value);
}
public Enumeration getAttributeNames() {
return Collections.enumeration(this.hm.keySet());
}
public boolean isNew() {
return false;
}
public Object getAttribute(String name) {
return this.hm.get(name);
}
public Object getValue(String name) {
return this.hm.get(name);
}
}
class uWSGIServletRequest implements HttpServletRequest {
uWSGIServletSession session = null;
public Object getAttribute(String name) {
System.out.println("getAttribute " + name);
return null;
}
public Enumeration getAttributeNames() {
return null;
}
public String getCharacterEncoding() {
return "utf-8";
}
public void setCharacterEncoding(String env) {
}
public String getParameter(String name) {
System.out.println("getParameter " + name);
return null;
}
public Enumeration getParameterNames() {
return null;
}
public String[] getParameterValues(String name) {
return null;
}
public int getContentLength() {
return 0;
}
public String getContentType() {
return "text/plain";
}
public ServletInputStream getInputStream() {
return null;
}
public Map getParameterMap() {
return null;
}
public String getProtocol() {
return "HTTP/1.0";
}
public String getScheme() {
System.out.println("getScheme");
return "http";
}
public String getServerName() {
return "quantal64.local";
}
public int getServerPort() {
return 80;
}
public BufferedReader getReader() {
return null;
}
public String getRemoteAddr() {
return "127.0.0.1";
}
public String getRemoteHost() {
return "localhost";
}
public void setAttribute(String name, Object o) {
}
public void removeAttribute(String name) {
}
public Locale getLocale() {
return null;
}
public Enumeration getLocales() {
return null;
}
public boolean isSecure() {
return false;
}
public RequestDispatcher getRequestDispatcher(String path) {
System.out.println("RequestDispatcher getRequestDispatcher " + path);
return null;
}
public String getRealPath(String path) {
System.out.println("getRealPath " + path);
return "/tmp";
}
public int getRemotePort() {
return 1717;
}
public String getLocalName() {
return "localhost";
}
public String getLocalAddr() {
return "127.0.0.1";
}
public int getLocalPort() {
return 80;
}
public String getAuthType() {
return null;
}
public Cookie[] getCookies() {
return null;
}
public long getDateHeader(String name) {
return -1;
}
public String getHeader(String name) {
System.out.println("getHeader " + name);
return null;
}
public Enumeration getHeaders(String name) {
System.out.println("getHeaders " + name);
return null;
}
public Enumeration getHeaderNames() {
return null;
}
public int getIntHeader(String name) {
return -1;
}
public String getMethod() {
System.out.println("getMethod");
return "GET";
}
public String getPathInfo() {
System.out.println("getPathInfo");
return "";
}
public String getPathTranslated() {
System.out.println("getPathTranslated");
return null;
}
public String getContextPath() {
System.out.println("getContextPath");
return "";
}
public String getQueryString() {
return "r=17";
}
public String getRemoteUser() {
return "kratos";
}
public boolean isUserInRole(String role) {
return false;
}
public java.security.Principal getUserPrincipal() {
return null;
}
public String getRequestedSessionId() {
System.out.println("getRequestedSessionId !!!");
return null;
}
public String getRequestURI() {
System.out.println("getRequestURI");
return "/foo.jsp";
}
public StringBuffer getRequestURL() {
System.out.println("getRequestURL");
//return "http://quantal64.local/roberta?r=17";
return null;
}
public String getServletPath() {
System.out.println("getServletPath");
return "/root/uwsgi/foo.jsp";
}
public HttpSession getSession(boolean create) {
System.out.println(" getSession !!!");
return null;
}
public HttpSession getSession() {
System.out.println("!!! getSession !!!");
if (this.session == null) {
this.session = new uWSGIServletSession();
}
return this.session;
}
public boolean isRequestedSessionIdFromURL() {
return false;
}
public boolean isRequestedSessionIdFromUrl() {
return false;
}
public boolean isRequestedSessionIdFromCookie() {
return false;
}
public boolean isRequestedSessionIdValid() {
return false;
}
}
class uWSGIServletResponse implements HttpServletResponse {
PrintWriter pw;
public uWSGIServletResponse() {
this.pw = new PrintWriter(new uWSGIServletOutputStream());
}
public void addCookie(Cookie cookie) {
}
public boolean containsHeader(String name) {
return false;
}
public String encodeURL(String url) {
System.out.println("URL = " + url);
return url;
}
public String encodeRedirectURL(String url) {
return url;
}
public String encodeUrl(String url) {
return url;
}
public String encodeRedirectUrl(String url) {
return url;
}
public void sendError(int sc, String msg) {
}
public void sendError(int sc) {
}
public void sendRedirect(String location) {
}
public void setDateHeader(String name, long date) {
}
public void addDateHeader(String name, long date) {
}
public void setHeader(String name, String value) {
System.out.println("SET_HEADER " + name + " = " + value);
}
public void addHeader(String name, String value) {
System.out.println("ADD_HEADER " + name + " = " + value);
}
public void setIntHeader(String name, int value) {
}
public void addIntHeader(String name, int value) {
}
public void setStatus(int sc) {
System.out.println("STATUS " + sc);
}
public void setStatus(int sc, String sm) {
System.out.println("STATUS " + sc + " " + sm);
}
public void flushBuffer() {
System.out.println("flushBuffer");
this.pw.flush();
}
public void resetBuffer() {
System.out.println("resetBuffer");
}
public boolean isCommitted() {
return true;
}
public void reset() {
}
public void setLocale(Locale loc) {
}
public Locale getLocale() {
return null;
}
public int getBufferSize() {
return 4096;
}
public void setBufferSize(int size) {
}
public void setContentType(String type) {
System.out.println("setContentType " + type);
}
public void setContentLength(int len) {
}
public void setCharacterEncoding(String charset) {
}
public PrintWriter getWriter() {
System.out.println("getWriter()");
return this.pw;
}
public ServletOutputStream getOutputStream() {
System.out.println("getOutputStream()");
return null;
}
public String getContentType() {
return "text/plain";
}
public String getCharacterEncoding() {
return "utf-8";
}
}
+19
View File
@@ -0,0 +1,19 @@
import os
import shutil
jvm_path = 'plugins/jvm'
up = {}
try:
execfile('%s/uwsgiplugin.py' % jvm_path, up)
except:
f = open('%s/uwsgiplugin.py' % jvm_path)
exec(f.read(), up)
f.close()
NAME='servlet'
CFLAGS = up['CFLAGS']
CFLAGS.append('-I%s' % jvm_path)
LDFLAGS = []
LIBS = []
GCC_LIST = ['servlet_plugin']
+7
View File
@@ -2,6 +2,12 @@
#include <uwsgi.h>
#ifdef __UCLIBC__
struct uwsgi_plugin ugreen_plugin = {
.name = "ugreen",
};
#else
#ifdef __APPLE__
#define _XOPEN_SOURCE
#endif
@@ -130,3 +136,4 @@ struct uwsgi_plugin ugreen_plugin = {
.init = u_green_init,
.options = ugreen_options,
};
#endif
+1 -1
View File
@@ -3,7 +3,7 @@ NAME='v8'
CFLAGS = ['-Wno-deprecated-declarations']
LDFLAGS = []
LIBS = ['-lv8']
LIBS = ['-lstdc++', '-lv8']
engine = os.environ.get('UWSGICONFIG_V8_ENGINE', '')
if engine == 'teajs':
CFLAGS.append('-DUWSGI_V8_TEAJS -fexceptions')
+3
View File
@@ -95,6 +95,9 @@ class uWSGIDistribution(Distribution):
self.cmdclass['install_lib'] = uWSGIInstallLib
self.cmdclass['build_ext'] = uWSGIBuilder
def is_pure(self):
return False
setup(name='uWSGI',
version=uc.uwsgi_version,
View File
View File
View File
+17 -17
View File
@@ -3,11 +3,11 @@ import uwsgi
import time
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
@@ -20,19 +20,19 @@ def application(env, sr):
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
@@ -43,13 +43,13 @@ def application(env, sr):
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
while True:
msg = uwsgi.websocket_recv()

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