Compare commits

..
152 Commits
Author SHA1 Message Date
Unbit 7f99855527 1.9.18.1 2013-10-11 14:27:26 +02:00
Unbit 8c29178f81 fixed kFreeBSD support 2013-10-11 16:24:46 +02:00
Unbit ed71000033 fixed FreeBSD compilation 2013-10-11 09:44:50 +02:00
Unbit 20860ed069 fixed python3 build 2013-10-11 14:07:02 +02:00
Unbit 2e62f13917 fixed mono options parsing 2013-10-11 05:59:20 +02:00
Unbit 1b2a83ce70 updated gemspec for 1.9.18 2013-10-11 05:51:19 +02:00
Unbit 113ec5ae9e added minimal profiles 2013-10-11 05:05:07 +02:00
root 68e81828d1 finally fixed the problem with python and arm (raspberrypi/sheevaplug) 2013-10-11 02:50:40 +00:00
Unbit 543790dc83 auto-modifier1 only if modifier1 is 0 2013-10-10 09:29:28 +02:00
unbit be24060578 Merge pull request #414 from arkaitzj/master
Still need to loop again when EAGAIN after a read triggered by an event, Fixes #363
2013-10-09 20:14:05 -07:00
Arkaitz Jimenez bdedc1c94c Still need to loop again when EAGAIN after a read triggered by an event 2013-10-10 00:12:57 +02:00
unbit e2454aa898 Merge pull request #413 from prymitive/backlog2
fixed backlog2 example plugin
2013-10-08 18:55:10 -07:00
Łukasz Mierzwa dfa4834be3 fixed backlog2 example plugin 2013-10-08 23:16:03 +02:00
Unbit f204249110 better fallback for non-zero modifiers 2013-10-07 17:50:43 +02:00
Unbit f4c25a6cd1 prepare for 1.9.18 release 2013-10-07 13:23:05 +02:00
Unbit fbfbacce14 fixed attach.py 2013-10-07 13:03:50 +02:00
Unbit a0eed32b3f move uWSGI 1.9 to GPL2 + linking exception 2013-10-07 12:19:33 +02:00
Unbit 9fe9fe1bb6 fixed data:// scheme 2013-10-07 11:37:52 +02:00
Unbit 192312e3ea avoid crashing on non-conformant PSGI response headers 2013-10-07 10:21:39 +02:00
Unbit ee46fe6ba6 Merge branch 'master' of github.com:unbit/uwsgi 2013-10-07 10:11:59 +02:00
Unbit 58abd07a88 support remote sources for perl scripts 2013-10-07 10:11:50 +02:00
Unbit c246a6008e correctly returns http error on connect 2013-10-07 10:11:23 +02:00
Unbit 706f1b59c3 make clang happy 2013-10-07 09:52:32 +02:00
Unbit ddbc8920f7 use uwsgi_open_and_read for perl files 2013-10-07 09:50:56 +02:00
Roberto De Ioris 7e3bf6868e fixed perl autoreload when under clang 2013-10-06 11:01:12 +02:00
Unbit 4c7ecef577 added perl auto reloader 2013-10-06 10:52:27 +02:00
Unbit e3da0aaad4 automatically returns the default app even if the modifier is wrong 2013-10-06 09:26:08 +02:00
Unbit 99e576e40c support pty on NetBSD 2013-10-06 07:04:12 +02:00
Unbit 7604ce3441 --wsgi-accept-buffers 2013-10-05 12:34:57 +02:00
Unbit a0082b5b98 accepting buffer is an option: --wsgi-accept-buffer 2013-10-05 12:32:49 +02:00
Unbit c90c639348 --wsgi-strict disable string/bytes optimizations too 2013-10-05 09:09:53 +02:00
Unbit 2e188dc25a fixed big endian support for uwsgi protocol 2013-10-05 07:15:36 +02:00
Unbit 312d21cb3f added 'before' variants for vassals templating 2013-10-05 07:07:48 +02:00
unbit 4ee138be7c Merge pull request #411 from thekad/master
updating so jvm plugin can compile in arm
2013-10-04 21:22:01 -07:00
Jorge Gallegos 299aef99b3 updating so jvm plugin can compile in arm
This *should* work for all arm versions so far and still works for i386/x86_64
2013-10-04 16:39:54 -07:00
Unbit 06953e4547 fixed uwsgiconfig.py for embed_config 2013-10-04 17:13:10 +02:00
Unbit 7565ee8740 fixed a memleak spotted by cppcheck 2013-10-04 12:29:16 +02:00
Unbit 10377f02a3 run the autoreloader even in non-apps mode when non-lazy 2013-10-04 06:22:06 +02:00
Unbit a41e6e2c61 added --emperor-cap 2013-10-04 06:11:29 +02:00
Unbit 6b2b909d33 apply PR_SET_PDEATHSIG to vassals on linux 2013-10-03 19:46:33 +02:00
Unbit 70cd18bffb added --unshare2 2013-10-03 19:43:43 +02:00
Unbit d6be4bcad9 added --mountpoint-check 2013-10-03 14:42:52 +02:00
Unbit 85530b5d8e added --exit 2013-10-03 11:38:51 +02:00
Unbit e3848e84d3 expose more clone() flags 2013-10-03 10:42:55 +02:00
Unbit 4ec9312b10 pivot_root improvements 2013-10-02 16:52:14 +02:00
Unbit aedf3b2455 reindented core/utils.c 2013-10-02 13:58:18 +02:00
Unbit 2210ec7f71 added call scheme 2013-10-02 10:58:27 +02:00
Unbit a9bee41707 added UWSGI_ADDITIONAL_SOURCES env var and additional_sources buildconf option 2013-10-02 10:52:53 +02:00
Unbit 3adbfd100f allow overriding schemes 2013-10-02 10:39:41 +02:00
Unbit 8d8de4b8da pluginized uwsgi_open_and_read 2013-10-02 10:37:39 +02:00
Unbit 099403d554 fixed #409 2013-10-02 09:39:33 +02:00
Unbit 13938a6aa7 more consistent placeholders support 2013-10-02 09:31:48 +02:00
Unbit 9be3a4aaf8 various consistency fixes for strict mode + autoload 2013-10-02 08:41:43 +02:00
Unbit 009e42f349 fixed #409 2013-10-02 07:42:41 +02:00
Unbit 207dd3bc77 fixed #407 2013-10-02 07:36:14 +02:00
Unbit feec6b3151 do not set upper magic vars in --inherit or --include mode 2013-10-01 18:42:30 +02:00
Unbit bf8207f0f1 added magic vars for original config file 2013-10-01 18:16:01 +02:00
Unbit 9fcbc6ee68 added --set-placeholder/--set-ph 2013-10-01 15:50:46 +02:00
Unbit dcb58aaa34 added UWSGI_EMBED_CONFIG variable 2013-10-01 15:39:07 +02:00
Unbit 7163d8ddd4 fixed #406 2013-10-01 15:30:39 +02:00
Unbit c7b24eec45 fixed regression in --set as a workaround for broken getopt_long 2013-10-01 15:02:33 +02:00
Unbit 1e7098f787 fixed #405 2013-10-01 13:27:50 +02:00
Unbit b28f0d9863 fixed #405 2013-10-01 12:22:30 +02:00
Unbit b49c4f4af9 chdir at every emperor glob interaction 2013-10-01 11:38:29 +02:00
Unbit 2c39aafb0b honour --force-cwd 2013-10-01 11:32:17 +02:00
unbit 1036d9c18b Merge pull request #402 from xrmx/ia64
Ia64 fixes
2013-09-30 08:31:03 -07:00
Unbit f0c8cbf190 try specified rvm paths first 2013-09-30 17:12:54 +02:00
Unbit f51db4481b added sendfile support to raw mode 2013-09-30 15:45:27 +02:00
Unbit 717eba7ab3 implemented raw response for python 2013-09-30 15:25:00 +02:00
Unbit 3cc971ba55 raw sockets must be undeferred 2013-09-30 15:01:58 +02:00
Unbit 23b3d7483f introducing raw mode 2013-09-30 13:43:13 +02:00
unbit ba03837e29 Merge pull request #297 from prymitive/dfix
fixed dump daemon process termination
2013-09-30 04:41:37 -07:00
Łukasz Mierzwa 06952fbaff wait for deamon pid after SIGTERM to prevent it from becoming zombie 2013-09-30 12:56:01 +02:00
Unbit 27be00b4cc fixed #399 2013-09-30 11:47:14 +02:00
unbit b50a377190 Merge pull request #217 from prymitive/idle_fix
zero pids after worker killed due to --idle usage
2013-09-30 01:51:22 -07:00
Unbit 1ed9cb0bec prepare for 1.9.18 2013-09-30 09:46:17 +02:00
unbit a548ede3c7 Merge pull request #400 from xrmx/config-cleanup
Some uwsgiconfig.py cleanups
2013-09-30 00:44:38 -07:00
unbit de26c09030 Merge pull request #401 from prymitive/cheaper_fix_limit
adapted cheaper algos to work properly with cheaper limits
2013-09-30 00:41:45 -07:00
Unbit 19aa7c2560 clear exception on PyObject_CheckReadBuffer error 2013-09-30 09:40:40 +02:00
Unbit 215e0c4cbc typos 2013-09-30 09:26:58 +02:00
Unbit d484acefa4 use buffer protocol in WSGI response 2013-09-30 09:25:25 +02:00
Riccardo Magliocchetti 4032efd3e8 Add proper ifdefery for namespaces on ia64
Fix #398
2013-09-29 21:45:07 +02:00
Riccardo Magliocchetti f9d412bcca uwsgiconfig: restore obsolete linux check on ia64
Fix #397
2013-09-29 21:35:38 +02:00
Łukasz Mierzwa 5f52063b9e cheaper API change to allow signaling cheaper algo if it can spawn new workers or only cheap them. Fixes #394 2013-09-29 20:30:29 +02:00
Riccardo Magliocchetti 87833abb42 uwsgiconfig: add --debug and --asan options
--debug compiles with debug symbols
--asan adds support for compiling with address sanitizer, see
http://clang.llvm.org/docs/AddressSanitizer.html#usage
Should work with clang and gcc 4.8. Does not find as many issues
as valgrind but having lot less overhead could be enabled in more
situations.

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

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

