Compare commits

..
116 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
Łukasz Mierzwa edbff83fd6 zero pids after worker killed due to --idle usage 2013-04-08 10:32:39 +02:00
58 changed files with 2857 additions and 1548 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)))
+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
+4 -4
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));
+158 -6
View File
@@ -293,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)) {
@@ -303,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;
@@ -394,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 ?
@@ -457,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() {
@@ -477,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
+255 -60
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,24 +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;
}
uct = uwsgi.vassals_includes;
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) {
@@ -1050,62 +1130,58 @@ 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;
}
uct = uwsgi.vassals_includes;
while (uct) {
uwsgi_foreach (uct, uwsgi.vassals_includes) {
vassal_argv[counter] = "--include";
vassal_argv[counter + 1] = uct->value;
counter += 2;
uct = uct->next;
}
vassal_argv[counter] = NULL;
@@ -1121,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
@@ -1471,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) {
@@ -1577,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) {
@@ -1607,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;
}
}
@@ -1703,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;
@@ -1846,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;
@@ -1901,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);
}
+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__
+4 -1
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;
@@ -176,6 +178,7 @@ void uwsgi_init_default() {
// clear reforked status
uwsgi.master_is_reforked = 0;
uwsgi.master_fifo_fd = -1;
uwsgi_master_fifo_prepare();
}
@@ -463,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
+13 -33
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");
@@ -387,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) {
@@ -735,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
+14
View File
@@ -118,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");
@@ -322,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);
}
}
}
+5
View File
@@ -40,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;
+13 -7
View File
@@ -151,7 +151,13 @@ int uwsgi_calc_cheaper(void) {
uwsgi.cheaper_fifo_delta = 0;
}
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
// 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++) {
@@ -189,7 +195,7 @@ int uwsgi_calc_cheaper(void) {
}
// fake algo to allow control with the fifo
int uwsgi_cheaper_algo_manual(void) {
int uwsgi_cheaper_algo_manual(int can_spawn) {
return 0;
}
@@ -228,7 +234,7 @@ int uwsgi_cheaper_algo_manual(void) {
*/
int uwsgi_cheaper_algo_spare(void) {
int uwsgi_cheaper_algo_spare(int can_spawn) {
int i;
static uint64_t overload_count = 0;
@@ -252,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");
@@ -320,7 +326,7 @@ healthy:
*/
int uwsgi_cheaper_algo_backlog(void) {
int uwsgi_cheaper_algo_backlog(int can_spawn) {
int i;
#ifdef __linux__
@@ -329,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
@@ -1345,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;
+19 -3
View File
@@ -16,6 +16,7 @@
#ifndef MS_REC
#define MS_REC 16384
#endif
#include <sys/statfs.h>
#endif
struct uwsgi_mount_flag {
@@ -102,7 +103,7 @@ 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;
@@ -121,7 +122,7 @@ int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
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;
@@ -189,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;
@@ -236,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
}
+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;
+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
+20 -13
View File
@@ -1673,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;
}
@@ -1714,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;
@@ -1747,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;
@@ -1877,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;
+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;
}
+896 -841
View File
File diff suppressed because it is too large Load Diff
+173 -172
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,11 +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 (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},
@@ -306,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},
@@ -406,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},
@@ -462,6 +479,11 @@ 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},
{"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},
@@ -833,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
@@ -856,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},
@@ -878,140 +903,6 @@ void show_config(void) {
}
int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char *value) {
int configured;
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
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);
}
retry:
configured = uwsgi_manage_opt(new_key, new_value);
if (!configured && uwsgi.autoload) {
if (uwsgi_try_autoload(new_key)) goto retry;
}
}
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;
@@ -1051,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);
@@ -1061,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] == '/') {
@@ -1084,16 +995,31 @@ void config_magic_table_fill(char *filename, char **magic_table) {
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) {
@@ -1473,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;
}
@@ -1958,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");
@@ -2113,6 +2051,9 @@ 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;
@@ -2385,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
@@ -2393,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
@@ -2410,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);
@@ -2576,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)) {
@@ -2588,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);
@@ -2599,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
@@ -2763,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
@@ -3104,6 +3048,7 @@ next2:
}
}
// END OF INITIALIZATION
// !!! from now on, we could be in the master or in a worker !!!
@@ -3442,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;
@@ -3481,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;
}
}
/*
@@ -3922,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;
@@ -3930,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) {
@@ -3939,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] = '=';
}
@@ -3997,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);
@@ -4021,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__
@@ -4291,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) {
@@ -4572,3 +4553,23 @@ void uwsgi_update_pidfiles() {
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;
}
+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,
};
+101 -9
View File
@@ -2,6 +2,13 @@
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>
@@ -9,9 +16,9 @@
extern struct uwsgi_server uwsgi;
#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>
@@ -24,22 +31,45 @@ extern struct uwsgi_server uwsgi;
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},
@@ -61,6 +91,7 @@ static struct uwsgi_option forkptyrouter_options[] = {
// 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;
@@ -68,7 +99,13 @@ static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
// the chunk has been sent, start (again) reading from client and instances
if (cr_write_complete(peer)) {
// reset the buffer
peer->out->pos = 0;
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);
}
@@ -91,6 +128,42 @@ static ssize_t fpty_write(struct corerouter_peer *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()");
@@ -106,10 +179,22 @@ static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
// 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;
main_peer->session->peers->out = main_peer->in;
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);
@@ -137,12 +222,19 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
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, NULL);
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
if (fpty_session->pid < 0) {
uwsgi_error("forkpty()");
return -1;
@@ -156,23 +248,23 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
argv[1] = "-c";
argv[2] = ufpty.cmd;
argv[3] = NULL;
execve(argv[0], argv, uwsgi.environ);
execv(argv[0], argv);
}
else {
char *argv[2];
argv[0] = ufpty.cmd;
argv[1] = NULL;
execve(argv[0], argv, uwsgi.environ);
execv(argv[0], argv);
}
}
else {
char *argv[2];
argv[0] = "/bin/sh";
argv[1] = NULL;
execve(argv[0], argv, uwsgi.environ);
execv(argv[0], argv);
}
// never here;
uwsgi_error("forkptyrouter_alloc_session()/execve()");
uwsgi_error("forkptyrouter_alloc_session()/execv()");
exit(1);
}
+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':
+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']
+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) {
+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);
+6 -27
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);
+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++;
+51 -8
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,7 +77,8 @@ 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", 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,17 +258,40 @@ 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);
@@ -277,8 +302,15 @@ static int uwsgi_pty_client() {
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
+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;
+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);
}
+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;
}
+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'
+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-22'
s.date = '2013-10-11'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+63 -14
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
@@ -197,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>
@@ -237,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
@@ -308,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>
@@ -554,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;
};
@@ -585,6 +590,7 @@ struct uwsgi_daemon {
char *legion;
#endif
int control;
struct uwsgi_daemon *next;
};
@@ -1516,6 +1522,8 @@ struct wsgi_request {
char *transformed_chunk;
size_t transformed_chunk_len;
int is_raw;
struct msghdr msg;
union {
struct cmsghdr cmsg;
@@ -1555,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;
};
@@ -1718,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;
@@ -1727,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
@@ -1751,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;
@@ -1763,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;
@@ -1787,6 +1800,8 @@ struct uwsgi_server {
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;
@@ -1863,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
@@ -2193,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
@@ -2261,6 +2282,7 @@ struct uwsgi_server {
int harakiri_verbose;
int harakiri_no_arh;
int magic_table_first_round;
char *magic_table[256];
int numproc;
@@ -2547,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 {
@@ -2961,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);
@@ -3147,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 *);
@@ -3191,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);
@@ -3422,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));
@@ -3454,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 *);
@@ -3462,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 *);
@@ -3479,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 *);
@@ -3562,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 *);
@@ -3600,16 +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_manual(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);
@@ -3818,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 *);
@@ -4055,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);
@@ -4339,6 +4375,19 @@ 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
}
#endif
+164 -80
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.17'
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)
@@ -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)