small change: don't use exceptions for flow control
2013-09-16 12:49:14 +02:00
Unbit 03a4e900ea fixed #378 2013-09-16 11:50:37 +02:00
Unbit b52dbf2aa0 added forkptyrouter 2013-09-16 06:38:29 +02:00
Unbit c7a22c3b53 improved logpipe 2013-09-15 12:02:14 +02:00
unbit 775aae3f1e Merge pull request #380 from KLab/logpipe
Add pipe logger.
2013-09-15 03:09:53 -07:00
INADA Naoki 862731ba91 Add pipe logger. 2013-09-15 16:47:58 +09:00
Unbit 8c302eee51 start 1.9.17 now 2013-09-14 15:30:23 +02:00
Łukasz Mierzwa edbff83fd6 zero pids after worker killed due to --idle usage 2013-04-08 10:32:39 +02:00
96 changed files with 3833 additions and 1809 deletions
+16
View File
@@ -1,3 +1,19 @@
----------------------------------------------------------------------
LINKING EXCEPTION
In addition to the permissions in the GNU General Public License,
the authors give you unlimited permission to link the compiled
version of this library into combinations with other programs,
and to distribute those combinations without any restriction
coming from the use of this file. (The General Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into
a combined executable.)
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
+2 -2
View File
@@ -7,7 +7,7 @@ filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
print(f.read())
os.write(1, f.read())
f.close()
print(struct.pack("<Q", size))
os.write(1, (struct.pack("<Q", size)))
+1 -1
View File
@@ -1,3 +1,3 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
inherit = base
+33
View File
@@ -0,0 +1,33 @@
[uwsgi]
xml = false
yaml = false
json = false
zeromq = false
ssl = false
pcre = false
routing = false
matheval = false
debug = false
unbit = false
xml_implementation = none
yaml_implementation = none
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = psgi
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = python
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = pypy
inherit = minimal
+3
View File
@@ -0,0 +1,3 @@
[uwsgi]
main_plugin = rack
inherit = minimal
View File
+2 -3
View File
@@ -184,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(list, ",", p, ctx) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) {
free(list);
@@ -205,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
free(list);
return 0;
+10 -13
View File
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
/* how the cache bitmap works:
a bitmap is a shared mempry area allocated when requested by the user with --cache2
a bitmap is a shared memory area allocated when requested by the user with --cache2
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
the block is usable otherwise the block scanner will search for the next one.
@@ -325,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
exit(1);
}
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
exit(1);
}
@@ -335,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
else {
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uc->items) {
if (uc->items == MAP_FAILED) {
uwsgi_error("uwsgi_cache_init()/mmap()");
exit(1);
}
@@ -773,7 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
}
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
}
else {
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
@@ -1191,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
uc->store = c_store;
if (c_nodes) {
char *p = strtok(c_nodes, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
uwsgi_string_new_list(&uc->nodes, p);
p = strtok(NULL, ";");
}
}
if (c_sync) {
char *p = strtok(c_sync, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_sync, ";", p, ctx) {
uwsgi_string_new_list(&uc->sync_nodes, p);
p = strtok(NULL, ";");
}
}
if (c_udp_servers) {
char *p = strtok(c_udp_servers, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
uwsgi_string_new_list(&uc->udp_servers, p);
p = strtok(NULL, ";");
}
}
+160 -9
View File
@@ -55,10 +55,9 @@ int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
int uwsgi_logic_opt_for(char *key, char *value) {
char *p = strtok(uwsgi.logic_opt_data, " ");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
p = strtok(NULL, " ");
}
return 1;
@@ -294,8 +293,25 @@ int uwsgi_count_options(struct uwsgi_option *uopt) {
return count;
}
int uwsgi_opt_exists(char *name) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) return 1;
op++;
}
return 0;
}
/*
avoid loops here !!!
*/
struct uwsgi_option *uwsgi_opt_get(char *name) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_option *op;
int round = 0;
retry:
round++;
if (round > 2) goto end;
op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
@@ -304,10 +320,26 @@ struct uwsgi_option *uwsgi_opt_get(char *name) {
op++;
}
if (uwsgi.autoload) {
if (uwsgi_try_autoload(name)) goto retry;
}
end:
if (uwsgi.strict) {
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
exit(1);
}
return NULL;
}
void add_exported_option(char *key, char *value, int configured) {
add_exported_option_do(key, value, configured, 0);
}
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
@@ -395,6 +427,15 @@ add:
uwsgi.exported_opts_cnt++;
uwsgi.dirty_config = 1;
if (placeholder_only) {
if (uwsgi_opt_exists(key)) {
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
exit(1);
}
uwsgi.exported_opts[id]->configured = 1;
return;
}
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
// requires master ?
@@ -458,11 +499,6 @@ add:
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() {
@@ -478,3 +514,118 @@ void uwsgi_fallback_config() {
// never here
}
}
int uwsgi_manage_opt(char *key, char *value) {
struct uwsgi_option *op = uwsgi_opt_get(key);
if (op) {
op->func(key, value, op->data);
return 1;
}
return 0;
}
void uwsgi_configure() {
int i;
// and now apply the remaining configs
restart:
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
uwsgi.dirty_config = 0;
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
// some option could cause a dirty config tree
if (uwsgi.dirty_config)
goto restart;
}
}
void uwsgi_opt_custom(char *key, char *value, void *data ) {
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
size_t i, count = 1;
size_t value_len = 0;
if (value)
value_len = strlen(value);
off_t pos = 0;
char **opt_argv;
char *tmp_val = NULL, *p = NULL;
// now count the number of args
for (i = 0; i < value_len; i++) {
if (value[i] == ' ') {
count++;
}
}
// allocate a tmp array
opt_argv = uwsgi_calloc(sizeof(char *) * count);
//make a copy of the value;
if (value_len > 0) {
tmp_val = uwsgi_str(value);
// fill the array of options
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
opt_argv[pos] = p;
pos++;
}
}
else {
// no argument specified
opt_argv[0] = "";
}
#ifdef UWSGI_DEBUG
uwsgi_log("found custom option %s with %d args\n", key, count);
#endif
// now make a copy of the option template
char *tmp_opt = uwsgi_str(uco->value);
// split it
char *ctx = NULL;
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
char *equal = strchr(p, '=');
if (!equal)
goto clear;
*equal = '\0';
// build the key
char *new_key = uwsgi_str(p);
for (i = 0; i < count; i++) {
char *old_key = new_key;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
if (new_key != old_key)
free(old_key);
free(placeholder);
}
// build the value
char *new_value = uwsgi_str(equal + 1);
for (i = 0; i < count; i++) {
char *old_value = new_value;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
if (new_value != old_value)
free(old_value);
free(placeholder);
}
// ignore return value here
uwsgi_manage_opt(new_key, new_value);
}
clear:
free(tmp_val);
free(tmp_opt);
free(opt_argv);
}
+11 -13
View File
@@ -139,6 +139,10 @@ int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
}
#endif
if (ud->pid == diedpid && !ud->pidfile) {
if (ud->control) {
gracefully_kill_them_all(0);
return 0;
}
uwsgi_spawn_daemon(ud);
return 1;
}
@@ -231,9 +235,11 @@ void uwsgi_detach_daemons() {
// try to gracefully stop daemon, kill it if it won't die
// if mercy is not set than wait up to 3 seconds
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
int waitpid_status;
while (!kill(ud->pid, 0)) {
kill(-ud->pid, SIGTERM);
sleep(1);
waitpid(-ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
kill(-ud->pid, SIGKILL);
@@ -253,7 +259,6 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
// skip unregistered daemons
if (!ud->registered) return;
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
@@ -299,18 +304,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
if (!uwsgi.daemons_honour_stdin) {
// /dev/null will became stdin
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
uwsgi_remap_fd(0, "/dev/null");
}
if (setsid() < 0) {
@@ -412,6 +406,10 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
uwsgi_ud->last_spawn = 0;
uwsgi_ud->daemonize = daemonize;
uwsgi_ud->pidfile = pidfile;
uwsgi_ud->control = 0;
if (!strcmp(opt, "attach-control-daemon")) {
uwsgi_ud->control = 1;
}
#ifdef UWSGI_SSL
uwsgi_ud->legion = legion;
#endif
+267 -53
View File
@@ -339,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
struct stat st;
struct uwsgi_instance *ui_current;
if (chdir(uwsgi.cwd)) {
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
exit(1);
}
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
return;
}
@@ -617,6 +622,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
}
void emperor_stop(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// remove uWSGI instance
if (write(c_ui->pipe[0], "\0", 1) != 1) {
@@ -624,10 +630,23 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
}
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
}
void emperor_curse(struct uwsgi_instance *c_ui) {
if (c_ui->status == 1) return;
// curse uWSGI instance
c_ui->status = 1;
c_ui->cursed_at = uwsgi_now();
uwsgi_log("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
}
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
struct uwsgi_header uh;
@@ -817,7 +836,7 @@ 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 defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
if (uwsgi.emperor_clone) {
char stack[PTHREAD_STACK_MIN];
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
@@ -825,7 +844,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
else {
#endif
pid = fork();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
}
#endif
if (pid < 0) {
@@ -940,6 +959,59 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#ifdef CLONE_NEWUSER
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
if (setuid(0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
exit(1);
}
}
#endif
#ifdef UWSGI_CAP
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
int i;
for(i=0;i<=CAP_LAST_CAP;i++) {
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
if (has_cap == 1) {
if (i == CAP_SETPCAP) continue;
int j;int found = 0;
for(j=0;j<uwsgi.emperor_cap_count;j++) {
if (uwsgi.emperor_cap[j] == (int) i) {
found = 1; break;
}
}
if (found) continue;
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
uwsgi_log_verbose("unable to drop capability %lu\n", i);
exit(1);
}
}
}
// just for being paranoid
#ifdef SECBIT_KEEP_CAPS
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#else
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
uwsgi_error("prctl()");
exit(1);
}
#endif
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
}
#endif
#endif
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);
if (setgid(n_ui->gid)) {
@@ -1025,18 +1097,32 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
int counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while (uct) {
counter += 2;
uct = uct->next;
}
struct uwsgi_string_list *uct;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
// reset counter
counter = 1;
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
if (colon) {
@@ -1044,55 +1130,60 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
}
// initialize to a default value
vassal_argv[1] = "--inherit";
vassal_argv[counter] = "--inherit";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
vassal_argv[1] = "--xml";
vassal_argv[counter] = "--xml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
vassal_argv[1] = "--ini";
vassal_argv[counter] = "--ini";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
vassal_argv[counter] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
vassal_argv[1] = "--json";
vassal_argv[counter] = "--json";
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(n_ui->name, usl->value)) {
vassal_argv[1] = "--config";
vassal_argv[counter] = "--config";
break;
}
usl = usl->next;
}
if (colon) colon[0] = ':';
if (colon) {
colon[0] = ':';
}
// start config filename...
counter++;
vassal_argv[2] = n_ui->name;
vassal_argv[counter] = n_ui->name;
if (uwsgi.emperor_magic_exec) {
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
}
counter = 3;
uct = uwsgi.vassals_templates;
while (uct) {
// start templates,includes,inherit...
counter++;
uwsgi_foreach(uct, uwsgi.vassals_templates) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter + 1] = uct->value;
counter += 2;
uct = uct->next;
}
uwsgi_foreach (uct, uwsgi.vassals_includes) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
}
vassal_argv[counter] = NULL;
// disable stdin OR map it to the "on demand" socket
@@ -1106,18 +1197,7 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
}
}
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
uwsgi_remap_fd(0, "/dev/null");
}
// close all of the unneded fd
@@ -1456,7 +1536,8 @@ void emperor_loop() {
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
emperor_curse(ui_current);
}
else {
if (byte == 17) {
@@ -1506,10 +1587,14 @@ void emperor_loop() {
while (ui_current) {
if (ui_current->last_heartbeat > 0) {
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
// set last_heartbeat to 0 avoiding races
ui_current->last_heartbeat = 0;
emperor_respawn(ui_current, uwsgi_now());
if (ui_current->pid > 0) {
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill()");
}
}
}
}
ui_current = ui_current->ui_next;
@@ -1558,14 +1643,8 @@ void emperor_loop() {
ui_current = ui;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->status == 1) {
if (ui_current->config)
free(ui_current->config);
// SAFE
emperor_del(ui_current);
break;
}
else if (ui_current->pid == diedpid) {
time_t now = uwsgi_now();
if (ui_current->pid == diedpid) {
if (ui_current->status == 0) {
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
@@ -1588,6 +1667,13 @@ void emperor_loop() {
break;
}
}
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
ui_current->cursed_at = now;
if (kill(ui_current->pid, SIGKILL)) {
uwsgi_error("[emperor] kill");
}
break;
}
}
@@ -1684,6 +1770,8 @@ void emperor_send_stats(int fd) {
goto end0;
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
goto end0;
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
goto end0;
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
@@ -1827,6 +1915,46 @@ void uwsgi_emperor_start() {
}
void uwsgi_check_emperor() {
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
if (emperor_fd_pass) {
for(;;) {
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
if (proxy_fd < 0) {
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
sleep(1);
continue;
}
int count = 2;
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
if (fds && count > 0) {
char *env_emperor_fd = uwsgi_num2str(fds[0]);
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
free(env_emperor_fd);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd);
if (count > 1) {
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
free(env_emperor_fd_config);
int i; for(i=0;i<count;i++) close(fds[i]);
goto next;
}
free(env_emperor_fd_config);
}
break;
}
next:
if (fds) free(fds);
close(proxy_fd);
sleep(1);
}
unsetenv("UWSGI_EMPEROR_PROXY");
}
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
@@ -1882,3 +2010,89 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_manage_emperor_proxy() {
struct sockaddr_un epsun;
socklen_t epsun_len = sizeof(struct sockaddr_un);
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
if (ep_client < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
return;
}
int num_fds = 1;
if (uwsgi.emperor_fd_config > -1) num_fds++;
struct msghdr ep_msg;
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
struct iovec ep_iov[2];
struct cmsghdr *cmsg;
ep_iov[0].iov_base = "uwsgi-emperor";
ep_iov[0].iov_len = 13;
ep_iov[1].iov_base = &num_fds;
ep_iov[1].iov_len = sizeof(int);
ep_msg.msg_name = NULL;
ep_msg.msg_namelen = 0;
ep_msg.msg_iov = ep_iov;
ep_msg.msg_iovlen = 2;
ep_msg.msg_flags = 0;
ep_msg.msg_control = ep_msg_control;
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
cmsg = CMSG_FIRSTHDR(&ep_msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
if (num_fds > 1) {
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
}
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
}
free(ep_msg_control);
close(ep_client);
}
+122
View File
@@ -0,0 +1,122 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
the --master-fifo option create a unix named pipe (fifo) you can use to send management
commands to the master:
echo r > myfifo
*/
// this var can be accessed by plugins and hooks
void (*uwsgi_fifo_table[256])(int);
static char *uwsgi_fifo_by_slot() {
int count = 0;
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.master_fifo) {
if (count == uwsgi.master_fifo_slot) return usl->value;
count++;
}
return uwsgi.master_fifo->value;
}
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
/*
this is called as soon as possibile allowing plugins (or hooks) to override it
*/
void uwsgi_master_fifo_prepare() {
int i;
for(i=0;i<256;i++) {
uwsgi_fifo_table[i] = NULL;
}
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
uwsgi_fifo_table['f'] = uwsgi_refork_master;
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
uwsgi_fifo_table['p'] = suspend_resume_them_all;
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
uwsgi_fifo_table['Q'] = kill_them_all;
uwsgi_fifo_table['r'] = grace_them_all;
uwsgi_fifo_table['R'] = reap_them_all;
uwsgi_fifo_table['s'] = stats;
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
}
int uwsgi_master_fifo() {
char *path = uwsgi_fifo_by_slot();
unlink(path);
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
exit(1);
}
int fd = open(path, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error("uwsgi_master_fifo()/open()");
exit(1);
}
uwsgi_socket_nb(fd);
return fd;
}
int uwsgi_master_fifo_manage(int fd) {
char cmd;
ssize_t rlen = read(fd, &cmd, 1);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
uwsgi_error("uwsgi_master_fifo_manage()/read()");
exit(1);
}
// fifo destroyed, recreate it
else if (rlen == 0) {
close(fd);
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
return 0;
}
if (uwsgi_fifo_table[(int) cmd]) {
uwsgi_fifo_table[(int) cmd](0);
}
return 0;
}
+1
View File
@@ -70,6 +70,7 @@ void gateway_respawn(int id) {
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
uwsgi_close_all_sockets();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
+13 -7
View File
@@ -75,10 +75,12 @@ void uwsgi_init_default() {
uwsgi.original_log_fd = -1;
uwsgi.emperor_fd_config = -1;
uwsgi.emperor_fd_proxy = -1;
// default emperor scan frequency
uwsgi.emperor_freq = 3;
uwsgi.emperor_throttle = 1000;
uwsgi.emperor_heartbeat = 30;
uwsgi.emperor_curse_tolerance = 30;
// max 3 minutes throttling
uwsgi.emperor_max_throttle = 1000 * 180;
uwsgi.emperor_pid = -1;
@@ -172,6 +174,12 @@ void uwsgi_init_default() {
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
// clear reforked status
uwsgi.master_is_reforked = 0;
uwsgi.master_fifo_fd = -1;
uwsgi_master_fifo_prepare();
}
void uwsgi_setup_reload() {
@@ -216,21 +224,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
char *ctx = NULL;
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
@@ -460,7 +466,7 @@ void sanitize_args() {
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
exit(1);
}
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
exit(1);
}
+300 -189
View File
@@ -116,48 +116,31 @@ end:
}
/*
extremely complex function for reading resources (files, url...)
need a lot of refactoring...
*/
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
int fd = atoi(url);
return uwsgi_read_fd(fd, size, add_zero);
}
int fd;
struct stat sb;
char *buffer = NULL;
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url, NULL, cpipe[1]);
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
return buffer;
}
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
char byte;
ssize_t len;
char *uri, *colon;
char *domain;
char *ip;
int body = 0;
char *magic_buf;
int body = 0;
char *buffer = NULL;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
}
// fd ?
else if (!strncmp("fd://", url, 5)) {
fd = atoi(url + 5);
buffer = uwsgi_read_fd(fd, size, add_zero);
}
// exec ?
else if (!strncmp("exec://", url, 5)) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("pipe()");
exit(1);
}
uwsgi_run_command(url + 7, NULL, cpipe[1]);
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
close(cpipe[0]);
close(cpipe[1]);
}
// http url ?
else if (!strncmp("http://", url, 7)) {
domain = url + 7;
uri = strchr(domain, '/');
char *domain = url;
char *uri = strchr(domain, '/');
if (!uri) {
uwsgi_log("invalid http url\n");
exit(1);
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = 0;
uwsgi_log("domain: %s\n", domain);
colon = uwsgi_get_last_char(domain, ':');
char *colon = uwsgi_get_last_char(domain, ':');
if (colon) {
colon[0] = 0;
}
ip = uwsgi_resolve_ip(domain);
char *ip = uwsgi_resolve_ip(domain);
if (!ip) {
uwsgi_log("unable to resolve address %s\n", domain);
exit(1);
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
ip = uwsgi_concat2(ip, ":80");
}
fd = uwsgi_connect(ip, 0, 0);
int fd = uwsgi_connect(ip, 0, 0);
if (fd < 0) {
uwsgi_error("uwsgi_scheme_http()/connect()");
exit(1);
}
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
uri[0] = '/';
len = write(fd, "GET ", 4);
len = write(fd, uri, strlen(uri));
len = write(fd, " HTTP/1.0\r\n", 11);
len = write(fd, "Host: ", 6);
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = 0;
len = write(fd, domain, strlen(domain));
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
uri[0] = '/';
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
len = write(fd, "\r\n\r\n", 4);
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
int http_status_code_ptr = 0;
@@ -264,57 +248,231 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
buffer[*size - 1] = 0;
}
return buffer;
}
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
exit(1);
}
else if (!strncmp("emperor://", url, 10)) {
if (uwsgi.emperor_fd_config < 0) {
uwsgi_log("this is not a vassal instance\n");
ssize_t rlen;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
ssize_t rlen;
*size = 0;
struct uwsgi_header uh;
size_t remains = 4;
char *ptr = (char *) &uh;
while(remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
remains = uh.pktsize;
if (!remains) {
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
exit(1);
}
char *buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
}
*size = uh.pktsize + add_zero;
return buffer;
}
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
char *buffer = NULL;
int fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -8, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
buffer = uwsgi_calloc(remains + add_zero);
ptr = buffer;
while (remains) {
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
if (ret <= 0) {
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
exit(1);
}
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
if (rlen <= 0) {
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
exit(1);
}
ptr+=rlen;
remains-=rlen;
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
*size = uh.pktsize + add_zero;
}
return buffer;
}
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
if (!func) {
uwsgi_log("unable to find symbol %s\n", url);
exit(1);
}
char *s = func();
if (!s) {
uwsgi_log("called symbol %s did not return a string\n", url);
exit(1);
}
*size = strlen(s);
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, s, strlen(s));
return buffer;
}
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
if (raw_symbol) {
sym_start_ptr = *raw_symbol;
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
goto found;
}
char *symbol = uwsgi_concat3("_binary_", url, "_start");
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url, "_end");
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
found:
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
char *buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
return buffer;
}
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
#ifdef UWSGI_ELF
size_t s_len = 0;
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
return buffer;
#else
uwsgi_log("section:// scheme not supported on this platform\n");
exit(1);
#endif
}
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.schemes) {
if (!strcmp(usl->value, name)) goto found;
}
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
found:
usl->custom_ptr = func;
return usl;
}
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
struct stat sb;
char *buffer = NULL;
ssize_t len;
char *magic_buf;
int fd;
*size = 0;
// stdin ?
if (!strcmp(url, "-")) {
buffer = uwsgi_read_fd(0, size, add_zero);
}
#ifdef UWSGI_EMBED_CONFIG
else if (url[0] == 0) {
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
@@ -326,106 +484,19 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
}
#endif
else if (!strncmp("data://", url, 7)) {
fd = open(uwsgi.binary_path, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(uwsgi.binary_path);
exit(1);
}
int slot = atoi(url + 7);
if (slot < 0) {
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
uwsgi_log("requesting binary data slot %d\n", slot);
off_t fo = lseek(fd, 0, SEEK_END);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
int i = 0;
uint64_t datasize = 0;
for (i = 0; i <= slot; i++) {
fo = lseek(fd, -9, SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
ssize_t len = read(fd, &datasize, 8);
if (len != 8) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (datasize == 0) {
uwsgi_log("0 size binary data !!!\n");
exit(1);
}
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
if (fo < 0) {
uwsgi_error("lseek()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
if (i == slot) {
*size = datasize;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
len = read(fd, buffer, datasize);
if (len != (ssize_t) datasize) {
uwsgi_error("read()");
uwsgi_log("invalid binary data slot requested\n");
exit(1);
}
}
}
}
else if (!strncmp("sym://", url, 6)) {
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_start_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
if (!sym_end_ptr) {
uwsgi_log("unable to find symbol %s\n", symbol);
exit(1);
}
free(symbol);
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
if (!usl) goto fallback;
*size = sym_end_ptr - sym_start_ptr;
if (add_zero) {
*size += 1;
}
buffer = uwsgi_malloc(*size);
memset(buffer, 0, *size);
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
}
#ifdef UWSGI_ELF
else if (!strncmp("section://", url, 10)) {
size_t s_len = 0;
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero)
*size += 1;
}
#endif
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
buffer = func(url + usl->len + 3, size, add_zero);
if (buffer) goto end;
// never here !!!
uwsgi_log("unable to parse config file %s\n", url);
exit(1);
// fallback to file
else {
fallback:
fd = open(url, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(url);
@@ -457,7 +528,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
if (add_zero)
buffer[sb.st_size] = 0;
}
end:
@@ -1097,3 +1167,44 @@ int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
return -1;
}
void uwsgi_setup_schemes() {
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
uwsgi_register_scheme("http", uwsgi_scheme_http);
uwsgi_register_scheme("data", uwsgi_scheme_data);
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
uwsgi_register_scheme("section", uwsgi_scheme_section);
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
uwsgi_register_scheme("call", uwsgi_scheme_call);
}
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.schemes) {
char *url = uwsgi_concat2(usl->value, "://");
int ret = uwsgi_startswith(file, url, strlen(url));
free(url);
if (!ret) return usl;
}
return NULL;
}
void uwsgi_remap_fd(int fd, char *filename) {
int fdin = open(filename, O_RDWR);
if (fdin < 0) {
uwsgi_error_open(filename);
exit(1);
}
/* stdin */
if (fdin != fd) {
if (dup2(fdin, fd) < 0) {
uwsgi_error("uwsgi_remap_fd()/dup2()");
exit(1);
}
close(fdin);
}
}
+2
View File
@@ -106,6 +106,8 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
config_iter = json_object_iter_next(config, config_iter);
}
if (colon) colon[0] = ':';
}
#endif
+103 -69
View File
@@ -488,7 +488,6 @@ void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen,
void uwsgi_check_logrotate(void) {
char message[1024];
int need_rotation = 0;
int need_reopen = 0;
@@ -512,70 +511,81 @@ void uwsgi_check_logrotate(void) {
}
if (need_rotation) {
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
uwsgi_log_rotate();
}
else if (need_reopen) {
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
uwsgi_log_reopen();
}
}
void uwsgi_log_rotate() {
char message[1024];
if (!uwsgi.logfile) return;
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) uwsgi_now());
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
void uwsgi_log_reopen() {
char message[1024];
if (!uwsgi.logfile) return;
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
void log_request(struct wsgi_request *wsgi_req) {
@@ -1401,6 +1411,16 @@ static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_l
size_t new_msg_len = len;
while(usl) {
struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
if (ule->use_for) {
if (ul && ul->id) {
if (strcmp(ule->use_for, ul->id)) {
goto next;
}
}
else {
goto next;
}
}
size_t rlen = 0;
char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
if (new_msg != msg) {
@@ -1408,6 +1428,7 @@ static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_l
}
new_msg = buf;
new_msg_len = rlen;
next:
usl = usl->next;
}
if (ul) {
@@ -1625,21 +1646,28 @@ void uwsgi_setup_log_encoders() {
uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
if (space) *space = ' ';
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-encoder] registered %s\n", usl->value);
}
@@ -1647,21 +1675,27 @@ void uwsgi_setup_log_encoders() {
uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
char *space = strchr(usl->value, ' ');
if (space) *space = 0;
char *use_for = strchr(usl->value, ':');
if (use_for) *use_for = 0;
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
if (!ule) {
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
exit(1);
}
if (space) *space = ' ';
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
if (use_for) {
ule2->use_for = uwsgi_str(use_for+1);
*use_for = ':';
}
// we use a copy
if (space) {
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
if (space) {
*space = ' ';
ule2->args = uwsgi_str(space+1);
}
else {
ule2->args = uwsgi_str("");
}
usl->custom_ptr = ule2;
uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
}
+90 -74
View File
@@ -77,38 +77,6 @@ void uwsgi_master_manage_udp(int udp_fd) {
}
}
void uwsgi_master_manage_emperor() {
char byte;
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
if (rlen > 0) {
uwsgi_log_verbose("received message %d from emperor\n", byte);
// remove me
if (byte == 0) {
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
}
// reload me
else if (byte == 1) {
// un-lazy the stack to trigger a real reload
uwsgi.lazy = 0;
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
}
}
else {
uwsgi_log("lost connection with my emperor !!!\n");
close(uwsgi.emperor_fd);
if (!uwsgi.status.brutally_reloading)
kill_them_all(0);
sleep(2);
exit(1);
}
}
void uwsgi_master_restore_snapshot() {
int i, waitpid_status;
uwsgi_log("[snapshot] restoring workers...\n");
@@ -222,8 +190,8 @@ int uwsgi_get_tcp_info(int fd) {
#elif defined(__FreeBSD__)
if (!uwsgi.shared->ti.__tcpi_sacked) {
#endif
return 0;
}
return 0;
}
#if defined(__linux__)
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
@@ -242,12 +210,12 @@ int uwsgi_get_tcp_info(int fd) {
uwsgi_error("write()");
}
else {
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
}
}
}
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
@@ -306,7 +274,6 @@ int master_loop(char **argv, char **environ) {
struct uwsgi_rb_timer *min_timeout;
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
if (uwsgi.procname_master) {
uwsgi_set_processname(uwsgi.procname_master);
}
@@ -346,6 +313,11 @@ int master_loop(char **argv, char **environ) {
#endif
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
if (uwsgi.master_fifo) {
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
}
if (uwsgi.spoolers) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
}
@@ -383,7 +355,18 @@ int master_loop(char **argv, char **environ) {
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
if (uwsgi.has_emperor) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
if (uwsgi.emperor_proxy) {
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
if (uwsgi.emperor_fd_proxy < 0) exit(1);
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
uwsgi_error("[emperor-proxy] chmod()");
exit(1);
}
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
}
else {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
}
}
if (uwsgi.zerg_server) {
@@ -477,7 +460,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
// update exec touches
struct uwsgi_string_list *usl = uwsgi.touch_exec;
while(usl) {
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
@@ -489,16 +472,16 @@ int master_loop(char **argv, char **environ) {
uwsgi_check_touches(uwsgi.touch_exec);
// update signal touches
usl = uwsgi.touch_signal;
while(usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
while (usl) {
char *space = strchr(usl->value, ' ');
if (space) {
*space = 0;
usl->len = strlen(usl->value);
usl->custom_ptr = space + 1;
}
usl = usl->next;
}
uwsgi_check_touches(uwsgi.touch_signal);
// fsmon
uwsgi_fsmon_setup();
@@ -731,6 +714,7 @@ int master_loop(char **argv, char **environ) {
uwsgi_master_check_mules_deadline();
uwsgi_master_check_spoolers_deadline();
uwsgi_master_check_crons_deadline();
uwsgi_master_check_mountpoints();
#ifdef __linux__
#ifdef MADV_MERGEABLE
@@ -741,7 +725,7 @@ int master_loop(char **argv, char **environ) {
#endif
// resubscribe every 10 cycles by default
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
uwsgi_subscribe_all(0, 0);
}
@@ -765,40 +749,34 @@ int master_loop(char **argv, char **environ) {
}
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
if (touched) {
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
continue;
}
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
uwsgi_reload_workers();
continue;
}
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
if (touched) {
if (uwsgi.status.chain_reloading == 0) {
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
}
}
// be sure to run it as the last touch check
touched = uwsgi_check_touches(uwsgi.touch_exec);
if (touched) {
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
}
}
touched = uwsgi_check_touches(uwsgi.touch_signal);
if (touched) {
if (touched) {
uint8_t signum = atoi(touched);
uwsgi_route_signal(signum);
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
}
}
continue;
@@ -815,12 +793,18 @@ int master_loop(char **argv, char **environ) {
// reload gateways and daemons only on normal workflow (+outworld status)
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
if (uwsgi_master_check_emperor_death(diedpid)) continue;
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
if (uwsgi_master_check_mules_death(diedpid)) continue;
if (uwsgi_master_check_gateways_death(diedpid)) continue;
if (uwsgi_master_check_daemons_death(diedpid)) continue;
if (uwsgi_master_check_cron_death(diedpid)) continue;
if (uwsgi_master_check_emperor_death(diedpid))
continue;
if (uwsgi_master_check_spoolers_death(diedpid))
continue;
if (uwsgi_master_check_mules_death(diedpid))
continue;
if (uwsgi_master_check_gateways_death(diedpid))
continue;
if (uwsgi_master_check_daemons_death(diedpid))
continue;
if (uwsgi_master_check_cron_death(diedpid))
continue;
}
@@ -885,8 +869,9 @@ next:
// ok, if we are reloading or dying, just continue the master loop
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
if (!uwsgi.workers[thewid].cursed_at)
uwsgi.workers[thewid].cursed_at = uwsgi_now();
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
uwsgi.workers[thewid].cursed_at = 0;
continue;
}
@@ -964,3 +949,34 @@ next:
// never here
}
void uwsgi_reload_workers() {
int i;
uwsgi_block_signal(SIGHUP);
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_unblock_signal(SIGHUP);
}
void uwsgi_chain_reload() {
if (!uwsgi.status.chain_reloading) {
uwsgi_log_verbose("chain reload starting...\n");
uwsgi.status.chain_reloading = 1;
}
else {
uwsgi_log_verbose("chain reload already running...\n");
}
}
void uwsgi_brutally_reload_workers() {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
uwsgi_curse(i, SIGINT);
}
}
}
+22 -2
View File
@@ -35,11 +35,17 @@ int uwsgi_master_check_reload(char **argv) {
// check for chain reload
void uwsgi_master_check_chain() {
if (!uwsgi.status.chain_reloading) return;
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
int i;
int needed_procs = 0;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
needed_procs++;
}
}
if (uwsgi.status.chain_reloading > needed_procs) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
int i;
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
@@ -112,6 +118,9 @@ void uwsgi_master_check_idle() {
if (errno != ECHILD)
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
}
else {
uwsgi.workers[i].pid = 0;
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
@@ -316,3 +325,14 @@ void uwsgi_master_check_crons_deadline() {
}
}
void uwsgi_master_check_mountpoints() {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
if (uwsgi_check_mountpoint(usl->value)) {
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
uwsgi_nuclear_blast();
//never here
exit(1);
}
}
}
+9
View File
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
}
}
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
@@ -36,6 +40,11 @@ int uwsgi_master_manage_events(int interesting_fd) {
// emperor event ?
if (uwsgi.has_emperor) {
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
uwsgi_master_manage_emperor_proxy();
return 0;
}
if (interesting_fd == uwsgi.emperor_fd) {
uwsgi_master_manage_emperor();
return 0;
+99 -21
View File
@@ -142,7 +142,22 @@ int uwsgi_calc_cheaper(void) {
}
}
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
// then check for fifo
if (uwsgi.cheaper_fifo_delta != 0) {
if (!ignore_algo) {
needed_workers = uwsgi.cheaper_fifo_delta;
ignore_algo = 1;
}
uwsgi.cheaper_fifo_delta = 0;
}
// if cheaper limits wants to change worker count, then skip cheaper algo
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
// safe check to verify if cheaper algo obeyed ignore_algo value
if (ignore_algo && needed_workers > 0) {
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
needed_workers = 0;
}
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
@@ -179,6 +194,11 @@ int uwsgi_calc_cheaper(void) {
return 1;
}
// fake algo to allow control with the fifo
int uwsgi_cheaper_algo_manual(int can_spawn) {
return 0;
}
/*
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
@@ -214,7 +234,7 @@ int uwsgi_calc_cheaper(void) {
*/
int uwsgi_cheaper_algo_spare(void) {
int uwsgi_cheaper_algo_spare(int can_spawn) {
int i;
static uint64_t overload_count = 0;
@@ -238,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) {
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
@@ -306,7 +326,7 @@ healthy:
*/
int uwsgi_cheaper_algo_backlog(void) {
int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
@@ -315,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) {
int backlog = 0;
#endif
if (backlog > (int) uwsgi.cheaper_overload) {
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
@@ -353,23 +373,30 @@ void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
if (!uwsgi.master_is_reforked) {
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
}
else {
uwsgi_log("fork()'ing uWSGI...\n");
}
// call master cleanup hooks
uwsgi_master_cleanup_hooks();
// call atexit user exec
uwsgi_exec_atexit();
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
@@ -556,6 +583,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
}
}
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
}
@@ -1323,7 +1351,7 @@ end:
return NULL;
}
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
@@ -1512,3 +1540,53 @@ void uwsgi_add_reload_fds() {
add_reload_fds(uwsgi.reload_on_fd, "graceful");
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
}
void uwsgi_refork_master() {
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("uwsgi_refork_master()/fork()");
return;
}
if (pid > 0) {
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
return;
}
// detach from the old master
setsid();
uwsgi.master_is_reforked = 1;
uwsgi_reload(uwsgi.argv);
// never here
exit(1);
}
void uwsgi_cheaper_increase() {
uwsgi.cheaper_fifo_delta++;
}
void uwsgi_cheaper_decrease() {
uwsgi.cheaper_fifo_delta--;
}
void uwsgi_go_cheap() {
int i;
int waitpid_status;
if (uwsgi.status.is_cheap) return;
uwsgi_log_verbose("going cheap...\n");
uwsgi.status.is_cheap = 1;
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
if (errno != ECHILD)
uwsgi_error("uwsgi_go_cheap()/waitpid()");
}
}
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
+23 -9
View File
@@ -16,6 +16,7 @@
#ifndef MS_REC
#define MS_REC 16384
#endif
#include <sys/statfs.h>
#endif
struct uwsgi_mount_flag {
@@ -102,27 +103,26 @@ uint64_t uwsgi_mount_flag(char *mflag) {
}
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
struct iovec iov[6];
#endif
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p = strtok(mflags, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown mount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
p = strtok(NULL, ",");
}
free(mflags);
parsed:
#ifdef __linux__
return mount(what, where, fs, mountflags, NULL);
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
iov[0].iov_base = "fstype";
iov[0].iov_len = 7;
iov[1].iov_base = fs;
@@ -147,15 +147,14 @@ int uwsgi_umount(char *where, char *flags) {
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p = strtok(mflags, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown umount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
p = strtok(NULL, ",");
}
free(mflags);
parsed:
@@ -191,7 +190,7 @@ unmountable:
free(slashed);
}
return umount2(where, mountflags);
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
return unmount(where, mountflags);
#endif
return -1;
@@ -238,3 +237,18 @@ int uwsgi_umount_hook(char *arg) {
free(tmp_arg);
return 0;
}
int uwsgi_check_mountpoint(char *mountpoint) {
#ifdef __linux__
struct statfs sfs;
int ret = statfs(mountpoint, &sfs);
if (ret) {
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
return -1;
}
return 0;
#else
uwsgi_log("this platform does not support mountpoints check !!!\n");
return -1;
#endif
}
+2 -4
View File
@@ -453,8 +453,8 @@ void uwsgi_setup_mules_and_farms() {
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(mules_list, ",", p, ctx) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
@@ -462,8 +462,6 @@ void uwsgi_setup_mules_and_farms() {
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
+1 -1
View File
@@ -323,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__)
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
+3 -1
View File
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal + 1, NULL);
if (!plugin_already_loaded(equal+1)) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
}
p = strtok_r(NULL, "\n", &ctx);
+1 -1
View File
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (!uwsgi.queue) {
if (uwsgi.queue == MAP_FAILED) {
uwsgi_error("mmap()");
exit(1);
}
+2
View File
@@ -389,6 +389,8 @@ wait:
remains -= len;
*rlen += len;
continue;
}else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
if (len == 0) {
+1 -1
View File
@@ -20,7 +20,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__linux__) || defined(__sun__)
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#endif
+31 -16
View File
@@ -187,6 +187,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
return -1;
}
#ifdef __linux__
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
@@ -1645,8 +1653,8 @@ void uwsgi_map_sockets() {
}
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon + 1, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
@@ -1657,7 +1665,6 @@ void uwsgi_map_sockets() {
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
}
@@ -1666,18 +1673,7 @@ void uwsgi_map_sockets() {
if (!enabled) {
close(uwsgi_sock->fd);
int fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
uwsgi_sock->disabled = 1;
}
@@ -1707,6 +1703,10 @@ void uwsgi_bind_sockets() {
while (uwsgi_sock) {
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
char *tcp_port = strrchr(uwsgi_sock->name, ':');
int current_defer_accept = uwsgi.no_defer_accept;
if (uwsgi_sock->no_defer) {
uwsgi.no_defer_accept = 1;
}
if (tcp_port == NULL) {
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi_sock->family = AF_UNIX;
@@ -1740,6 +1740,7 @@ void uwsgi_bind_sockets() {
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
exit(1);
}
uwsgi.no_defer_accept = current_defer_accept;
}
uwsgi_sock->bound = 1;
uwsgi_sock = uwsgi_sock->next;
@@ -1870,7 +1871,20 @@ setup_proto:
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && !strcmp("raw", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_raw_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
@@ -1976,3 +1990,4 @@ int uwsgi_accept(int server_fd) {
}
+104
View File
@@ -379,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
return buf - 1;
}
/*
status 0: append mode
status 1: single quote found
status 2: double quote found
status 3: backslash found (on 0)
status 4: backslash found (on 1)
status 5: backslash found (on 2)
*/
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
size_t i;
int status = 0;
char *base = uwsgi_concat2n(what, what_len, "", 0);
char *item = NULL;
char *ptr = NULL;
*rlen = 0;
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
for(i=0;i<what_len;i++) {
if (!item) {
item = uwsgi_malloc((what_len - i)+1);
ptr = item;
}
if (status == 0) {
if (base[i] == '\\') {
status = 3;
}
else if (base[i] == '"') {
status = 2;
}
else if (base[i] == '\'') {
status = 1;
}
else if (strchr(sep, base[i])) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
item = NULL;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash
if (status == 3) {
*ptr++= base[i];
status = 0;
continue;
}
// single quote
if (status == 1) {
if (base[i] == '\\') {
status = 4;
}
else if (base[i] == '\'') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// double quote
if (status == 2) {
if (base[i] == '\\') {
status = 5;
}
else if (base[i] == '"') {
status = 0;
}
else {
*ptr++= base[i];
}
continue;
}
// backslash single quote
if (status == 4) {
*ptr++= base[i];
status = 1;
continue;
}
// backslash double quote
if (status == 5) {
*ptr++= base[i];
status = 2;
continue;
}
}
if (item) {
*ptr++= 0;
ret[(*rlen)] = item; (*rlen)++;
}
free(base);
return ret;
}
+906 -859
View File
File diff suppressed because it is too large Load Diff
+256 -184
View File
@@ -53,6 +53,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"scgi-modifier1", required_argument, 0, "force the specified modifier1 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier1, 0},
{"scgi-modifier2", required_argument, 0, "force the specified modifier2 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier2, 0},
{"raw-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using RAW protocol", uwsgi_opt_add_socket_no_defer, "raw", 0},
{"raw-modifier1", required_argument, 0, "force the specified modifier1 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_modifier1, 0},
{"raw-modifier2", required_argument, 0, "force the specified modifier2 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_modifier2, 0},
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
@@ -78,7 +82,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
{"set", required_argument, 'S', "set a placeholder or an option", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
{"set-placeholder", required_argument, 0, "set a placeholder", uwsgi_opt_set_placeholder, (void *) 1, UWSGI_OPT_IMMEDIATE},
{"set-ph", required_argument, 0, "set a placeholder", uwsgi_opt_set_placeholder, (void *) 1, UWSGI_OPT_IMMEDIATE},
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
@@ -173,10 +179,13 @@ 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-proxy-socket", required_argument, 0, "force the vassal to became an Emperor proxy", uwsgi_opt_set_str, &uwsgi.emperor_proxy, 0},
{"emperor-wrapper", required_argument, 0, "set a binary wrapper for vassals", uwsgi_opt_set_str, &uwsgi.emperor_wrapper, 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},
{"emperor-curse-tolerance", required_argument, 0, "set the Emperor tolerance about cursed vassals", uwsgi_opt_set_int, &uwsgi.emperor_curse_tolerance, 0},
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
@@ -196,10 +205,18 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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
#ifdef UWSGI_CAP
{"emperor-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
{"vassals-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
{"vassal-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 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},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
{"vassals-include", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes, 0},
{"vassals-inherit-before", required_argument, 0, "add config templates to vassals config (uses --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates_before, 0},
{"vassals-include-before", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes_before, 0},
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
@@ -305,8 +322,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
#endif
#ifdef __linux__
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
{"unshare2", required_argument, 0, "unshare() part of the processes and put it in a new namespace after rootfs change", uwsgi_opt_set_unshare, &uwsgi.unshare2, 0},
#endif
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
{"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0},
{"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0},
{"jail-ip6", required_argument, 0, "add an ipv6 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip6, 0},
@@ -325,6 +343,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"refork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
{"re-fork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
{"hook-asap", required_argument, 0, "run the specified hook as soon as possible", uwsgi_opt_add_string_list, &uwsgi.hook_asap, 0},
{"hook-pre-jail", required_argument, 0, "run the specified hook before jailing", uwsgi_opt_add_string_list, &uwsgi.hook_pre_jail, 0},
{"hook-post-jail", required_argument, 0, "run the specified hook after jailing", uwsgi_opt_add_string_list, &uwsgi.hook_post_jail, 0},
{"hook-in-jail", required_argument, 0, "run the specified hook in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.hook_in_jail, 0},
@@ -337,6 +356,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"hook-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
{"hook-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
{"exec-asap", required_argument, 0, "run the specified command as soon as possible", uwsgi_opt_add_string_list, &uwsgi.exec_asap, 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},
@@ -349,6 +369,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"mount-asap", required_argument, 0, "mount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.mount_asap, 0},
{"mount-pre-jail", required_argument, 0, "mount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.mount_pre_jail, 0},
{"mount-post-jail", required_argument, 0, "mount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.mount_post_jail, 0},
{"mount-in-jail", required_argument, 0, "mount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.mount_in_jail, 0},
@@ -357,6 +378,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"mount-as-vassal", required_argument, 0, "mount filesystem before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.mount_as_vassal, 0},
{"mount-as-emperor", required_argument, 0, "mount filesystem in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.mount_as_emperor, 0},
{"umount-asap", required_argument, 0, "unmount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.umount_asap, 0},
{"umount-pre-jail", required_argument, 0, "unmount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.umount_pre_jail, 0},
{"umount-post-jail", required_argument, 0, "unmount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.umount_post_jail, 0},
{"umount-in-jail", required_argument, 0, "unmount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.umount_in_jail, 0},
@@ -377,6 +399,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 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},
@@ -400,7 +423,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
{"yml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_JSON
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
@@ -456,7 +479,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"check-mountpoint", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
{"mountpoint-check", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
{"check-mount", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
{"mount-check", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal management", 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},
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
@@ -489,6 +517,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
{"master-fifo", required_argument, 0, "enable the master fifo", uwsgi_opt_add_string_list, &uwsgi.master_fifo, UWSGI_OPT_MASTER},
#ifdef UWSGI_SSL
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
@@ -825,6 +855,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when teh daemon dies, the master dies too", 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},
#ifdef UWSGI_SSL
@@ -848,7 +879,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"dump-options", no_argument, 0, "dump the full list of available options", uwsgi_opt_true, &uwsgi.dump_options, 0},
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
{"binary-append-data", required_argument, 0, "return the content of a resource to stdout for appending to a uwsgi binary (for data:// usage)", uwsgi_opt_binary_append_data, NULL, UWSGI_OPT_IMMEDIATE},
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
{"exit", optional_argument, 0, "force exit() of the instance", uwsgi_opt_exit, NULL, UWSGI_OPT_IMMEDIATE},
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
@@ -870,138 +903,6 @@ void show_config(void) {
}
int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char *value) {
size_t i, count = 1;
size_t value_len = 0;
if (value)
value_len = strlen(value);
off_t pos = 0;
char **opt_argv;
char *tmp_val = NULL, *p = NULL;
if (strcmp(uco->name, key)) {
return 0;
}
// now count the number of args
for (i = 0; i < value_len; i++) {
if (value[i] == ' ') {
count++;
}
}
// allocate a tmp array
opt_argv = uwsgi_calloc(sizeof(char *) * count);
//make a copy of the value;
if (value_len > 0) {
tmp_val = uwsgi_str(value);
// fill the array of options
p = strtok(tmp_val, " ");
while (p) {
opt_argv[pos] = p;
pos++;
p = strtok(NULL, " ");
}
}
else {
// no argument specified
opt_argv[0] = "";
}
#ifdef UWSGI_DEBUG
uwsgi_log("found custom option %s with %d args\n", key, count);
#endif
// now make a copy of the option template
char *tmp_opt = uwsgi_str(uco->value);
// split it
p = strtok(tmp_opt, ";");
while (p) {
char *equal = strchr(p, '=');
if (!equal)
goto clear;
*equal = '\0';
// build the key
char *new_key = uwsgi_str(p);
for (i = 0; i < count; i++) {
char *old_key = new_key;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
if (new_key != old_key)
free(old_key);
free(placeholder);
}
// build the value
char *new_value = uwsgi_str(equal + 1);
for (i = 0; i < count; i++) {
char *old_value = new_value;
char *tmp_num = uwsgi_num2str(i + 1);
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
free(tmp_num);
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
if (new_value != old_value)
free(old_value);
free(placeholder);
}
// we can ignore its return value
(void) uwsgi_manage_opt(new_key, new_value);
p = strtok(NULL, ";");
}
clear:
free(tmp_val);
free(tmp_opt);
free(opt_argv);
return 1;
}
int uwsgi_manage_opt(char *key, char *value) {
struct uwsgi_option *op = uwsgi.options;
while (op->name) {
if (!strcmp(key, op->name)) {
op->func(key, value, op->data);
return 1;
}
op++;
}
struct uwsgi_custom_option *uco = uwsgi.custom_options;
while (uco) {
if (uwsgi_manage_custom_option(uco, key, value)) {
return 1;
}
uco = uco->next;
}
return 0;
}
void uwsgi_configure() {
int i;
// and now apply the remaining configs
restart:
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
uwsgi.dirty_config = 0;
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
if (uwsgi.exported_opts[i]->configured == 0 && uwsgi.autoload) {
uwsgi.dirty_config = uwsgi_try_autoload(uwsgi.exported_opts[i]->key);
}
if (uwsgi.dirty_config)
goto restart;
}
}
void config_magic_table_fill(char *filename, char **magic_table) {
char *tmp = NULL;
@@ -1041,8 +942,11 @@ void config_magic_table_fill(char *filename, char **magic_table) {
fullname = minimal_name;
}
magic_table['b'] = uwsgi.binary_path;
magic_table['p'] = fullname;
magic_table['s'] = uwsgi_get_last_char(fullname, '/') + 1;
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
if (magic_table['d'][strlen(magic_table['d']) - 1] == '/') {
tmp = magic_table['d'] + (strlen(magic_table['d']) - 1);
@@ -1051,6 +955,23 @@ void config_magic_table_fill(char *filename, char **magic_table) {
#endif
*tmp = 0;
}
// clear optional vars
magic_table['c'] = "";
magic_table['e'] = "";
magic_table['n'] = magic_table['s'];
magic_table['0'] = "";
magic_table['1'] = "";
magic_table['2'] = "";
magic_table['3'] = "";
magic_table['4'] = "";
magic_table['5'] = "";
magic_table['6'] = "";
magic_table['7'] = "";
magic_table['8'] = "";
magic_table['9'] = "";
if (uwsgi_get_last_char(magic_table['d'], '/')) {
magic_table['c'] = uwsgi_str(uwsgi_get_last_char(magic_table['d'], '/') + 1);
if (magic_table['c'][strlen(magic_table['c']) - 1] == '/') {
@@ -1060,26 +981,45 @@ void config_magic_table_fill(char *filename, char **magic_table) {
int base = '0';
char *to_split = uwsgi_str(magic_table['d']);
char *p = strtok(to_split, "/");
while (p && base <= '9') {
magic_table[base] = p;
base++;
p = strtok(NULL, "/");
char *p, *ctx = NULL;
uwsgi_foreach_token(to_split, "/", p, ctx) {
if (base <= '9') {
magic_table[base] = p;
base++;
}
else {
break;
}
}
if (tmp)
*tmp = '/';
if (uwsgi_get_last_char(filename, '.'))
magic_table['e'] = uwsgi_get_last_char(filename, '.') + 1;
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['e'] = uwsgi_get_last_char(magic_table['s'], '.') + 1;
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
reuse:
magic_table['x'] = "";
if (section) {
magic_table['x'] = section+1;
*section = ':';
}
// first round ?
if (!uwsgi.magic_table_first_round) {
magic_table['O'] = magic_table['o'];
magic_table['D'] = magic_table['d'];
magic_table['S'] = magic_table['s'];
magic_table['P'] = magic_table['p'];
magic_table['C'] = magic_table['c'];
magic_table['E'] = magic_table['e'];
magic_table['N'] = magic_table['n'];
magic_table['X'] = magic_table['x'];
uwsgi.magic_table_first_round = 1;
}
}
int find_worker_id(pid_t pid) {
@@ -1217,6 +1157,28 @@ void kill_them_all(int signum) {
uwsgi_destroy_processes();
}
// gracefully destroy
void gracefully_kill_them_all(int signum) {
if (uwsgi_instance_is_dying) return;
uwsgi.status.gracefully_destroying = 1;
// unsubscribe if needed
uwsgi_unsubscribe_all();
uwsgi_log_verbose("graceful shutdown triggered...\n");
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0) {
uwsgi_curse(i, SIGHUP);
}
}
uwsgi_destroy_processes();
}
// graceful reload
void grace_them_all(int signum) {
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
@@ -1437,6 +1399,15 @@ void what_i_am_doing() {
int unconfigured_hook(struct wsgi_request *wsgi_req) {
if (wsgi_req->uh->modifier1 == 0 && !uwsgi.no_default_app) {
if (uwsgi_apps_cnt > 0 && wsgi_req->app_id > -1 && wsgi_req->app_id < uwsgi.max_apps) {
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
if (uwsgi.p[ua->modifier1]->request != unconfigured_hook) {
wsgi_req->uh->modifier1 = ua->modifier1;
return uwsgi.p[ua->modifier1]->request(wsgi_req);
}
}
}
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
return -1;
}
@@ -1922,6 +1893,9 @@ int main(int argc, char *argv[], char *envp[]) {
init_magic_table(uwsgi.magic_table);
// initialize schemes
uwsgi_setup_schemes();
// initialize the clock
uwsgi_register_clock(&uwsgi_unix_clock);
uwsgi_set_clock("unix");
@@ -2046,6 +2020,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
uwsgi.magic_table['V'] = UWSGI_VERSION;
uwsgi.magic_table['['] = "\033";
// you can embed a ini file in the uWSGi binary with default options
#ifdef UWSGI_EMBED_CONFIG
@@ -2076,6 +2051,35 @@ int main(int argc, char *argv[], char *envp[]) {
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
// fixup cwd
if (uwsgi.force_cwd) uwsgi.cwd = uwsgi.force_cwd;
// run "asap" hooks
uwsgi_hooks_run(uwsgi.hook_asap, "asap", 1);
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.mount_asap) {
uwsgi_log("mounting \"%s\" (asap)...\n", usl->value);
if (uwsgi_mount_hook(usl->value)) exit(1);
}
uwsgi_foreach(usl, uwsgi.umount_asap) {
uwsgi_log("un-mounting \"%s\" (asap)...\n", usl->value);
if (uwsgi_umount_hook(usl->value)) exit(1);
}
uwsgi_foreach(usl, uwsgi.exec_asap) {
uwsgi_log("running \"%s\" (asap)...\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_asap) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
}
// manage envdirs ASAP
uwsgi_envdirs(uwsgi.envdirs);
@@ -2126,6 +2130,7 @@ int main(int argc, char *argv[], char *envp[]) {
// setup cheaper algos
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
uwsgi_register_cheaper_algo("manual", uwsgi_cheaper_algo_manual);
// setup imperial monitors
uwsgi_register_imperial_monitor("dir", uwsgi_imperial_monitor_directory_init, uwsgi_imperial_monitor_directory);
@@ -2293,7 +2298,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
}
@@ -2321,7 +2326,7 @@ int main(int argc, char *argv[], char *envp[]) {
// TODO pluginize basic Linux namespace support
#ifdef __linux__
#if defined(__linux__) && !defined(__ia64__)
if (uwsgi.ns) {
linux_namespace_start((void *) uwsgi.argv);
// never here
@@ -2329,7 +2334,7 @@ int main(int argc, char *argv[], char *envp[]) {
else {
#endif
uwsgi_start((void *) uwsgi.argv);
#ifdef __linux__
#if defined(__linux__) && !defined(__ia64__)
}
#endif
@@ -2346,9 +2351,11 @@ int uwsgi_start(void *v_argv) {
#ifdef __linux__
uwsgi_set_cgroup();
#if !defined(__ia64__)
if (uwsgi.ns) {
linux_namespace_jail();
}
#endif
#endif
uwsgi_hooks_run(uwsgi.hook_in_jail, "in-jail", 1);
@@ -2512,7 +2519,7 @@ int uwsgi_start(void *v_argv) {
if (uwsgi.async > 1) {
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
uwsgi_log_initial("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
uwsgi.rl.rlim_cur = uwsgi.async;
uwsgi.rl.rlim_max = uwsgi.async;
if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
@@ -2524,7 +2531,7 @@ int uwsgi_start(void *v_argv) {
uwsgi.async = (int) uwsgi.max_fd;
}
}
uwsgi_log("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
uwsgi_log_initial("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
// optimization, this array maps file descriptor to requests
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
@@ -2535,16 +2542,16 @@ int uwsgi_start(void *v_argv) {
#endif
if (uwsgi.vhost) {
uwsgi_log("VirtualHosting mode enabled.\n");
uwsgi_log_initial("VirtualHosting mode enabled.\n");
}
// setup locking
uwsgi_setup_locking();
if (uwsgi.use_thunder_lock) {
uwsgi_log("thunder lock: enabled\n");
uwsgi_log_initial("thunder lock: enabled\n");
}
else {
uwsgi_log("thunder lock: disabled (you can enable it with --thunder-lock)\n");
uwsgi_log_initial("thunder lock: disabled (you can enable it with --thunder-lock)\n");
}
// allocate rpc structures
@@ -2699,7 +2706,8 @@ int uwsgi_start(void *v_argv) {
!uwsgi.emperor &&
!uwsgi.command_mode &&
!uwsgi.daemons_cnt &&
!uwsgi.crons
!uwsgi.crons &&
!uwsgi.emperor_proxy
#ifdef UWSGI_SSL
&& !uwsgi.legions
#endif
@@ -3040,6 +3048,7 @@ next2:
}
}
// END OF INITIALIZATION
// !!! from now on, we could be in the master or in a worker !!!
@@ -3216,8 +3225,8 @@ void uwsgi_worker_run() {
// eventually remap plugins
if (uwsgi.remap_modifier) {
char *map = strtok(uwsgi.remap_modifier, ",");
while (map != NULL) {
char *map, *ctx = NULL;
uwsgi_foreach_token(uwsgi.remap_modifier, ",", map, ctx) {
char *colon = strchr(map, ':');
if (colon) {
colon[0] = 0;
@@ -3226,7 +3235,6 @@ void uwsgi_worker_run() {
uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
}
map = strtok(NULL, ",");
}
}
@@ -3379,7 +3387,26 @@ void build_options() {
pos += c;
}
}
// custom_options are not added to uwsgi.options
uco = uwsgi.custom_options;
while (uco) {
uwsgi.options[pos].name = uco->name;
if (uco->has_args) {
uwsgi.options[pos].type = required_argument;
}
else {
uwsgi.options[pos].type = no_argument;
}
// custom options should be immediate
uwsgi.options[pos].flags = UWSGI_OPT_IMMEDIATE;
// help shows the option definition
uwsgi.options[pos].help = uco->value;
uwsgi.options[pos].data = uco;
uwsgi.options[pos].func = uwsgi_opt_custom;
pos++;
uco = uco->next;
}
pos = 0;
@@ -3418,21 +3445,6 @@ void build_options() {
op++;
pos++;
}
uco = uwsgi.custom_options;
while (uco) {
uwsgi.long_options[pos].name = uco->name;
if (uco->has_args) {
uwsgi.long_options[pos].has_arg = required_argument;
}
else {
uwsgi.long_options[pos].has_arg = no_argument;
}
uwsgi.long_options[pos].flag = 0;
// add 1000 to avoid short_options collision
uwsgi.long_options[pos].val = 1000 + pos;
pos++;
uco = uco->next;
}
}
/*
@@ -3859,6 +3871,13 @@ void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
uwsgi_sock->proto_name = protocol;
}
void uwsgi_opt_add_socket_no_defer(char *opt, char *value, void *protocol) {
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
uwsgi_sock->proto_name = protocol;
uwsgi_sock->no_defer = 1;
}
void uwsgi_opt_add_lazy_socket(char *opt, char *value, void *protocol) {
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
uwsgi_sock->proto_name = protocol;
@@ -3867,7 +3886,7 @@ void uwsgi_opt_add_lazy_socket(char *opt, char *value, void *protocol) {
}
void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
void uwsgi_opt_set_placeholder(char *opt, char *value, void *ph) {
char *p = strchr(value, '=');
if (!p) {
@@ -3876,7 +3895,7 @@ void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
}
p[0] = 0;
add_exported_option(uwsgi_str(value), p + 1, 1);
add_exported_option_do(uwsgi_str(value), p + 1, 0, ph ? 1 : 0);
p[0] = '=';
}
@@ -3934,6 +3953,14 @@ void uwsgi_opt_set_umask(char *opt, char *value, void *mode) {
}
void uwsgi_opt_exit(char *opt, char *value, void *none) {
int exit_code = 1;
if (value) {
exit_code = atoi(value);
}
exit(exit_code);
}
void uwsgi_opt_print(char *opt, char *value, void *str) {
if (str) {
fprintf(stdout, "%s\n", (char *) str);
@@ -3958,7 +3985,18 @@ void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
#ifdef UWSGI_CAP
void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
uwsgi_build_cap(value);
uwsgi.cap_count = uwsgi_build_cap(value, &uwsgi.cap);
if (uwsgi.cap_count == 0) {
uwsgi_log("[security] empty capabilities mask !!!\n");
exit(1);
}
}
void uwsgi_opt_set_emperor_cap(char *opt, char *value, void *none) {
uwsgi.emperor_cap_count = uwsgi_build_cap(value, &uwsgi.emperor_cap);
if (uwsgi.emperor_cap_count == 0) {
uwsgi_log("[security] empty capabilities mask !!!\n");
exit(1);
}
}
#endif
#ifdef __linux__
@@ -4000,8 +4038,8 @@ void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
char *plugins_list = uwsgi_concat2(value, "");
char *p = strtok(plugins_list, ",");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(plugins_list, ",", p, ctx) {
#ifdef UWSGI_DEBUG
uwsgi_debug("loading plugin %s\n", p);
#endif
@@ -4012,7 +4050,6 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
uwsgi_log("unable to load plugin \"%s\"\n", p);
exit(1);
}
p = strtok(NULL, ",");
}
free(p);
free(plugins_list);
@@ -4229,39 +4266,45 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
void uwsgi_opt_load(char *opt, char *filename, void *none) {
// here we need to avoid setting upper magic vars
int orig_magic = uwsgi.magic_table_first_round;
uwsgi.magic_table_first_round = 1;
if (uwsgi_endswith(filename, ".ini")) {
uwsgi_opt_load_ini(opt, filename, none);
return;
goto end;
}
#ifdef UWSGI_XML
if (uwsgi_endswith(filename, ".xml")) {
uwsgi_opt_load_xml(opt, filename, none);
return;
goto end;
}
#endif
#ifdef UWSGI_YAML
if (uwsgi_endswith(filename, ".yaml")) {
uwsgi_opt_load_yml(opt, filename, none);
return;
goto end;
}
if (uwsgi_endswith(filename, ".yml")) {
uwsgi_opt_load_yml(opt, filename, none);
return;
goto end;
}
#endif
#ifdef UWSGI_JSON
if (uwsgi_endswith(filename, ".json")) {
uwsgi_opt_load_json(opt, filename, none);
return;
goto end;
}
if (uwsgi_endswith(filename, ".js")) {
uwsgi_opt_load_json(opt, filename, none);
return;
goto end;
}
#endif
// fallback to pluggable system
uwsgi_opt_load_config(opt, filename, none);
end:
uwsgi.magic_table_first_round = orig_magic;
}
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
@@ -4501,3 +4544,32 @@ void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
exit(0);
}
void uwsgi_update_pidfiles() {
if (uwsgi.pidfile) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
}
void uwsgi_opt_binary_append_data(char *opt, char *value, void *none) {
size_t size;
char *buf = uwsgi_open_and_read(value, &size, 0, NULL);
uint64_t file_len = size;
if (write(1, buf, size) != (ssize_t) size) {
uwsgi_error("uwsgi_opt_binary_append_data()/write()");
exit(1);
}
if (write(1, &file_len, 8) != 8) {
uwsgi_error("uwsgi_opt_binary_append_data()/write()");
exit(1);
}
exit(0);
}
+3
View File
@@ -151,6 +151,8 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
}
/* We can safely free resources */
if (colon) colon[0] = ':';
xmlFreeDoc(doc);
xmlCleanupParser();
@@ -267,6 +269,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
} while (!done);
if (colon) colon[0] = ':';
// we can safely free, as we have a copy of datas
XML_ParserFree(parser);
+1
View File
@@ -280,6 +280,7 @@ next:
}
#endif
if (colon) colon[0] = ':';
}
+3 -2
View File
@@ -123,12 +123,13 @@ int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t
if (!gzipped0) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
free(gzipped0);
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
if (uwsgi_buffer_u32le(ub, crc32)) goto end2;
if (uwsgi_buffer_u32le(ub, len)) goto end2;
deflateEnd(z);
return 0;
end:
if (gzipped0) free(gzipped0);
end2:
deflateEnd(z);
return -1;
}
View File
+2 -3
View File
@@ -71,8 +71,8 @@ static void carbon_post_init() {
u_server->healthy = 1;
u_server->errors = 0;
char *p = strtok(usl->value, ":");
while (p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(usl->value, ":", p, ctx) {
if (!u_server->hostname) {
u_server->hostname = uwsgi_str(p);
}
@@ -81,7 +81,6 @@ static void carbon_post_init() {
}
else
break;
p = strtok(NULL, ":");
}
if (!u_server->hostname || !u_server->port) {
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
+2 -3
View File
@@ -828,8 +828,8 @@ clear2:
// set the start position of args in argv
i = 1;
if (helper) i = 2;
char *p = strtok(qs, "+");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(qs, "+", p, ctx) {
// create a copy for the url_decoded string
char *arg_copy = uwsgi_str(p);
uint16_t arg_copy_len = strlen(p);
@@ -838,7 +838,6 @@ clear2:
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
i++;
p = strtok(NULL, "+");
}
free(qs);
}
+4 -2
View File
@@ -13,7 +13,7 @@
extern struct uwsgi_server uwsgi;
int cheaper_backlog2_algo(void) {
int cheaper_backlog2_algo(int can_spawn) {
int i;
#ifdef __linux__
@@ -22,7 +22,9 @@ int cheaper_backlog2_algo(void) {
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
// if can_spawn == 0 we cannot spawn any new worker
// this is set to 1 if --cheaper-rss-limit-* options are used and running workers are exceeding resources limit
if (can_spawn && backlog > (int)uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
+12 -12
View File
@@ -142,7 +142,7 @@ int spawn_emergency_worker(int backlog) {
#endif
int cheaper_busyness_algo(void) {
int cheaper_busyness_algo(int can_spawn) {
int i;
// we use microseconds
@@ -243,11 +243,12 @@ int cheaper_busyness_algo(void) {
uwsgi_cheaper_busyness_global.tolerance_counter = 0;
int decheaped = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step) break;
if (can_spawn) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step) break;
}
}
}
@@ -271,15 +272,15 @@ int cheaper_busyness_algo(void) {
uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n",
uwsgi.cheaper_overload, avg_busyness, decheaped);
} else {
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n",
uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc);
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers available with current limits (%d)\n",
uwsgi.cheaper_overload, avg_busyness, active_workers);
}
// return the maximum number of workers to spawn
return decheaped;
#ifdef __linux__
} else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
} else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
return spawn_emergency_worker(backlog);
#endif
@@ -347,14 +348,14 @@ int cheaper_busyness_algo(void) {
}
#ifdef __linux__
else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
// we check for backlog overload every cycle
return spawn_emergency_worker(backlog);
}
else if (backlog > 0) {
if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
// backlog was > 0 last time, check timestamp and spawn workers if needed
if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
if (can_spawn && (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000);
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
return spawn_emergency_worker(backlog);
@@ -391,4 +392,3 @@ struct uwsgi_plugin cheaper_busyness_plugin = {
.options = uwsgi_cheaper_busyness_options,
};
+296
View File
@@ -0,0 +1,296 @@
/*
uWSGI forkpty-router
can use the uwsgi protocol, modifier2 means:
0 -> stdin
1-99 -> UNIX signal
100 -> window rows (pktsize is the window size)
101 -> window cols (pktsize is the window size)
*/
#include <uwsgi.h>
#include "../corerouter/cr.h"
extern struct uwsgi_server uwsgi;
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
#endif
#ifndef __FreeBSD__
#include <utmp.h>
#endif
static struct uwsgi_forkptyrouter {
struct uwsgi_corerouter cr;
char *cmd;
uint16_t win_rows;
uint16_t win_cols;
} ufpty;
extern struct uwsgi_server uwsgi;
struct forkptyrouter_session {
struct corerouter_session session;
// use the uwsgi protocol ?
int uwsgi;
size_t restore_size;
struct winsize w;
pid_t pid;
};
static void uwsgi_opt_forkpty_urouter(char *opt, char *value, void *cr) {
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, ucr->name);
ugs->no_defer = 1;
ugs->mode = 1;
ucr->has_sockets++;
}
static struct uwsgi_option forkptyrouter_options[] = {
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
{"forkptyurouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
{"forkpty-urouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
{"forkptyrouter-rows", required_argument, 0, "set forkptyrouter default pty window rows", uwsgi_opt_set_16bit, &ufpty.win_rows, 0},
{"forkptyrouter-cols", required_argument, 0, "set forkptyrouter default pty window cols", uwsgi_opt_set_16bit, &ufpty.win_cols, 0},
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
{"forkptyrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufpty.cr.fallback, 0},
{"forkptyrouter-events", required_argument, 0, "set the maximum number of concufptyent events", uwsgi_opt_set_int, &ufpty.cr.nevents, 0},
{"forkptyrouter-cheap", no_argument, 0, "run the forkptyrouter in cheap mode", uwsgi_opt_true, &ufpty.cr.cheap, 0},
{"forkptyrouter-timeout", required_argument, 0, "set forkptyrouter timeout", uwsgi_opt_set_int, &ufpty.cr.socket_timeout, 0},
{"forkptyrouter-stats", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-stats-server", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-ss", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
{"forkptyrouter-harakiri", required_argument, 0, "enable forkptyrouter harakiri", uwsgi_opt_set_int, &ufpty.cr.harakiri, 0},
{0, 0, 0, 0, 0, 0, 0},
};
// write to backend
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
ssize_t len = cr_write(peer, "fpty_instance_write()");
// end on empty write
if (!len) return 0;
// the chunk has been sent, start (again) reading from client and instances
if (cr_write_complete(peer)) {
// reset the buffer
if (fpty_session->uwsgi) {
if (uwsgi_buffer_decapitate(peer->out, peer->out->pos)) return -1;
peer->out->pos = fpty_session->restore_size;
}
else {
peer->out->pos = 0;
}
cr_reset_hooks(peer);
}
return len;
}
// write to client
static ssize_t fpty_write(struct corerouter_peer *main_peer) {
ssize_t len = cr_write(main_peer, "fpty_write()");
// end on empty write
if (!len) return 0;
// ok this response chunk is sent, let's start reading again
if (cr_write_complete(main_peer)) {
// reset the buffer
main_peer->out->pos = 0;
cr_reset_hooks(main_peer);
}
return len;
}
static ssize_t fpty_parse_uwsgi(struct corerouter_peer *peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
for(;;) {
if (peer->in->pos < 4) return 0;
struct uwsgi_header *uh = (struct uwsgi_header *) peer->in->buf;
uint16_t pktsize = uh->pktsize;
switch(uh->modifier2) {
case 0:
// stdin
if ((size_t) (pktsize+4) > peer->in->pos) return 0;
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
return pktsize;
case 100:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
fpty_session->w.ws_row = pktsize;
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
// rows
break;
case 101:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
fpty_session->w.ws_col = pktsize;
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
// cols
break;
default:
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
// send signal
kill(fpty_session->pid, uh->modifier2);
break;
}
}
return 0;
}
// read from backend
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
ssize_t len = cr_read(peer, "fpty_instance_read()");
if (!len) return 0;
// set the input buffer as the main output one
peer->session->main_peer->out = peer->in;
peer->session->main_peer->out_pos = 0;
cr_write_to_main(peer, fpty_write);
return len;
}
// read from client
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) main_peer->session;
ssize_t len = cr_read(main_peer, "fpty_read()");
if (!len) return 0;
if (fpty_session->uwsgi) {
ssize_t rlen = fpty_parse_uwsgi(main_peer);
if (rlen < 0) return -1;
if (rlen == 0) return 1;
fpty_session->restore_size = main_peer->in->pos - rlen;
main_peer->session->peers->out = main_peer->in;
main_peer->session->peers->out->pos = rlen;
}
else {
main_peer->session->peers->out = main_peer->in;
}
main_peer->session->peers->out_pos = 0;
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
return len;
}
static void fpty_session_close(struct corerouter_session *cs) {
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
if (fpty_session->pid > 0) {
int waitpid_status = 0;
if (waitpid(fpty_session->pid, &waitpid_status, WNOHANG) < 0) {
uwsgi_error("fpty_session_close()/waitpid()");
}
}
}
// allocate a new session
static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
// set default read hook
cs->main_peer->last_hook_read = fpty_read;
// wait4() on close
cs->close = fpty_session_close;
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
if (ugs->mode == 1) {
fpty_session->uwsgi = 1;
}
// default terminal size
fpty_session->w.ws_row = ufpty.win_rows ? ufpty.win_rows : 24;
fpty_session->w.ws_col = ufpty.win_cols ? ufpty.win_cols : 80;
// add a new peer
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
// on new connection generate a new pty
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
if (fpty_session->pid < 0) {
uwsgi_error("forkpty()");
return -1;
}
else if (fpty_session->pid == 0) {
if (ufpty.cmd) {
char *space = strchr(ufpty.cmd, ' ');
if (space) {
char *argv[4];
argv[0] = uwsgi_binsh();
argv[1] = "-c";
argv[2] = ufpty.cmd;
argv[3] = NULL;
execv(argv[0], argv);
}
else {
char *argv[2];
argv[0] = ufpty.cmd;
argv[1] = NULL;
execv(argv[0], argv);
}
}
else {
char *argv[2];
argv[0] = "/bin/sh";
argv[1] = NULL;
execv(argv[0], argv);
}
// never here;
uwsgi_error("forkptyrouter_alloc_session()/execv()");
exit(1);
}
ucr->cr_table[peer->fd] = peer;
cr_reset_hooks_and_read(peer, fpty_instance_read);
return 0;
}
static int forkptyrouter_init() {
ufpty.cr.session_size = sizeof(struct forkptyrouter_session);
ufpty.cr.alloc_session = forkptyrouter_alloc_session;
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufpty);
return 0;
}
static void forkptyrouter_setup() {
ufpty.cr.name = uwsgi_str("uWSGI forkptyrouter");
ufpty.cr.short_name = uwsgi_str("forkptyrouter");
}
struct uwsgi_plugin forkptyrouter_plugin = {
.name = "forkptyrouter",
.options = forkptyrouter_options,
.init = forkptyrouter_init,
.on_load = forkptyrouter_setup
};
+8
View File
@@ -0,0 +1,8 @@
NAME='forkptyrouter'
CFLAGS = []
LDFLAGS = []
LIBS = []
REQUIRES = ['corerouter']
GCC_LIST = ['forkptyrouter']
+4 -6
View File
@@ -123,10 +123,9 @@ static void uwsgi_gccgo_initialize() {
int argc = 0;
if (ugccgo.args) {
char *argv_list = uwsgi_str(ugccgo.args);
char *p = strtok(argv_list, " ");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(argv_list, " ", p, ctx) {
argc++;
p = strtok(NULL, " ");
}
free(argv_list);
}
@@ -134,12 +133,11 @@ static void uwsgi_gccgo_initialize() {
if (argc > 0) {
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
char *argv_list = uwsgi_str(ugccgo.args);
char *p = strtok(argv_list, " ");
char *p, *ctx = NULL;
int n = 0;
while(p) {
uwsgi_foreach_token(argv_list, " ", p, ctx) {
argv[n] = p;
n++;
p = strtok(NULL, " ");
}
runtime_args(argc, argv);
}
+2 -3
View File
@@ -117,13 +117,12 @@ connect:
static void uwsgi_glusterfs_connect_do(struct uwsgi_app *ua) {
char *servers = uwsgi_str(ua->callable);
char *p = strtok(servers, ";");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(servers, ";", p, ctx) {
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);
+3 -1
View File
@@ -7,12 +7,14 @@ JVM_INCPATH = None
JVM_LIBPATH = None
operating_system = os.uname()[0].lower()
arch = os.uname()[4]
arch = os.uname()[4].lower()
if arch in ('i686', 'x86', 'x86_32'):
arch = 'i386'
elif arch in ('x86_64',):
arch = 'amd64'
elif arch.startswith('arm'):
arch = 'arm'
# try to detect the JVM
if operating_system == 'darwin':
+4 -6
View File
@@ -181,10 +181,9 @@ static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(list2, " ", p, ctx) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
@@ -228,10 +227,9 @@ static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
char *p, *ctx = NULL;
uwsgi_foreach_token(list2, " ", p, ctx) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
+71
View File
@@ -0,0 +1,71 @@
#include <uwsgi.h>
#include <ffi.h>
ffi_type *uwsgi_libffi_get_type(char *what, size_t *skip) {
if (!uwsgi_startswith(what, "int:", 4)) { *skip = 4; return &ffi_type_sint32;}
if (!uwsgi_startswith(what, "sint:", 5)) { *skip = 5; return &ffi_type_sint32;}
if (!uwsgi_startswith(what, "uint:", 5)) { *skip = 5;return &ffi_type_uint32;}
return &ffi_type_pointer;
}
void *uwsgi_libffi_get_value(char *what, ffi_type *t) {
if (t == &ffi_type_sint32) {
int32_t *num = uwsgi_malloc(sizeof(int32_t));
*num = atoi(what);
return num;
}
return NULL;
}
static int uwsgi_libffi_hook(char *arg) {
size_t argc = 0;
size_t i;
char **argv = uwsgi_split_quoted(arg, strlen(arg), " \t", &argc);
if (!argc) goto end;
void *func = dlsym(RTLD_DEFAULT, argv[0]);
if (!func) goto destroy;
ffi_cif cif;
ffi_type **args_type = (ffi_type **) uwsgi_malloc(sizeof(ffi_type) * (argc-1));
void **values = uwsgi_malloc(sizeof(void*) * (argc-1));
for(i=1;i<argc;i++) {
size_t skip = 0;
args_type[i-1] = uwsgi_libffi_get_type(argv[i], &skip);
void *v = uwsgi_libffi_get_value(argv[i] + skip, args_type[i-1]);
values[i-1] = v ? v : &argv[i];
uwsgi_log("%d = %s %p\n", i, argv[i], values[i-1]);
}
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, argc-1, &ffi_type_sint64, args_type) == FFI_OK) {
int64_t rc = 0;
uwsgi_log("ready to call\n");
ffi_call(&cif, func, &rc, values);
}
uwsgi_log("ready to call2\n");
for(i=0;i<(argc-1);i++) {
char **ptr = (char **) values[i];
if (*ptr != argv[i+1]) {
free(values[i]);
}
}
free(args_type);
free(values);
destroy:
for(i=0;i<argc;i++) {
free(argv[i]);
}
end:
free(argv);
return -1;
}
static void uwsgi_libffi_setup() {
uwsgi_register_hook("ffi", uwsgi_libffi_hook);
}
struct uwsgi_plugin libffi_plugin = {
.name = "libffi",
.on_load = uwsgi_libffi_setup,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='libffi'
CFLAGS=[]
LDFLAGS=[]
LIBS=['-lffi']
GCC_LIST=['libffi']
+53
View File
@@ -0,0 +1,53 @@
#include <uwsgi.h>
#include <libtcc.h>
uint64_t uwsgi_libtcc_counter = 0;
static int uwsgi_libtcc_hook(char *arg) {
char *func_base = "uwsgi_libtcc_func";
size_t func_len = strlen(func_base) + sizeof(UMAX64_STR);
char *func_name = uwsgi_malloc(func_len);
if (snprintf(func_name, func_len, "%s%llu", func_base, uwsgi_libtcc_counter) < (int) strlen(func_base)) {
free(func_name);
return -1;
}
uwsgi_libtcc_counter++;
size_t source_len = 64 + func_len + strlen(arg);
char *source = uwsgi_malloc(source_len);
if (snprintf(source, source_len, "void %s() { %s ;}", func_name, arg) < (int) ( strlen(func_base) + strlen(arg))) {
free(func_name);
free(source);
return -1;
}
TCCState *s = tcc_new();
if (tcc_compile_string(s, source)) goto error;
if (tcc_relocate(s, TCC_RELOCATE_AUTO)) goto error;
void (*func)() = tcc_get_symbol(s, func_name);
if (!func) goto error;
free(func_name);
free(source);
// call the function
func();
tcc_delete(s);
return 0;
error:
free(func_name);
free(source);
tcc_delete(s);
return -1;
}
static void uwsgi_libtcc_setup() {
uwsgi_register_hook("tcc", uwsgi_libtcc_hook);
}
struct uwsgi_plugin libtcc_plugin = {
.name = "libtcc",
.on_load = uwsgi_libtcc_setup,
};
+5
View File
@@ -0,0 +1,5 @@
NAME='libtcc'
CFLAGS=[]
LDFLAGS=[]
LIBS=['-ltcc']
GCC_LIST=['libtcc']
+18 -2
View File
@@ -1,6 +1,6 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!ul->configured) {
if (ul->arg) {
@@ -18,8 +18,24 @@ ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
}
static ssize_t uwsgi_fd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!ul->configured) {
ul->fd = -1;
if (ul->arg) ul->fd = atoi(ul->arg);
ul->configured = 1;
}
if (ul->fd >= 0) {
return write(ul->fd, message, len);
}
return 0;
}
void uwsgi_file_logger_register() {
uwsgi_register_logger("file", uwsgi_file_logger);
uwsgi_register_logger("fd", uwsgi_fd_logger);
}
struct uwsgi_plugin logfile_plugin = {
+60
View File
@@ -0,0 +1,60 @@
#include <uwsgi.h>
/*
The pipe logger
Author: INADA Naoki
every log line is sent to the stdin of an external process
Example:
req-logger = pipe:/usr/local/bin/mylogger
*/
static ssize_t uwsgi_pipe_logger(struct uwsgi_logger *ul, char *message, size_t len) {
if (!ul->configured) {
if (ul->arg) {
int pipefd[2];
// retry later...
if (pipe(pipefd) < 0) return -1;
pid_t pid = fork();
if (pid < 0) return -1;
if (pid > 0) {
close(pipefd[0]);
ul->fd = pipefd[1];
}
else {
// child
setsid();
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
uwsgi_exec_command_with_args(ul->arg);
exit(1); // if here something seriously failed
}
}
ul->configured = 1;
}
int err = write(ul->fd, message, len);
// on failed writes, re-configure the logger
if (err <= 0) {
close(ul->fd);
ul->configured = 0;
return err;
}
return 0;
}
static void uwsgi_pipe_logger_register() {
uwsgi_register_logger("pipe", uwsgi_pipe_logger);
}
struct uwsgi_plugin logpipe_plugin = {
.name = "logpipe",
.on_load = uwsgi_pipe_logger_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='logpipe'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['logpipe']
+1
View File
@@ -84,6 +84,7 @@ struct uwsgi_option uwsgi_mono_options[] = {
{"mono-assembly", required_argument, 0, "load the specified main assembly (default: uwsgi.dll)", uwsgi_opt_set_str, &umono.assembly_name, 0},
{"mono-exec", required_argument, 0, "exec the specified assembly just before app loading", uwsgi_opt_add_string_list, &umono.exec, 0},
{"mono-index", required_argument, 0, "add an asp.net index file", uwsgi_opt_add_string_list, &umono.index, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static MonoString *uwsgi_mono_method_GetFilePath(MonoObject *this) {
+2 -3
View File
@@ -164,8 +164,8 @@ int uwsgi_buffer_msgpack_false(struct uwsgi_buffer *ub) {
static char *uwsgi_msgpack_log_encoder(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
char *buf = NULL;
if (!ule->configured) {
char *p = strtok(ule->args, "|");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(ule->args, "|", p, ctx) {
char *colon = strchr(p, ':');
if (colon) *colon = 0;
// find the type of item
@@ -259,7 +259,6 @@ static char *uwsgi_msgpack_log_encoder(struct uwsgi_log_encoder *ule, char *msg,
}
if (colon) *colon = ':';
p = strtok(NULL, "|");
}
ule->configured = 1;
}
+8 -9
View File
@@ -5,25 +5,24 @@ NAME='php'
ld_run_path = None
PHPPATH = 'php-config'
try:
phpdir = os.environ['UWSGICONFIG_PHPDIR']
phpdir = os.environ.get('UWSGICONFIG_PHPDIR')
if phpdir:
ld_run_path = "%s/lib" % phpdir
PHPPATH = "%s/bin/php-config" % phpdir
except:
pass
try:
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
except:
pass
PHPPATH = os.environ.get('UWSGICONFIG_PHPPATH', PHPPATH)
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
if ld_run_path:
LDFLAGS.append('-L%s' % ld_run_path)
os.environ['LD_RUN_PATH'] = ld_run_path
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
phplibdir = os.environ.get('UWSGICONFIG_PHPLIBDIR')
if phplibdir:
LIBS.append('-Wl,-rpath=%s' % phplibdir)
GCC_LIST = ['php_plugin']
+7
View File
@@ -53,6 +53,11 @@ struct uwsgi_perl {
struct uwsgi_string_list *exec;
struct uwsgi_string_list *exec_post_fork;
int auto_reload;
time_t last_auto_reload;
struct uwsgi_string_list *auto_reload_ignore;
HV *auto_reload_hash;
};
void init_perl_embedded_module(void);
@@ -70,3 +75,5 @@ PerlInterpreter *uwsgi_perl_new_interpreter(void);
int uwsgi_perl_mule(char *);
void uwsgi_perl_run_hook(SV *);
void uwsgi_perl_exec(char *);
void uwsgi_perl_check_auto_reload(void);
+8 -30
View File
@@ -260,7 +260,6 @@ static void uwsgi_perl_free_stashes(void) {
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
struct stat st;
int i;
SV **callables;
@@ -268,31 +267,14 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
// prepare for $0
uperl.embedding[1] = app_name;
int fd = open(app_name, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(app_name);
goto clear2;
}
size_t size;
char *buf = uwsgi_open_and_read(app_name, &size, 1, NULL);
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
close(fd);
goto clear2;
if (uwsgi_file_exists(app_name)) {
// prepare for $0 (if the file is local)
uperl.embedding[1] = app_name;
}
char *buf = uwsgi_calloc(st.st_size+1);
if (read(fd, buf, st.st_size) != st.st_size) {
uwsgi_error("read()");
close(fd);
free(buf);
goto clear2;
}
close(fd);
// the first (default) app, should always be loaded in the main interpreter
if (interpreters == NULL) {
if (uwsgi_apps_cnt) {
@@ -309,10 +291,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
}
}
if (!interpreters) {
goto clear2;
}
if (!interpreters) goto clear2;
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
@@ -383,10 +362,9 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
AV *uperl_argv = GvAV(PL_argvgv);
if (uperl.argv_items) {
char *argv_list = uwsgi_str(uperl.argv_items);
char *p = strtok(argv_list, " ");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(argv_list, " ", p, ctx) {
av_push(uperl_argv, newSVpv(p, 0));
p = strtok(NULL, " ");
}
}
struct uwsgi_string_list *usl = uperl.argv_item;
+58
View File
@@ -23,10 +23,60 @@ struct uwsgi_option uwsgi_perl_options[] = {
{"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},
{"perl-auto-reload", required_argument, 0, "enable perl auto-reloader with the specified frequency", uwsgi_opt_set_int, &uperl.auto_reload, UWSGI_OPT_MASTER},
{"perl-auto-reload-ignore", required_argument, 0, "ignore the specified files when auto-reload is enabled", uwsgi_opt_add_string_list, &uperl.auto_reload_ignore, UWSGI_OPT_MASTER},
{0, 0, 0, 0, 0, 0, 0},
};
int uwsgi_perl_check_mtime(time_t now, HV *list, SV *key) {
// insert item with the current time
if (!hv_exists_ent(list, key, 0)) {
// useless if...
if (hv_store_ent(list, key, newSViv(now), 0)) return 0;
}
else {
// compare mtime
struct stat st;
if (stat(SvPV_nolen(key), &st)) return 0;
HE *mtime = hv_fetch_ent(list, key, 0, 0);
if (!mtime) return 0;
if (st.st_mtime > SvIV(HeVAL(mtime))) {
uwsgi_log_verbose("[perl-auto-reloader] %s has been modified !!!\n", SvPV_nolen(key));
kill(uwsgi.workers[0].pid, SIGHUP);
return 1;
}
}
return 0;
}
void uwsgi_perl_check_auto_reload() {
time_t now = uwsgi_now();
HE *he;
if (!uperl.auto_reload_hash) {
uperl.auto_reload_hash = newHV();
// useless return value
if (!SvREFCNT_inc(uperl.auto_reload_hash)) return;
}
GV *gv_inc = gv_fetchpv("INC", TRUE, SVt_PV);
if (!gv_inc) return;
HV *inc = GvHV(gv_inc);
hv_iterinit(inc);
while((he = hv_iternext(inc))) {
SV *filename = hv_iterval(inc, he);
struct uwsgi_string_list *usl;
int found = 0;
uwsgi_foreach(usl, uperl.auto_reload_ignore) {
if (!strcmp(usl->value, SvPV_nolen(filename))) {
found = 1; break;
}
}
if (found) continue;
if (uwsgi_perl_check_mtime(now, uperl.auto_reload_hash, filename)) return;
}
}
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *newobj;
@@ -563,6 +613,14 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
// clear the env
SvREFCNT_dec(wsgi_req->async_environ);
// now we can check for changed files
if (uperl.auto_reload) {
time_t now = uwsgi_now();
if (now - uperl.last_auto_reload > uperl.auto_reload) {
uwsgi_perl_check_auto_reload();
}
}
}
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
+6
View File
@@ -78,8 +78,14 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
// generate headers
for(i=0; i<=av_len(headers); i++) {
hitem = av_fetch(headers,i,0);
if (!*hitem) {
uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;
}
chitem = SvPV(*hitem, hlen);
hitem = av_fetch(headers,i+1,0);
if (!*hitem) {
uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;
}
chitem2 = SvPV(*hitem, hlen2);
if (uwsgi_response_add_header(wsgi_req, chitem, hlen, chitem2, hlen2)) return UWSGI_OK;
i++;
+54 -11
View File
@@ -1,7 +1,7 @@
#include <uwsgi.h>
#ifdef __linux__
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__)
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
@@ -21,6 +21,7 @@ struct uwsgi_pty_client {
static struct uwsgi_pty {
char *addr;
char *remote;
char *uremote;
int queue;
int server_fd;
int master_fd;
@@ -76,9 +77,10 @@ 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-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, UWSGI_OPT_NO_INITIAL},
{"pty-uconnect", required_argument, 0, "connect the current terminal to a pty server (using uwsgi protocol)", uwsgi_opt_set_str, &upty.uremote, UWSGI_OPT_NO_INITIAL},
{"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},
{"pty-exec", required_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},
};
@@ -256,29 +258,59 @@ static void uwsgi_pty_init() {
}
static int uwsgi_pty_client() {
if (!upty.remote) return 0;
static void uwsgi_pty_winch() {
// 2 uwsgi packets
char uwsgi_pkt[8];
#ifdef TIOCGWINSZ
struct winsize w;
ioctl(0, TIOCGWINSZ, &w);
uwsgi_pkt[0] = 0;
uwsgi_pkt[1] = (uint8_t) (w.ws_row & 0xff);
uwsgi_pkt[2] = (uint8_t) ((w.ws_row >> 8) & 0xff);
uwsgi_pkt[3] = 100;
uwsgi_pkt[4] = 0;
uwsgi_pkt[5] = (uint8_t) (w.ws_col & 0xff);
uwsgi_pkt[6] = (uint8_t) ((w.ws_col >> 8) & 0xff);
uwsgi_pkt[7] = 101;
#endif
if (write(upty.server_fd, uwsgi_pkt, 8) != 8) {
uwsgi_error("uwsgi_pty_winch()/write()");
exit(1);
}
}
uwsgi_log("[pty] connecting to %s ...\n", upty.remote);
static int uwsgi_pty_client() {
if (!upty.remote && !upty.uremote) return 0;
char *remote = upty.uremote ? upty.uremote : upty.remote;
uwsgi_log("[pty] connecting to %s ...\n", 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);
upty.server_fd = uwsgi_connect(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_socket_nb(upty.server_fd);
//uwsgi_socket_nb(0);
uwsgi_log("[pty] connected.\n");
uwsgi_pty_setterm(0);
if (upty.uremote) {
signal(SIGWINCH, uwsgi_pty_winch);
// send current terminal size
uwsgi_pty_winch();
}
upty.queue = event_queue_init();
event_queue_add_fd_read(upty.queue, upty.server_fd);
event_queue_add_fd_read(upty.queue, 0);
@@ -287,10 +319,21 @@ static int uwsgi_pty_client() {
char buf[8192];
int interesting_fd = -1;
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
if (ret <= 0) break;
if (ret == 0) break;
if (ret < 0) {
if (errno == EINTR) continue;
break;
}
if (interesting_fd == 0) {
ssize_t rlen = read(0, buf, 8192);
if (rlen <= 0) break;
if (upty.uremote) {
struct uwsgi_header uh;
uh.modifier1 = 0;
uh.pktsize = rlen;
uh.modifier2 = 0;
if (write(upty.server_fd, &uh, 4) != 4) break;
}
if (write(upty.server_fd, buf, rlen) != rlen) break;
continue;
}
+20 -3
View File
@@ -156,8 +156,14 @@ struct uwsgi_option uwsgi_python_options[] = {
{"wsgi-env-behavior", required_argument, 0, "set the strategy for allocating/deallocating the WSGI env", uwsgi_opt_set_str, &up.wsgi_env_behaviour, 0},
{"start_response-nodelay", no_argument, 0, "send WSGI http headers as soon as possible (PEP violation)", uwsgi_opt_true, &up.start_response_nodelay, 0},
{"wsgi-strict", no_argument, 0, "try to be fully PEP compliant disabling optimizations", uwsgi_opt_true, &up.wsgi_strict, 0},
{"wsgi-accept-buffer", no_argument, 0, "accept CPython buffer-compliant objects as WSGI response in addition to string/bytes", uwsgi_opt_true, &up.wsgi_accept_buffer, 0},
{"wsgi-accept-buffers", no_argument, 0, "accept CPython buffer-compliant objects as WSGI response in addition to string/bytes", uwsgi_opt_true, &up.wsgi_accept_buffer, 0},
{"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE},
{"python-raw", required_argument, 0, "load a python file for managing raw requests", uwsgi_opt_set_str, &up.raw, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -308,6 +314,10 @@ realstuff:
// this time we use this higher level function
// as this code can be executed in a signal handler
#ifdef __GNU_kFreeBSD__
return;
#endif
if (!Py_IsInitialized()) {
return;
}
@@ -1068,7 +1078,6 @@ void uwsgi_python_init_apps() {
up.loaders[LOADER_CALLABLE] = uwsgi_callable_loader;
up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader;
struct uwsgi_string_list *upli = up.import_list;
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
@@ -1119,6 +1128,12 @@ next:
uppa = uppa->next;
}
if (up.raw) {
up.raw_callable = uwsgi_file_loader(up.raw);
if (up.raw_callable) {
Py_INCREF(up.raw_callable);
}
}
if (up.wsgi_config != NULL) {
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
@@ -1354,8 +1369,10 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
UWSGI_RELEASE_GIL;
sleep(up.auto_reload);
UWSGI_GET_GIL;
// do not start monitoring til the first app is loaded (required for lazy mode)
if (uwsgi_apps_cnt == 0) continue;
if (uwsgi.lazy || uwsgi.lazy_apps) {
// do not start monitoring til the first app is loaded (required for lazy mode)
if (uwsgi_apps_cnt == 0) continue;
}
#ifdef UWSGI_PYTHON_OLD
int pos = 0;
#else
+6 -4
View File
@@ -320,8 +320,9 @@ void init_pyargv() {
char *tmp_ptr = uwsgi_str(up.argv);
#ifdef __sun__
// FIX THIS !!!
ap = strtok(tmp_ptr, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
char *ctx = NULL;
ap = strtok_r(tmp_ptr, " ", &ctx);
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
#else
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
#endif
@@ -352,8 +353,9 @@ void init_pyargv() {
#ifdef __sun__
// FIX THIS !!!
ap = strtok(py_argv_copy, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
char *ctx = NULL;
ap = strtok_r(py_argv_copy, " ", &ctx);
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
#else
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
#endif
+90
View File
@@ -0,0 +1,90 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
static int manage_raw_response(struct wsgi_request *wsgi_req) {
int ret = 0;
if (!wsgi_req->async_force_again) {
ret = uwsgi_python_send_body(wsgi_req, (PyObject *) wsgi_req->async_result);
if (ret == 0) {
if (PyInt_Check((PyObject *) wsgi_req->async_result) || PyObject_HasAttrString((PyObject *) wsgi_req->async_result, "fileno")) {
// is it a file ?
int fd = PyObject_AsFileDescriptor((PyObject *) wsgi_req->async_result);
if (fd >= 0) {
wsgi_req->sendfile_fd = fd;
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
wsgi_req->sendfile_fd = -1;
return UWSGI_OK;
}
}
}
}
if (ret == 0) {
if (!wsgi_req->async_placeholder) {
wsgi_req->async_placeholder = PyObject_GetIter((PyObject *) wsgi_req->async_result);
if (!wsgi_req->async_placeholder)
return UWSGI_OK;
}
PyObject *pychunk = PyIter_Next((PyObject *) wsgi_req->async_placeholder);
if (!pychunk)
return UWSGI_OK;
ret = uwsgi_python_send_body(wsgi_req, pychunk);
if (ret == 0) {
if (PyInt_Check(pychunk) || PyObject_HasAttrString(pychunk, "fileno")) {
// is it a file ?
int fd = PyObject_AsFileDescriptor(pychunk);
if (fd >= 0) {
wsgi_req->sendfile_fd = fd;
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
wsgi_req->sendfile_fd = -1;
}
}
}
Py_DECREF(pychunk);
return UWSGI_AGAIN;
}
return UWSGI_OK;
}
int uwsgi_request_python_raw(struct wsgi_request *wsgi_req) {
if (!up.raw_callable)
return UWSGI_OK;
// back from async
if (wsgi_req->async_force_again) {
UWSGI_GET_GIL int ret = manage_raw_response(wsgi_req);
if (ret == UWSGI_AGAIN) {
wsgi_req->async_force_again = 1;
UWSGI_RELEASE_GIL return UWSGI_AGAIN;
}
goto end;
}
UWSGI_GET_GIL PyObject * args = PyTuple_New(1);
PyTuple_SetItem(args, 0, PyInt_FromLong(wsgi_req->fd));
wsgi_req->async_result = PyEval_CallObject(up.raw_callable, args);
Py_DECREF(args);
if (wsgi_req->async_result) {
for (;;) {
int ret = manage_raw_response(wsgi_req);
if (ret == UWSGI_AGAIN) {
wsgi_req->async_force_again = 1;
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL return UWSGI_AGAIN;
}
continue;
}
break;
}
}
end:
if (PyErr_Occurred())
PyErr_Print();
if (wsgi_req->async_result) {
Py_DECREF((PyObject *) wsgi_req->async_result);
}
UWSGI_RELEASE_GIL;
return UWSGI_OK;
}
+10 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include <Python.h>
#include <frameobject.h>
@@ -180,6 +180,11 @@ struct uwsgi_python {
int start_response_nodelay;
char *programname;
int wsgi_strict;
int wsgi_accept_buffer;
char *raw;
PyObject *raw_callable;
};
@@ -276,6 +281,10 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
void uwsgi_python_exception_log(struct wsgi_request *);
int uwsgi_python_send_body(struct wsgi_request *, PyObject *);
int uwsgi_request_python_raw(struct wsgi_request *);
#define py_current_wsgi_req() current_wsgi_req();\
if (!wsgi_req) {\
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
+11 -3
View File
@@ -11,7 +11,7 @@ def get_python_version():
return version
NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker']
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker', 'raw']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
LDFLAGS = []
@@ -32,9 +32,17 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
# try 3.x style config dir
if not os.path.exists(libdir):
libdir = '%s/lib/python%s/config-%s' % (sys.prefix, version, get_python_version())
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
if not os.path.exists(libpath):
# get cpu type
uname = os.uname()
if uname[4].startswith('arm'):
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
else:
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/libpython%s.a' % (libdir, version)
LIBS.append(libpath)
+2
View File
@@ -292,6 +292,8 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
if (wsgi_req->is_raw) return uwsgi_request_python_raw(wsgi_req);
struct uwsgi_app *wi;
if (wsgi_req->async_force_again) {
+68 -20
View File
@@ -5,6 +5,68 @@ extern struct uwsgi_python up;
extern struct uwsgi_plugin python_plugin;
extern PyTypeObject uwsgi_InputType;
/*
Albeit PEP 333/3333 is clear about what kind of return object we must
expect from a WSGI callable, we CAN use the buffer api to optimize for lower-level
returns type: bytes, bytearray, array.array
to enable this optimization add --wsgi-accept-buffer
NOTE: this is a violation of the standards !!! use only if you know the implications !!!
*/
int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) {
if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict;
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
Py_buffer pbuf;
int has_buffer = 0;
#endif
char *content = NULL;
size_t content_len = 0;
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
if (PyObject_CheckBuffer(chunk)) {
if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) {
content = (char *) pbuf.buf;
content_len = (size_t) pbuf.len;
has_buffer = 1;
goto found;
}
}
#else
if (PyObject_CheckReadBuffer(chunk)) {
if (!PyObject_AsCharBuffer(chunk, (const char **) &content, (Py_ssize_t *) &content_len)) {
PyErr_Clear();
goto found;
}
}
#endif
strict:
// fallback
if (PyString_Check(chunk)) {
content = PyString_AsString(chunk);
content_len = PyString_Size(chunk);
}
found:
if (content) {
UWSGI_RELEASE_GIL
uwsgi_response_write_body_do(wsgi_req, content, content_len);
UWSGI_GET_GIL
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
if (has_buffer) PyBuffer_Release(&pbuf);
#endif
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
return -1;
}
return 1;
}
return 0;
}
/*
this is a hack for supporting non-file object passed to wsgi.file_wrapper
*/
@@ -169,19 +231,11 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
PyObject *pychunk;
// return or yield ?
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
char *content = PyString_AsString((PyObject *)wsgi_req->async_result);
size_t content_len = PyString_Size((PyObject *)wsgi_req->async_result);
UWSGI_RELEASE_GIL
uwsgi_response_write_body_do(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
}
goto clear;
// in strict mode we do not optimize apps directly returning strings (or bytes)
if (!up.wsgi_strict) {
if (uwsgi_python_send_body(wsgi_req, (PyObject *)wsgi_req->async_result)) goto clear;
}
if (wsgi_req->sendfile_obj == wsgi_req->async_result) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
@@ -222,19 +276,13 @@ exception:
if (PyString_Check(pychunk)) {
char *content = PyString_AsString(pychunk);
size_t content_len = PyString_Size(pychunk);
UWSGI_RELEASE_GIL
uwsgi_response_write_body_do(wsgi_req, content, content_len);
UWSGI_GET_GIL
uwsgi_py_check_write_errors {
uwsgi_py_write_exception(wsgi_req);
int ret = uwsgi_python_send_body(wsgi_req, pychunk);
if (ret != 0) {
if (ret < 0) {
Py_DECREF(pychunk);
goto clear;
}
}
else if (wsgi_req->sendfile_obj == pychunk) {
if (wsgi_req->sendfile_fd >= 0) {
UWSGI_RELEASE_GIL
+12 -12
View File
@@ -416,6 +416,18 @@ void uwsgi_ruby_gem_set_apply(char *gemset) {
void uwsgi_ruby_gemset(char *gemset) {
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
while(rvm_paths) {
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
if (uwsgi_file_exists(filename)) {
uwsgi_ruby_gem_set_apply(filename);
free(filename);
return;
}
free(filename);
rvm_paths = rvm_paths->next;
}
char *home = getenv("HOME");
if (home) {
@@ -436,18 +448,6 @@ void uwsgi_ruby_gemset(char *gemset) {
}
free(filename);
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
while(rvm_paths) {
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
if (uwsgi_file_exists(filename)) {
uwsgi_ruby_gem_set_apply(filename);
free(filename);
return;
}
free(filename);
rvm_paths = rvm_paths->next;
}
uwsgi_log("ERROR: unable to load gemset %s !!!\n", gemset);
exit(1);
+5 -3
View File
@@ -18,8 +18,10 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
struct uwsgi_buffer *ub_url = NULL;
if (ur->data3_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;
if (!ub_url) {
uwsgi_buffer_destroy(ub_addr);
return UWSGI_ROUTE_BREAK;
}
}
@@ -82,7 +84,7 @@ static int uwsgi_router_http(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_http;
ur->data = (void *) args;
ur->data_len = strlen(args);
char *comma = strchr(ur->data, ',');
if (comma) {
*comma = 0;
+6 -6
View File
@@ -158,18 +158,19 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
}
argc = 0;
argv[0] = strtok(args, "/");
char *ctx = NULL;
argv[0] = strtok_r(args, "/", &ctx);
if (!argv[0]) {
free(args);
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *p = strtok(NULL, "/");
char *p = strtok_r(NULL, "/", &ctx);
while(p) {
argc++;
argv[argc] = p;
argvs[argc] = strlen(p);
p = strtok(NULL, "/");
p = strtok_r(NULL, "/", &ctx);
}
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, response_buf);
@@ -558,8 +559,8 @@ static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
ur->custom = 0;
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
char *p = strtok(args, " ");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(args, " ", p, ctx) {
if (!ur->data) {
ur->data = p;
}
@@ -576,7 +577,6 @@ static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
argvs[ur->custom] = strlen(p);
ur->custom++;
}
p = strtok(NULL, " ");
}
if (!ur->data) {
+1 -1
View File
@@ -104,7 +104,7 @@ static int u_green_init() {
ug.contexts[i].uc_stack.ss_sp = mmap(NULL, ug.u_stack_size + (uwsgi.page_size*2) , PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0) + uwsgi.page_size;
if (!ug.contexts[i].uc_stack.ss_sp) {
if (ug.contexts[i].uc_stack.ss_sp == MAP_FAILED) {
uwsgi_error("mmap()");
exit(1);
}
+2 -3
View File
@@ -158,11 +158,10 @@ static void uwsgi_webdav_add_a_prop(xmlNode *node, char *opt, xmlNode *req_prop,
else if (type == 2) {
new_node = xmlNewChild(node, NULL, BAD_CAST first_space + 1, NULL);
char *comps = uwsgi_str(second_space + 1);
char *p = strtok(comps, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(comps, ",", p, ctx) {
xmlNode *comp = xmlNewChild(new_node, NULL, BAD_CAST "comp", NULL);
xmlNewProp(comp, BAD_CAST "name", BAD_CAST p);
p = strtok(NULL, ",");
}
free(comps);
}
+2 -3
View File
@@ -72,16 +72,15 @@ static char *uwsgi_xslt_apply(xmlDoc *doc, char *xsltfile, char *params, int *rl
}
vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
tmp_params = uwsgi_str(params);
char *p = strtok(tmp_params, "&");
int pos = 0;
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(tmp_params, "&", p, ctx) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
vparams[pos] = p; pos++;
vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;
}
p = strtok(NULL, "&");
}
}
+4 -6
View File
@@ -91,18 +91,17 @@ struct zergpool_socket *add_zergpool_socket(char *name, char *sockets) {
}
char *sock_list = uwsgi_str(sockets);
char *p = strtok(sock_list, ",");
while(p) {
char *p, *ctx = NULL;
uwsgi_foreach_token(sock_list, ",", p, ctx) {
z_sock->num_sockets++;
p = strtok(NULL, ",");
}
free(sock_list);
z_sock->sockets = uwsgi_calloc(sizeof(int) * (z_sock->num_sockets + 1));
sock_list = uwsgi_str(sockets);
int pos = 0;
p = strtok(sock_list, ",");
while(p) {
ctx = NULL;
uwsgi_foreach_token(sock_list, ",", p, ctx) {
char *port = strchr(p, ':');
char *sockname;
if (!port) {
@@ -117,7 +116,6 @@ struct zergpool_socket *add_zergpool_socket(char *name, char *sockets) {
uwsgi_log("zergpool %s bound to TCP socket %s (fd: %d)\n", name, sockname, z_sock->sockets[pos]);
}
pos++;
p = strtok(NULL, ",");
free(sockname);
}
free(sock_list);
+8 -2
View File
@@ -1,8 +1,14 @@
#include "../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_proto_raw_parser(struct wsgi_request *wsgi_req) {
wsgi_req->is_raw = 1;
wsgi_req->uh->modifier1 = uwsgi.raw_modifier1;
wsgi_req->uh->modifier2 = uwsgi.raw_modifier2;
return UWSGI_OK;
}
uint16_t proto_base_add_uwsgi_header(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
+3
View File
@@ -10,6 +10,9 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
if (len > 0) {
wsgi_req->proto_parser_pos += len;
if (wsgi_req->proto_parser_pos >= 4) {
#ifdef __BIG_ENDIAN__
wsgi_req->uh->pktsize = uwsgi_swap16(wsgi_req->uh->pktsize);
#endif
if ((wsgi_req->proto_parser_pos-4) == wsgi_req->uh->pktsize) {
return UWSGI_OK;
}
-22
View File
@@ -1,22 +0,0 @@
import sys
import os
import pyuwsgi
orig_args = sys.argv
orig_executable = sys.executable
orig_args.insert(0, orig_executable)
uwsgi_args = []
uwsgi_args.append('--socket')
uwsgi_args.append(':3031')
#uwsgi_args.append('--master')
uwsgi_args.append('--module')
#uwsgi_args.append('welcome')
uwsgi_args.append('hello')
#pyuwsgi.run('welcome.ini')
pyuwsgi.run(uwsgi_args)
# if you are here uWSGI has been reloaded
os.execv(orig_executable, orig_args)
+7
View File
@@ -0,0 +1,7 @@
import array
def application(e, sr):
sr('200 OK', [('Content-Type','text/html')])
a = array.array('b',[54,55,56,57])
yield a
yield bytearray(b'abcdef')
yield b'ciao'
View File
View File
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-09-14'
s.date = '2013-10-11'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+99 -13
View File
@@ -53,8 +53,6 @@ extern "C" {
}
#define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "emperor://", 10) || !uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5) || !uwsgi_startswith(file, "exec://", 7) || !uwsgi_startswith(file, "section://", 10))
#define uwsgi_n64(x) strtoul(x, NULL, 10)
#define ushared uwsgi.shared
@@ -132,6 +130,8 @@ extern "C" {
#define uwsgi_foreach(x, y) for(x=y;x;x = x->next)
#define uwsgi_foreach_token(x, y, z, w) for(z=strtok_r(x, y, &w);z;z = strtok_r(NULL, y, &w))
#ifndef __need_IOV_MAX
#define __need_IOV_MAX
@@ -195,7 +195,11 @@ extern "C" {
#endif
#include <netdb.h>
#ifdef __FreeBSD__
#if defined(__GNU_kFreeBSD__)
#include <bsd/unistd.h>
#endif
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/cpuset.h>
@@ -235,7 +239,7 @@ extern "C" {
#include <linux/limits.h>
#endif
#if defined(__linux) || defined(__FreeBSD__)
#if defined(__linux) || defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
#include <sys/mount.h>
#endif
@@ -306,6 +310,9 @@ extern int pivot_root(const char *new_root, const char *put_old);
#ifdef __linux__
#include <sys/sendfile.h>
#include <sys/epoll.h>
#elif defined(__GNU_kFreeBSD__)
#include <sys/sendfile.h>
#include <sys/event.h>
#elif defined(__sun__)
#include <sys/sendfile.h>
#include <sys/devpoll.h>
@@ -552,7 +559,7 @@ struct uwsgi_gateway_socket {
// could be useful for ssl
void *ctx;
// could be useful ofr plugins
// could be useful for plugins
int mode;
};
@@ -583,6 +590,7 @@ struct uwsgi_daemon {
char *legion;
#endif
int control;
struct uwsgi_daemon *next;
};
@@ -1256,6 +1264,7 @@ struct uwsgi_log_encoder {
char *name;
char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *);
int configured;
char *use_for;
char *args;
void *data;
struct uwsgi_log_encoder *next;
@@ -1513,6 +1522,8 @@ struct wsgi_request {
char *transformed_chunk;
size_t transformed_chunk_len;
int is_raw;
struct msghdr msg;
union {
struct cmsghdr cmsg;
@@ -1552,7 +1563,7 @@ struct uwsgi_signal_rb_timer {
struct uwsgi_cheaper_algo {
char *name;
int (*func) (void);
int (*func) (int);
struct uwsgi_cheaper_algo *next;
};
@@ -1684,6 +1695,13 @@ struct uwsgi_server {
int drop_after_init;
int drop_after_apps;
int master_is_reforked;
struct uwsgi_string_list *master_fifo;
int master_fifo_fd;
int master_fifo_slot;
// kill the stack on SIGTERM (instead of brutal reloading)
int die_on_term;
@@ -1708,6 +1726,8 @@ struct uwsgi_server {
uint64_t http_modifier2;
uint64_t scgi_modifier1;
uint64_t scgi_modifier2;
uint64_t raw_modifier1;
uint64_t raw_modifier2;
// enable lazy mode
int lazy;
@@ -1717,7 +1737,7 @@ struct uwsgi_server {
int cheaper;
char *requested_cheaper_algo;
struct uwsgi_cheaper_algo *cheaper_algos;
int (*cheaper_algo) (void);
int (*cheaper_algo) (int);
int cheaper_step;
uint64_t cheaper_overload;
// minimal number of running workers in cheaper mode
@@ -1730,6 +1750,8 @@ struct uwsgi_server {
uint64_t cheaper_rss_limit_soft;
uint64_t cheaper_rss_limit_hard;
int cheaper_fifo_delta;
// destroy the stack when idle
int die_on_idle;
@@ -1739,7 +1761,9 @@ struct uwsgi_server {
// true if run under the emperor
int has_emperor;
char *emperor_procname;
char *emperor_proxy;
int emperor_fd;
int emperor_fd_proxy;
int emperor_queue;
int emperor_nofollow;
int emperor_tyrant;
@@ -1751,6 +1775,7 @@ struct uwsgi_server {
int emperor_max_throttle;
int emperor_magic_exec;
int emperor_heartbeat;
int emperor_curse_tolerance;
struct uwsgi_string_list *emperor_extra_extension;
// search for a file with the specified extension at the same level of the vassal file
char *emperor_on_demand_extension;
@@ -1774,6 +1799,9 @@ struct uwsgi_server {
char *emperor_stats;
int emperor_stats_fd;
struct uwsgi_string_list *vassals_templates;
struct uwsgi_string_list *vassals_includes;
struct uwsgi_string_list *vassals_templates_before;
struct uwsgi_string_list *vassals_includes_before;
// true if loyal to the emperor
int loyal;
@@ -1850,15 +1878,19 @@ struct uwsgi_server {
#ifdef UWSGI_CAP
cap_value_t *cap;
int cap_count;
cap_value_t *emperor_cap;
int emperor_cap_count;
#endif
#ifdef __linux__
int unshare;
int unshare2;
int emperor_clone;
char *pivot_root;
#endif
char *emperor_wrapper;
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
char *jail;
struct uwsgi_string_list *jail_ip4;
#ifdef AF_INET6
@@ -1952,6 +1984,7 @@ struct uwsgi_server {
struct uwsgi_hook *hooks;
struct uwsgi_string_list *hook_asap;
struct uwsgi_string_list *hook_pre_jail;
struct uwsgi_string_list *hook_post_jail;
struct uwsgi_string_list *hook_in_jail;
@@ -1965,6 +1998,7 @@ struct uwsgi_server {
struct uwsgi_string_list *hook_as_emperor;
struct uwsgi_string_list *exec_asap;
struct uwsgi_string_list *exec_pre_jail;
struct uwsgi_string_list *exec_post_jail;
struct uwsgi_string_list *exec_in_jail;
@@ -1977,6 +2011,7 @@ struct uwsgi_server {
struct uwsgi_string_list *exec_as_vassal;
struct uwsgi_string_list *exec_as_emperor;
struct uwsgi_string_list *call_asap;
struct uwsgi_string_list *call_pre_jail;
struct uwsgi_string_list *call_post_jail;
struct uwsgi_string_list *call_in_jail;
@@ -1995,6 +2030,7 @@ struct uwsgi_server {
struct uwsgi_string_list *call_as_emperor2;
struct uwsgi_string_list *call_as_emperor4;
struct uwsgi_string_list *mount_asap;
struct uwsgi_string_list *mount_pre_jail;
struct uwsgi_string_list *mount_post_jail;
struct uwsgi_string_list *mount_in_jail;
@@ -2003,6 +2039,7 @@ struct uwsgi_server {
struct uwsgi_string_list *mount_as_vassal;
struct uwsgi_string_list *mount_as_emperor;
struct uwsgi_string_list *umount_asap;
struct uwsgi_string_list *umount_pre_jail;
struct uwsgi_string_list *umount_post_jail;
struct uwsgi_string_list *umount_in_jail;
@@ -2175,6 +2212,8 @@ struct uwsgi_server {
struct uwsgi_string_list *fs_brutal_reload;
struct uwsgi_string_list *fs_signal;
struct uwsgi_string_list *mountpoints_check;
int propagate_touch;
// enable grunt mode
@@ -2243,6 +2282,7 @@ struct uwsgi_server {
int harakiri_verbose;
int harakiri_no_arh;
int magic_table_first_round;
char *magic_table[256];
int numproc;
@@ -2529,6 +2569,8 @@ struct uwsgi_server {
int (*wait_write_hook) (int, int);
int (*wait_read_hook) (int, int);
struct uwsgi_string_list *schemes;
};
struct uwsgi_rpc {
@@ -2943,6 +2985,7 @@ void uwsgi_register_loop(char *, void (*)(void));
void *uwsgi_get_loop(char *);
void add_exported_option(char *, char *, int);
void add_exported_option_do(char *, char *, int, int);
ssize_t uwsgi_send_empty_pkt(int, char *, uint8_t, uint8_t);
@@ -3129,8 +3172,10 @@ int uwsgi_str3_num(char *);
int uwsgi_str4_num(char *);
#ifdef __linux__
#if !defined(__ia64__)
void linux_namespace_start(void *);
void linux_namespace_jail(void);
#endif
int uwsgi_netlink_veth(char *, char *);
int uwsgi_netlink_veth_attach(char *, pid_t);
int uwsgi_netlink_ifup(char *);
@@ -3173,6 +3218,7 @@ int uwsgi_proto_scgi_parser(struct wsgi_request *);
int uwsgi_proto_base_accept(struct wsgi_request *, int);
int uwsgi_proto_raw_parser(struct wsgi_request *);
void uwsgi_proto_base_close(struct wsgi_request *);
uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
@@ -3404,7 +3450,8 @@ void uwsgi_linux_ksm_map(void);
#endif
#ifdef UWSGI_CAP
void uwsgi_build_cap(char *);
int uwsgi_build_cap(char *, cap_value_t **);
void uwsgi_apply_cap(cap_value_t *, int);
#endif
void uwsgi_register_logger(char *, ssize_t(*func) (struct uwsgi_logger *, char *, size_t));
@@ -3436,6 +3483,7 @@ int uwsgi_manage_opt(char *, char *);
void uwsgi_opt_print(char *, char *, void *);
void uwsgi_opt_true(char *, char *, void *);
void uwsgi_opt_set_str(char *, char *, void *);
void uwsgi_opt_custom(char *, char *, void *);
void uwsgi_opt_set_null(char *, char *, void *);
void uwsgi_opt_set_logger(char *, char *, void *);
void uwsgi_opt_set_req_logger(char *, char *, void *);
@@ -3444,6 +3492,7 @@ void uwsgi_opt_add_string_list(char *, char *, void *);
void uwsgi_opt_add_addr_list(char *, char *, void *);
void uwsgi_opt_add_string_list_custom(char *, char *, void *);
void uwsgi_opt_add_dyn_dict(char *, char *, void *);
void uwsgi_opt_binary_append_data(char *, char *, void *);
#ifdef UWSGI_PCRE
void uwsgi_opt_pcre_jit(char *, char *, void *);
void uwsgi_opt_add_regexp_dyn_dict(char *, char *, void *);
@@ -3461,6 +3510,7 @@ void uwsgi_opt_dyn_false(char *, char *, void *);
void uwsgi_opt_set_placeholder(char *, char *, void *);
void uwsgi_opt_add_shared_socket(char *, char *, void *);
void uwsgi_opt_add_socket(char *, char *, void *);
void uwsgi_opt_add_socket_no_defer(char *, char *, void *);
void uwsgi_opt_add_lazy_socket(char *, char *, void *);
void uwsgi_opt_add_cron(char *, char *, void *);
void uwsgi_opt_add_cron2(char *, char *, void *);
@@ -3544,6 +3594,7 @@ int uwsgi_logic_opt_if_not_plugin(char *, char *);
#ifdef UWSGI_CAP
void uwsgi_opt_set_cap(char *, char *, void *);
void uwsgi_opt_set_emperor_cap(char *, char *, void *);
#endif
#ifdef __linux__
void uwsgi_opt_set_unshare(char *, char *, void *);
@@ -3582,15 +3633,16 @@ void uwsgi_manage_zerg(int, int, int *);
time_t uwsgi_now(void);
int uwsgi_calc_cheaper(void);
int uwsgi_cheaper_algo_spare(void);
int uwsgi_cheaper_algo_backlog(void);
int uwsgi_cheaper_algo_backlog2(void);
int uwsgi_cheaper_algo_spare(int);
int uwsgi_cheaper_algo_backlog(int);
int uwsgi_cheaper_algo_backlog2(int);
int uwsgi_cheaper_algo_manual(int);
int uwsgi_master_log(void);
int uwsgi_master_req_log(void);
void uwsgi_flush_logs(void);
void uwsgi_register_cheaper_algo(char *, int (*)(void));
void uwsgi_register_cheaper_algo(char *, int (*)(int));
void uwsgi_setup_locking(void);
int uwsgi_fcntl_lock(int);
@@ -3799,11 +3851,13 @@ struct uwsgi_instance {
int on_demand_fd;
char *socket_name;
time_t cursed_at;
};
struct uwsgi_instance *emperor_get_by_fd(int);
struct uwsgi_instance *emperor_get(char *);
void emperor_stop(struct uwsgi_instance *);
void emperor_curse(struct uwsgi_instance *);
void emperor_respawn(struct uwsgi_instance *, time_t);
void emperor_add(struct uwsgi_emperor_scanner *, char *, time_t, char *, uint32_t, uid_t, gid_t, char *);
@@ -4036,6 +4090,7 @@ void uwsgi_legion_atexit(void);
#endif
struct uwsgi_option *uwsgi_opt_get(char *);
int uwsgi_opt_exists(char *);
int uwsgi_valid_fd(int);
void uwsgi_close_all_fds(void);
@@ -4301,6 +4356,37 @@ void uwsgi_log_encoders_register_embedded(void);
void uwsgi_register_log_encoder(char *, char *(*)(struct uwsgi_log_encoder *, char *, size_t, size_t *));
int uwsgi_accept(int);
void suspend_resume_them_all(int);
void uwsgi_master_fifo_prepare();
int uwsgi_master_fifo();
int uwsgi_master_fifo_manage(int);
void uwsgi_log_rotate();
void uwsgi_log_reopen();
void uwsgi_reload_workers();
void uwsgi_chain_reload();
void uwsgi_refork_master();
void uwsgi_update_pidfiles();
void gracefully_kill_them_all(int);
void uwsgi_brutally_reload_workers();
void uwsgi_cheaper_increase();
void uwsgi_cheaper_decrease();
void uwsgi_go_cheap();
char **uwsgi_split_quoted(char *, size_t, char *, size_t *);
void uwsgi_master_manage_emperor_proxy();
struct uwsgi_string_list *uwsgi_register_scheme(char *, char * (*)(char *, size_t *, int));
void uwsgi_setup_schemes(void);
struct uwsgi_string_list *uwsgi_check_scheme(char *);
void uwsgi_remap_fd(int, char *);
void uwsgi_opt_exit(char *, char *, void *);
int uwsgi_check_mountpoint(char *);
void uwsgi_master_check_mountpoints(void);
#ifdef __cplusplus
}
+165 -81
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.16'
uwsgi_version = '1.9.18.1'
import os
import re
@@ -13,6 +13,7 @@ uwsgi_cpu = os.uname()[4]
import sys
import subprocess
from threading import Thread,Lock
from optparse import OptionParser
try:
from queue import Queue
@@ -56,26 +57,35 @@ binary_list = []
# this is used for reporting (at the end of the build)
# the server configuration
report = {}
report['kernel'] = False
report['execinfo'] = False
report['ifaddrs'] = False
report['locking'] = False
report['event'] = False
report['timer'] = False
report['filemonitor'] = False
report['pcre'] = False
report['matheval'] = False
report['routing'] = False
report['capabilities'] = False
report['yaml'] = False
report['json'] = False
report['ssl'] = False
report['zeromq'] = False
report['xml'] = False
report['debug'] = False
report['plugin_dir'] = False
report['zlib'] = False
report = {
'kernel': False,
'execinfo': False,
'ifaddrs': False,
'locking': False,
'event': False,
'timer': False,
'filemonitor': False,
'pcre': False,
'matheval': False,
'routing': False,
'capabilities': False,
'yaml': False,
'json': False,
'ssl': False,
'zeromq': False,
'xml': False,
'debug': False,
'plugin_dir': False,
'zlib': False,
}
verbose_build = False
def print_compilation_output(default_str, verbose_str):
if verbose_build:
print(verbose_str)
elif default_str is not None:
print(default_str)
compile_queue = None
print_lock = None
@@ -85,8 +95,8 @@ def thread_compiler(num):
while True:
(objfile, cmdline) = compile_queue.get()
if objfile:
print_lock.acquire()
print("[thread %d][%s] %s" % (num, GCC, objfile))
print_lock.acquire()
print_compilation_output("[thread %d][%s] %s" % (num, GCC, objfile), "[thread %d] %s" % (num, cmdline))
print_lock.release()
ret = os.system(cmdline)
if ret != 0:
@@ -170,7 +180,7 @@ def push_print(msg):
def push_command(objfile, cmdline):
if not compile_queue:
print("[%s] %s" % (GCC, objfile))
print_compilation_output("[%s] %s" % (GCC, objfile), cmdline)
ret = os.system(cmdline)
if ret != 0:
sys.exit(1)
@@ -205,7 +215,7 @@ def compile(cflags, last_cflags_ts, objfile, srcfile):
push_command(objfile, cmdline)
def build_uwsgi(uc, print_only=False):
def build_uwsgi(uc, print_only=False, gcll=None):
global print_lock, compile_queue, thread_compilers
@@ -218,10 +228,17 @@ def build_uwsgi(uc, print_only=False):
t.start()
thread_compilers.append(t)
gcc_list, cflags, ldflags, libs = uc.get_gcll()
if not gcll:
gcc_list, cflags, ldflags, libs = uc.get_gcll()
else:
gcc_list, cflags, ldflags, libs = gcll
if 'UWSGI_EMBED_PLUGINS' in os.environ:
uc.set('embedded_plugins', uc.get('embedded_plugins') + ',' + os.environ['UWSGI_EMBED_PLUGINS'])
ep = uc.get('embedded_plugins')
if ep:
uc.set('embedded_plugins', ep + ',' + os.environ['UWSGI_EMBED_PLUGINS'])
else:
uc.set('embedded_plugins', os.environ['UWSGI_EMBED_PLUGINS'])
if uc.get('embedded_plugins'):
ep = uc.get('embedded_plugins').split(',')
@@ -291,6 +308,15 @@ def build_uwsgi(uc, print_only=False):
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
gcc_list.append('core/dot_h')
additional_sources = os.environ.get('UWSGI_ADDITIONAL_SOURCES')
if not additional_sources:
additional_sources = uc.get('additional_sources')
if additional_sources:
for item in additional_sources.split(','):
if item.endswith('.c'):
gcc_list.append(item[:-2])
else:
gcc_list.append(item)
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
@@ -433,8 +459,8 @@ def build_uwsgi(uc, print_only=False):
bin_name = os.environ.get('UWSGI_BIN_NAME', uc.get('bin_name'))
if uc.get('embed_config'):
gcc_list.append(uc.get('embed_config'))
if uc.embed_config:
gcc_list.append(uc.embed_config)
for ef in binary_list:
gcc_list.append("build/%s" % ef)
@@ -507,7 +533,7 @@ class uConf(object):
self.config.readfp(open_profile(filename))
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks', 'core/fifo',
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
@@ -530,7 +556,8 @@ class uConf(object):
report['kernel'] = uwsgi_os
if uwsgi_os == 'Linux':
self.gcc_list.append('lib/linux_ns')
if uwsgi_cpu != 'ia64':
self.gcc_list.append('lib/linux_ns')
try:
lk_ver = uwsgi_os_k.split('.')
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]) <= 9:
@@ -597,8 +624,11 @@ class uConf(object):
self.ldflags = os.environ.get("LDFLAGS", "").split()
self.libs = ['-lpthread', '-lm', '-rdynamic']
if uwsgi_os == 'Linux':
if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD'):
self.libs.append('-ldl')
if uwsgi_os == 'GNU/kFreeBSD':
self.cflags.append('-D__GNU_kFreeBSD__')
self.libs.append('-lbsd')
# check for inherit option
inherit = self.get('inherit')
@@ -674,6 +704,11 @@ class uConf(object):
self.libs.append('-lexecinfo')
report['execinfo'] = True
if uwsgi_os == 'GNU/kFreeBSD':
if self.has_include('execinfo.h'):
self.cflags.append('-DUWSGI_HAS_EXECINFO')
report['execinfo'] = True
if self.has_include('zlib.h'):
self.cflags.append('-DUWSGI_ZLIB')
self.libs.append('-lz')
@@ -698,6 +733,10 @@ class uConf(object):
if not uwsgi_os_v.startswith('Nexenta'):
self.libs.remove('-rdynamic')
if uwsgi_os == 'GNU/kFreeBSD':
if self.has_include('kvm.h'):
kvm_list.append('GNU/kFreeBSD')
if uwsgi_os in kvm_list:
self.libs.append('-lkvm')
@@ -730,7 +769,7 @@ class uConf(object):
locking_mode = 'pthread_mutex'
# FreeBSD umtx is still not ready for process shared locking
# starting from FreeBSD 9 posix semaphores can be shared between processes
elif uwsgi_os == 'FreeBSD':
elif uwsgi_os in ('FreeBSD', 'GNU/kFreeBSD'):
try:
fbsd_major = int(uwsgi_os_k.split('.')[0])
if fbsd_major >= 9:
@@ -773,7 +812,7 @@ class uConf(object):
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
event_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
event_mode = 'kqueue'
elif uwsgi_os.startswith('CYGWIN') or uwsgi_os == 'GNU':
event_mode = 'poll'
@@ -816,7 +855,7 @@ class uConf(object):
if int(sun_minor) >= 10:
timer_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
timer_mode = 'kqueue'
if timer_mode == 'timerfd':
@@ -843,7 +882,7 @@ class uConf(object):
if int(sun_major) >= 5:
if int(sun_minor) >= 10:
filemonitor_mode = 'port'
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
elif uwsgi_os in ('Darwin', 'FreeBSD', 'GNU/kFreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
filemonitor_mode = 'kqueue'
if filemonitor_mode == 'inotify':
@@ -943,7 +982,7 @@ class uConf(object):
if self.has_include('uuid/uuid.h'):
has_uuid = True
self.cflags.append("-DUWSGI_UUID")
if uwsgi_os == 'Linux' or uwsgi_os.startswith('CYGWIN') or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
if uwsgi_os in ('Linux', 'GNU', 'GNU/kFreeBSD') or uwsgi_os.startswith('CYGWIN') or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
self.libs.append('-luuid')
if self.get('append_version'):
@@ -952,17 +991,22 @@ class uConf(object):
uwsgi_version += self.get('append_version')
if uwsgi_os == 'FreeBSD' and self.has_include('jail.h'):
if uwsgi_os in ('FreeBSD','GNU/kFreeBSD') and self.has_include('jail.h'):
self.cflags.append('-DUWSGI_HAS_FREEBSD_LIBJAIL')
self.libs.append('-ljail')
self.embed_config = None
if uwsgi_os == 'Linux':
if self.get('embed_config'):
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (self.get('embed_config'), self.get('embed_config'))
self.embed_config = os.environ.get('UWSGI_EMBED_CONFIG')
if not self.embed_config:
self.embed_config = self.get('embed_config')
if self.embed_config:
binary_link_cmd = "ld -r -b binary -o %s.o %s" % (self.embed_config, self.embed_config)
print(binary_link_cmd)
os.system(binary_link_cmd)
self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" % self.get('embed_config').replace('.','_'))
self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" % self.get('embed_config').replace('.','_'))
self.cflags.append("-DUWSGI_EMBED_CONFIG=_binary_%s_start" % self.embed_config.replace('.','_'))
self.cflags.append("-DUWSGI_EMBED_CONFIG_END=_binary_%s_end" % self.embed_config.replace('.','_'))
if self.get('embed_files'):
for ef in self.get('embed_files').split(','):
ef_parts = ef.split('=')
@@ -1281,7 +1325,7 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
need_pic = ' -L. -luwsgi'
gccline = "%s%s %s -o %s.so %s %s %s %s" % (GCC, need_pic, shared_flag, plugin_dest, ' '.join(uniq_warnings(p_cflags)), ' '.join(gcc_list), ' '.join(uniq_warnings(p_ldflags)), ' '.join(uniq_warnings(p_libs)) )
print("[%s] %s.so" % (GCC, plugin_dest))
print_compilation_output("[%s] %s.so" % (GCC, plugin_dest), gccline)
ret = os.system(gccline)
if ret != 0:
@@ -1294,7 +1338,9 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
for rp in requires:
f.write("requires=%s\n" % rp)
f.close()
os.system("objcopy %s.so --add-section uwsgi=.uwsgi_plugin_section %s.so" % (plugin_dest, plugin_dest))
objline = "objcopy %s.so --add-section uwsgi=.uwsgi_plugin_section %s.so" % (plugin_dest, plugin_dest)
print_compilation_output(None, objline)
os.system(objline)
os.unlink('.uwsgi_plugin_section')
except:
pass
@@ -1304,43 +1350,82 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
print("*** %s plugin built and available in %s ***" % (name, plugin_dest + '.so'))
if __name__ == "__main__":
try:
cmd = sys.argv[1]
except:
print("please specify an argument")
sys.exit(1)
def vararg_callback(option, opt_str, value, parser):
assert value is None
value = []
for arg in parser.rargs:
# stop on --foo like options
if arg[:2] == "--" and len(arg) > 2:
break
# stop on -a, but not on -3 or -3.0
if arg[:1] == "-" and len(arg) > 1:
break
value.append(arg)
if cmd == '--build':
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-b", "--build", action="callback", callback=vararg_callback, dest="build", help="build a specific profile if provided or default.ini", metavar="PROFILE")
parser.add_option("-f", "--cflags", action="callback", callback=vararg_callback, dest="cflags", help="same as --build but less verbose", metavar="PROFILE")
parser.add_option("-u", "--unbit", action="store_true", dest="unbit", help="build unbit profile")
parser.add_option("-p", "--plugin", action="callback", callback=vararg_callback, dest="plugin", help="build a plugin as shared library, optionally takes a build profile name", metavar="PLUGIN [PROFILE]")
parser.add_option("-x", "--extra-plugin", action="callback", callback=vararg_callback, dest="extra_plugin", help="build an external plugin as shared library, takes an optional include dir", metavar="PLUGIN [INCLUDE_DIR]")
parser.add_option("-c", "--clean", action="store_true", dest="clean", help="clean the build")
parser.add_option("-e", "--check", action="store_true", dest="check", help="run cppcheck")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="more verbose build")
parser.add_option("-g", "--debug", action="store_true", dest="debug", help="build with debug symbols, affects only full build")
parser.add_option("-a", "--asan", action="store_true", dest="asan", help="build with address sanitizer, it's a debug option and affects only full build")
(options, args) = parser.parse_args()
if options.verbose:
verbose_build = True
add_cflags = []
add_ldflags = []
if options.debug:
add_cflags.append('-g')
add_ldflags.append('-g')
if options.asan:
add_cflags.extend(['-g', '-fsanitize=address', '-fno-omit-frame-pointer'])
add_ldflags.extend(['-g', '-fsanitize=address'])
if options.build is not None or options.cflags is not None:
is_cflags = options.cflags is not None
try:
bconf = sys.argv[2]
if not is_cflags:
bconf = options.build[0]
else:
bconf = options.cflags[0]
except:
pass
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
build_uwsgi(uConf(bconf))
elif cmd == '--cflags':
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
try:
bconf = sys.argv[2]
except:
pass
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
build_uwsgi(uConf(bconf, True), True)
elif cmd == '--unbit':
uc = uConf(bconf, is_cflags)
if add_cflags or add_ldflags:
gcc_list, cflags, ldflags, libs = uc.get_gcll()
if add_cflags:
cflags.extend(add_cflags)
if add_ldflags:
ldflags.extend(add_ldflags)
gcll = (gcc_list, cflags, ldflags, libs)
else:
gcll = None
build_uwsgi(uc, is_cflags, gcll=gcll)
elif options.unbit:
build_uwsgi(uConf('buildconf/unbit.ini'))
elif cmd == '--plugin':
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
elif options.plugin:
try:
bconf = sys.argv[3]
bconf = options.plugin[1]
except:
pass
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
@@ -1348,29 +1433,28 @@ if __name__ == "__main__":
uc = uConf(bconf)
gcc_list, cflags, ldflags, libs = uc.get_gcll()
try:
name = sys.argv[4]
name = options.plugin[2]
except:
name = None
print("*** uWSGI building and linking plugin %s ***" % sys.argv[2] )
build_plugin(sys.argv[2], uc, cflags, ldflags, libs, name)
elif cmd == '--extra-plugin':
print("*** uWSGI building and linking plugin %s ***" % options.plugin[0] )
build_plugin(options.plugin[0], uc, cflags, ldflags, libs, name)
elif options.extra_plugin:
print("*** uWSGI building and linking plugin ***")
cflags = spcall("%s --cflags" % sys.argv[2]).split()
cflags = spcall("%s --cflags" % options.extra_plugin[0]).split()
try:
cflags.append('-I%s' % sys.argv[3])
cflags.append('-I%s' % options.extra_plugin[1])
except:
pass
build_plugin('.', None, cflags, [], [], None)
elif cmd == '--clean':
elif options.clean:
os.system("rm -f core/*.o")
os.system("rm -f proto/*.o")
os.system("rm -f lib/*.o")
os.system("rm -f plugins/*/*.o")
os.system("rm -f build/*.o")
os.system("rm -f core/dot_h.c")
elif cmd == '--check':
elif options.check:
os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/ proto/ lib/ apache2/")
else:
print("unknown uwsgiconfig command")
parser.print_help()
sys.exit(1)