Compare commits

..
98 Commits
Author SHA1 Message Date
Unbit f387d27582 prepare for 1.9.15 2013-08-29 10:49:21 +02:00
Unbit 5d8e5d943f improved smartos support 2013-08-29 10:30:01 +00:00
Unbit 4046f76cb2 completed emperor hooks 2013-08-28 15:00:22 +02:00
Unbit 8baeb0af2f prepare for more emperor hooks 2013-08-28 13:25:52 +02:00
Unbit 63e0105a0f added interface waiting infrastructure 2013-08-28 12:43:26 +02:00
Unbit 70daa57caf Merge branch 'master' of github.com:unbit/uwsgi 2013-08-28 11:49:07 +02:00
Unbit db0f7951a9 added --exec-as-vassal and fixed 'fs' unshare 2013-08-28 11:48:51 +02:00
unbit 45a7a3066d Merge pull request #368 from Kapishin/master
Fix two typos in comments
2013-08-27 23:07:20 -07:00
Pavlo Kapyshin c73a6723d7 Fix two typos in comments 2013-08-28 08:57:58 +03:00
Unbit fb55f57531 added --emperor-use-clone 2013-08-27 21:47:00 +02:00
unbit 8cf4d5802a fixed FreeBSD support for pty plugin 2013-08-26 17:42:25 +02:00
Unbit e3c042e567 pty requires -lutil on linux 2013-08-26 15:44:31 +02:00
Unbit 5435f8927c added vassal's hooks 2013-08-26 10:13:08 +02:00
Unbit e1e65c46ac added --refork option 2013-08-26 10:05:41 +02:00
Unbit e1f3665a8e do not set sys,argv in pypy if already available 2013-08-26 05:38:19 +02:00
Unbit ef09a010cf allows pypy plugin to detect already available pypy environment 2013-08-26 05:01:28 +02:00
Unbit 3f5d79c755 added UWSGI_AS_LIB 2013-08-25 19:42:59 +02:00
unbit 3b5468f39f added FreeBSD support to pty plugin 2013-08-25 18:43:44 +02:00
Roberto De Ioris 5598c7cc22 added pty support to OpenBSD 2013-08-25 20:41:28 +02:00
Unbit d6fdb812a2 improved postfork() decorator 2013-08-25 18:35:56 +02:00
Unbit e6d5f6c612 fixed #366 2013-08-23 20:49:39 +02:00
Unbit 8f10daa2bf fixed pty binding 2013-08-23 19:16:38 +02:00
Unbit f027153452 exit on failed --pty-connect 2013-08-23 18:48:07 +02:00
Unbit 0ebda93a50 fixed #365 2013-08-23 18:41:10 +02:00
Unbit dc4e8950d2 sanitize pty options 2013-08-23 17:50:31 +02:00
Unbit 0f5336028f added OSX support for the pty plugin 2013-08-23 16:28:12 +02:00
Unbit e02341bffe include pty.h only on linux 2013-08-23 16:21:40 +02:00
Unbit ac92ff4079 added the pty plugin 2013-08-23 16:19:33 +02:00
Unbit a5da77bc54 added --add-gid 2013-08-23 14:46:06 +02:00
Unbit 0441e88b82 track unix sockets inode to reduce accidental removal on vacuum 2013-08-23 14:28:01 +02:00
Unbit 815f4abec0 fixed #364 2013-08-23 13:59:13 +02:00
Unbit 4f9e2ff3f6 added --perl-exec and --perl-exec-post-fork 2013-08-23 11:50:18 +02:00
Unbit ce8dd001bf ported uwsgi.cache_keys to pypy 2013-08-23 11:06:24 +02:00
Unbit d4e90f5215 added uwsgi.cache_keys function api 2013-08-23 10:43:13 +02:00
unbit da13562890 Merge pull request #362 from KLab/log-ftime
Add `%(ftime)` to logformat.
2013-08-20 00:58:20 -07:00
INADA Naoki d320075ab0 Add %(ftime) to logformat. 2013-08-20 16:45:59 +09:00
Unbit 4061826da4 try to fix python3 static files handling 2013-08-20 07:32:41 +02:00
Unbit 2854321891 improved python3 exceptions management 2013-08-16 07:09:50 +02:00
Unbit c4181cdc55 fixed type in pypy wsgi.input.read 2013-08-14 11:59:42 +02:00
Unbit 327582b695 added --worker-exec2 2013-08-14 10:16:39 +02:00
Unbit f56b9be4c5 allow post_fork hook on general plugins 2013-08-13 19:19:22 +02:00
Unbit 28ccace24f implemented --call hooks 2013-08-12 12:42:32 +02:00
Unbit 13f82176e3 added init_func support for plugins, and --need-plugin variant 2013-08-11 10:22:36 +02:00
Unbit be4d324f6b better symbol detection for pypy 2013-08-11 08:41:02 +02:00
Unbit 36486caabb sizeof on string includes NULL ... 2013-08-11 08:27:20 +02:00
Unbit b3af255727 Merge branch 'master' of github.com:unbit/uwsgi 2013-08-11 07:09:04 +02:00
Unbit a56f726f7d fixed a typo 2013-08-11 07:06:30 +02:00
unbit 24d6470f38 Merge pull request #359 from ryanpetrello/master
Add plugin support for the pecan WSGI framework (http://pecanpy.org).
2013-08-09 23:47:37 -07:00
Ryan Petrello 7e079e4c40 Add my name to the contributors list. 2013-08-10 01:00:12 -04:00
Ryan Petrello 0d9bc03c53 Add plugin support for the pecan WSGI framework (http://pecanpy.org). 2013-08-10 00:44:40 -04:00
Unbit 7598666768 added UWSGI_REMOVE_INCLUDES 2013-08-08 18:27:54 +02:00
Unbit cd6f027705 avoid unix nameclash on cygwin 2013-08-08 11:23:09 +02:00
Roberto De Ioris 0803a7f0b0 added router_expires 2013-08-07 08:14:38 +02:00
Roberto De Ioris 0eb956db4a example mv again 2013-08-06 07:39:20 +02:00
Roberto De Ioris 76c6ae6d16 mv again 2013-08-06 07:38:11 +02:00
Roberto De Ioris 40054e3494 another series of mv 2013-08-06 07:36:16 +02:00
Roberto De Ioris 8927dfd538 moved example files 2013-08-06 07:33:40 +02:00
Roberto De Ioris 68f734fcad announce legion's death on reload 2013-08-06 07:15:35 +02:00
Roberto De Ioris af4c7f74d5 fixed legion death 2013-08-06 07:08:42 +02:00
Roberto De Ioris 4581d1e7ce announce legion death on uwsgi exit 2013-08-06 06:58:04 +02:00
Unbit d465f61506 fix volfile report 2013-07-31 10:14:22 +02:00
Unbit 5cae9b9ba4 fixed glusterfs volfile support 2013-07-31 10:05:49 +02:00
unbit 428a2d9366 Merge pull request #350 from prymitive/matheval_fix
fix matheval check in build profiles
2013-07-30 19:52:39 -07:00
unbit 1c00b54b06 Merge pull request #351 from prymitive/dot_h
handle core/dot_h.c as other build objects
2013-07-30 08:57:39 -07:00
Unbit 6228fb91da preliminary async support for glusterfs 2013-07-30 16:42:56 +02:00
Łukasz Mierzwa 307cf3a0ef add autogenerated core/dot_h.c to .gitignore, so it won't be added by mistake to git, also remove it during make clean 2013-07-30 10:54:33 +02:00
Łukasz Mierzwa f723a804c0 fix matheval check in build profiles, currently matheval is always required while it should be only used if present or if requested by user 2013-07-30 10:27:02 +02:00
Unbit 24ac19e2d6 added last-modified to glusterfs 2013-07-29 17:40:06 +02:00
Unbit 38147d50ff check for matheval 2013-07-29 16:55:28 +02:00
Unbit 9f7db10582 first working glusterfs plugin prototype 2013-07-29 16:50:00 +02:00
Unbit ed35a50e6c rewrite ruby libdir on heroku 2013-07-29 08:49:25 +02:00
Unbit fae08f49cf another heroku workaround 2013-07-29 08:45:33 +02:00
Unbit 35f5b5b2eb improved ruby libdir detection for static builds 2013-07-29 08:25:06 +02:00
Unbit b785c8fccf added a check for ruby --enable-load-relative 2013-07-28 08:50:44 +02:00
Unbit 597c3cd7f1 try removing ruby_sysinit 2013-07-28 06:23:39 +02:00
Unbit bbbe01ef4b change ruby_process_options with ruby_options [5] 2013-07-27 23:49:49 +02:00
Unbit ea1e1cb65f change ruby_process_options with ruby_options [4] 2013-07-27 23:42:05 +02:00
Unbit a1d31ae954 change ruby_process_options with ruby_options [3] 2013-07-27 23:19:15 +02:00
Unbit fa0ed9489a change ruby_process_options with ruby_options [2] 2013-07-27 23:13:37 +02:00
Unbit 7bb7b351e0 change ruby_process_options with ruby_options 2013-07-27 23:01:09 +02:00
Unbit cb45f207a6 another attempt to make heroku happy [6] 2013-07-27 22:46:31 +02:00
Unbit 82ffb60bdd another attempt to make heroku happy [5] 2013-07-27 22:42:16 +02:00
Unbit ec38ce9a26 another attempt to make heroku happy [4] 2013-07-27 22:37:43 +02:00
Unbit 8279926bab another attempt to make heroku happy [3] 2013-07-27 22:18:18 +02:00
Unbit ac17b0910e another attempt to make heroku happy [2] 2013-07-27 22:09:29 +02:00
Unbit aae3e7ff17 another attempt to make heroku happy 2013-07-27 22:04:02 +02:00
Unbit 4cfff98cd1 try to workaround heroku 2013-07-27 22:01:21 +02:00
Unbit 19ee50949c skeleton for glusterfs plugin 2013-07-27 21:48:00 +02:00
Unbit ec27d624c3 fixed http-keepalive memleak 2013-07-26 12:17:23 +02:00
Unbit 0dc8803ff8 added --force-gateway 2013-07-26 12:03:38 +02:00
Unbit e8ea1a55f9 fixed #112 2013-07-25 21:56:29 +02:00
Unbit a0cb71ca78 added --strict mode 2013-07-25 21:24:04 +02:00
Unbit 5c5aef3827 1.9.15 development starts 2013-07-23 11:00:18 +02:00
Unbit 737a7f4d51 attempt to fix spooler's body in python 2013-07-23 08:40:11 +02:00
Unbit c3ee774d56 Merge branch 'master' of github.com:unbit/uwsgi 2013-07-23 06:28:29 +02:00
Unbit 2d5adacc65 preliminary python profiler for python3 2013-07-23 06:28:10 +02:00
unbit b7a8cc0297 Merge pull request #345 from pingswept/patch-1
Convert tabs to spaces to fix indentation error
2013-07-22 12:36:44 -07:00
Brandon Stafford 317b0f79a8 Convert tabs to spaces to fix indentation error
The uwsgi.websocket_handshake call on line 52 was not indented properly, causing the Python interpreter to choke. Converting the few tabs sprinkled through the document to spaces fixes that error.
2013-07-22 15:22:44 -04:00
68 changed files with 1859 additions and 382 deletions
+2
View File
@@ -9,3 +9,5 @@
/uwsgibuild.*
/t/ring/target
core/dot_h.c
+1
View File
@@ -24,3 +24,4 @@ Stephen Pierce
Mingli Yuan
Natanael Copa
Roberto Leandrini
Ryan Petrello
+2 -1
View File
@@ -6,6 +6,7 @@ zeromq = auto
ssl = auto
pcre = auto
routing = auto
matheval = auto
debug = false
unbit = false
xml_implementation = libxml2
@@ -16,7 +17,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
as_shared_library = false
locking = auto
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
+1 -1
View File
@@ -368,7 +368,7 @@ void async_loop() {
uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_main) {
uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
+5 -1
View File
@@ -3,6 +3,9 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
#endif
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
if (len) {
@@ -271,8 +274,9 @@ int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
if (ub->freed) {
uwsgi_log("[BUG] buffer at %p already destroyed !!!\n", ub);
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
}
ub->freed = 1;
#endif
+34
View File
@@ -204,6 +204,7 @@ static void uwsgi_cache_add_items(struct uwsgi_cache *uc) {
next:
usl = usl->next;
}
}
static void uwsgi_cache_load_files(struct uwsgi_cache *uc) {
@@ -1920,3 +1921,36 @@ void uwsgi_cache_setup_nodes(struct uwsgi_cache *uc) {
}
}
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *uc, uint64_t *pos, struct uwsgi_cache_item **uci) {
// security check
if (*pos >= uc->hashsize) return NULL;
// iterate hashtable
uint64_t orig_pos = *pos;
for(;*pos<uc->hashsize;(*pos)++) {
// get the cache slot
uint64_t slot = uc->hashtable[*pos];
if (*pos == orig_pos && *uci) {
slot = (*uci)->next;
}
if (slot == 0) continue;
*uci = cache_item(slot);
return *uci;
}
(*pos)++;
return NULL;
}
void uwsgi_cache_rlock(struct uwsgi_cache *uc) {
uwsgi_rlock(uc->lock);
}
void uwsgi_cache_rwunlock(struct uwsgi_cache *uc) {
uwsgi_rwunlock(uc->lock);
}
char *uwsgi_cache_item_key(struct uwsgi_cache_item *uci) {
return uci->key;
}
+17
View File
@@ -458,6 +458,23 @@ 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() {
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
char *argv[3];
argv[0] = uwsgi.binary_path;
argv[1] = uwsgi.fallback_config;
argv[2] = NULL;
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
}
}
+121 -14
View File
@@ -790,15 +790,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *);
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
@@ -822,9 +817,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// TODO pre-start hook
// a new uWSGI instance will start
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
if (uwsgi.emperor_clone) {
char stack[PTHREAD_STACK_MIN];
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
}
else {
#endif
pid = fork();
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
}
#endif
if (pid < 0) {
uwsgi_error("fork()")
uwsgi_error("uwsgi_emperor_spawn_vassal()/fork()")
}
else if (pid > 0) {
n_ui->pid = pid;
@@ -854,9 +859,72 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// once the config is sent we can run hooks (they can fail)
// exec hooks have access to all of the currently defined vars + UWSGI_VASSAL_PID, UWSGI_VASSAL_UID, UWSGI_VASSAL_GID, UWSGI_VASSAL_CONFIG
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
uwsgi_log("running \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
char *argv[4];
argv[0] = uwsgi_concat2("UWSGI_VASSAL_CONFIG=", n_ui->name);
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", n_ui->pid); argv[1] = argv_pid;
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", n_ui->uid); argv[2] = argv_uid;
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", n_ui->gid); argv[3] = argv_gid;
int ret = uwsgi_run_command_putenv_and_wait(NULL, usl->value, argv, 4);
uwsgi_log("command \"%s\" exited with code: %d\n", usl->value, ret);
free(argv[0]);
}
// 4 call hooks
// config / config + pid / config + pid + uid + gid
// call
uwsgi_foreach(usl, uwsgi.call_as_emperor) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func();
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor2) {
void (*func)(char *, pid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid);
}
}
uwsgi_foreach(usl, uwsgi.call_as_emperor4) {
void (*func)(char *, pid_t, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
}
else {
func(n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
}
}
return 0;
}
else {
uwsgi_emperor_spawn_vassal(n_ui);
}
return -1;
}
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
@@ -879,7 +947,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
char *uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
@@ -905,7 +973,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
free(uef);
}
uenvs = environ;
char **uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
@@ -942,17 +1010,19 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
close(n_ui->pipe_config[0]);
}
counter = 4;
int counter = 4;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while (uct) {
counter += 2;
uct = uct->next;
}
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
// set args
vassal_argv[0] = uwsgi.binary_path;
char *colon = NULL;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
if (colon) {
@@ -1037,6 +1107,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
// close all of the unneded fd
int i;
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
if (n_ui->use_config) {
@@ -1048,6 +1119,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
}
// run start hook (can fail)
if (uwsgi.vassals_start_hook) {
uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
if (uwsgi.emperor_absolute_dir) {
@@ -1059,6 +1131,44 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
}
// run exec hooks (cannot fail)
uwsgi_foreach(usl, uwsgi.exec_as_vassal) {
uwsgi_log("running \"%s\" (as-vassal)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
}
// run low-level hooks
uwsgi_foreach(usl, uwsgi.call_as_vassal) {
void (*func)(void) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func();
}
uwsgi_foreach(usl, uwsgi.call_as_vassal1) {
void (*func)(char *) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name);
}
uwsgi_foreach(usl, uwsgi.call_as_vassal3) {
void (*func)(char *, uid_t, gid_t) = dlsym(RTLD_DEFAULT, usl->value);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", usl->value);
exit(1);
}
func(n_ui->name, n_ui->uid, n_ui->gid);
}
// start !!!
if (execvp(vassal_argv[0], vassal_argv)) {
uwsgi_error("execvp()");
@@ -1066,9 +1176,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
// never here
exit(UWSGI_EXILE_CODE);
}
return -1;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
+1 -1
View File
@@ -41,7 +41,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process)
if (!uwsgi.master_process && !uwsgi.force_gateway)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
+2
View File
@@ -387,6 +387,8 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
return uwsgi.mypid;
}
+25 -2
View File
@@ -79,6 +79,9 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
ul->scroll = value;
ul->scroll_len = vallen;
}
else if (!uwsgi_strncmp(key, keylen, "dead", 4)) {
ul->dead = 1;
}
}
// this function is called when a node is added or removed (heavy locking is needed)
@@ -611,6 +614,14 @@ static void *legion_loop(void *foobar) {
usl = usl->next;
}
}
// remove node announcing death
else if (legion_msg.dead) {
uwsgi_log("[uwsgi-legion] %s: %.*s valor: %llu uuid: %.*s announced its death to Legion %s\n", node->valor > 0 ? "node" : "arbiter", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
uwsgi_wlock(ul->lock);
uwsgi_legion_remove_node(ul, node);
uwsgi_rwunlock(ul->lock);
continue;
}
node->last_seen = uwsgi_now();
node->lord_valor = legion_msg.lord_valor;
@@ -752,8 +763,11 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
goto err;
}
#ifdef UWSGI_UUID
#endif
if (ul->dead) {
if (uwsgi_buffer_append_keyval(ub, "dead", 4, "1", 1))
goto err;
}
unsigned char *encrypted = uwsgi_malloc(ub->pos + 4 + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(ul->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
@@ -1122,6 +1136,14 @@ void uwsgi_legion_action_register(char *name, int (*func) (struct uwsgi_legion *
}
}
void uwsgi_legion_announce_death(void) {
struct uwsgi_legion *legion = uwsgi.legions;
while (legion) {
legion->dead = 1;
uwsgi_legion_announce(legion);
legion = legion->next;
}
}
void uwsgi_legion_atexit(void) {
struct uwsgi_legion *legion = uwsgi.legions;
@@ -1140,6 +1162,7 @@ next:
legion = legion->next;
}
uwsgi_legion_announce_death();
}
int uwsgi_legion_i_am_the_lord(char *name) {
+22 -4
View File
@@ -45,7 +45,7 @@ void uwsgi_log(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -97,7 +97,7 @@ void uwsgi_log_verbose(const char *fmt, ...) {
}
else {
gettimeofday(&tv, NULL);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &tv.tv_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &tv.tv_sec, ctime_storage);
@@ -616,7 +616,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
break;
}
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, time_request);
@@ -1035,7 +1035,7 @@ static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_malloc(26);
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf);
@@ -1060,6 +1060,19 @@ static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
return ret;
}
static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
if (!uwsgi.log_strftime) {
return uwsgi_lf_ltime(wsgi_req, buf);
}
*buf = uwsgi_malloc(64);
time_t now = wsgi_req->start_of_request / 1000000;
size_t ret = strftime(*buf, 64, uwsgi.log_strftime, localtime(&now));
if (ret == 0) {
*buf[0] = 0;
return 0;
}
return ret;
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
@@ -1246,6 +1259,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ftime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ftime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
+1 -1
View File
@@ -393,7 +393,7 @@ int master_loop(char **argv, char **environ) {
}
if (uwsgi.stats) {
char *tcp_port = strchr(uwsgi.stats, ':');
char *tcp_port = strrchr(uwsgi.stats, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
+12
View File
@@ -98,6 +98,12 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
colon[0] = ':';
}
char *init_func = strchr(plugin_name, '|');
if (init_func) {
init_func[0] = 0;
init_func++;
}
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
@@ -157,6 +163,12 @@ success:
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
if (init_func) {
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
if (plugin_init_func) {
plugin_init_func();
}
}
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
+4
View File
@@ -1714,6 +1714,10 @@ void uwsgi_bind_sockets() {
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
}
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
struct stat st;
if (uwsgi_sock->name[0] != '@' && !stat(uwsgi_sock->name, &st)) {
uwsgi_sock->inode = st.st_ino;
}
}
else {
#ifdef AF_INET6
+3
View File
@@ -227,15 +227,18 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
#endif
if (write(fd, &uh, 4) != 4) {
uwsgi_log("[spooler] unable to write header for %s\n", filename);
goto clear;
}
if (write(fd, buffer, size) != size) {
uwsgi_log("[spooler] unable to write args for %s\n", filename);
goto clear;
}
if (body && body_len > 0) {
if ((size_t) write(fd, body, body_len) != body_len) {
uwsgi_log("[spooler] unable to write body for %s\n", filename);
goto clear;
}
}
+153 -26
View File
@@ -191,6 +191,8 @@ void daemonize(char *logfile) {
// get current working directory
char *uwsgi_get_cwd() {
if (uwsgi.force_cwd) return uwsgi.force_cwd;
// set this to static to avoid useless reallocations in stats mode
static size_t newsize = 256;
@@ -370,18 +372,49 @@ void uwsgi_as_root() {
#endif
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.wait_for_interface) {
if (!uwsgi.wait_for_interface_timeout) {
uwsgi.wait_for_interface_timeout = 60;
}
uwsgi_log("waiting for interface %s (max %d seconds) ...\n", usl->value, uwsgi.wait_for_interface_timeout);
int counter = 0;
for(;;) {
if (counter > uwsgi.wait_for_interface_timeout) {
uwsgi_log("interface %s unavailable after %d seconds\n", usl->value, counter);
exit(1);
}
unsigned int index = if_nametoindex(usl->value);
if (index > 0) {
uwsgi_log("interface %s found with index %u\n", usl->value, index);
break;
}
else {
sleep(1);
counter++;
}
}
}
// now run the scripts needed by root
struct uwsgi_string_list *usl = uwsgi.exec_as_root;
while (usl) {
uwsgi_foreach(usl, uwsgi.exec_as_root) {
uwsgi_log("running \"%s\" (as root)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_root) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
if (uwsgi.gidname) {
struct group *ugroup = getgrnam(uwsgi.gidname);
if (ugroup) {
@@ -480,6 +513,31 @@ void uwsgi_as_root() {
exit(1);
}
}
struct uwsgi_string_list *usl;
size_t ags = 0;
uwsgi_foreach(usl, uwsgi.additional_gids) ags++;
if (ags > 0) {
gid_t *ags_list = uwsgi_calloc(sizeof(gid_t) * ags);
size_t g_pos = 0;
uwsgi_foreach(usl, uwsgi.additional_gids) {
ags_list[g_pos] = atoi(usl->value);
if (!ags_list[g_pos]) {
struct group *g = getgrnam(usl->value);
if (g) {
ags_list[g_pos] = g->gr_gid;
}
else {
uwsgi_log("unable to find group %s\n", usl->value);
exit(1);
}
}
g_pos++;
}
if (setgroups(ags, ags_list)) {
uwsgi_error("setgroups()");
exit(1);
}
}
int additional_groups = getgroups(0, NULL);
if (additional_groups > 0) {
gid_t *gids = uwsgi_calloc(sizeof(gid_t) * additional_groups);
@@ -536,18 +594,42 @@ void uwsgi_as_root() {
}
#endif
if (uwsgi.refork) {
uwsgi_log("re-fork()ing...\n");
pid_t pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
exit(1);
}
if (pid > 0) {
// block all signals
sigset_t smask;
sigfillset(&smask);
sigprocmask(SIG_BLOCK, &smask, NULL);
int status;
if (waitpid(pid, &status, 0) < 0) {
uwsgi_error("waitpid()");
}
_exit(0);
}
}
// now run the scripts needed by the user
usl = uwsgi.exec_as_user;
while (usl) {
uwsgi_foreach(usl, uwsgi.exec_as_user) {
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_user) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
// we could now patch the binary
if (uwsgi.unprivileged_binary_patch) {
uwsgi.argv[0] = uwsgi.unprivileged_binary_patch;
@@ -1932,23 +2014,9 @@ void uwsgi_exec_command_with_args(char *cmdline) {
exit(1);
}
int uwsgi_run_command_and_wait(char *command, char *arg) {
static int uwsgi_run_command_do(char *command, char *arg) {
char *argv[4];
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
@@ -1976,6 +2044,54 @@ int uwsgi_run_command_and_wait(char *command, char *arg) {
exit(1);
}
int uwsgi_run_command_and_wait(char *command, char *arg) {
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
return uwsgi_run_command_do(command, arg);
}
int uwsgi_run_command_putenv_and_wait(char *command, char *arg, char **envs, unsigned int nenvs) {
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid > 0) {
if (waitpid(pid, &waitpid_status, 0) < 0) {
uwsgi_error("uwsgi_run_command_and_wait()/waitpid()");
return -1;
}
return WEXITSTATUS(waitpid_status);
}
unsigned int i;
for(i=0;i<nenvs;i++) {
if (putenv(envs[i])) {
uwsgi_error("uwsgi_run_command_putenv_and_wait()/putenv()");
exit(1);
}
}
return uwsgi_run_command_do(command, arg);
}
pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
char *argv[4];
@@ -2319,9 +2435,6 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
#ifdef CLONE_FILES
{"files", CLONE_FILES},
#endif
#ifdef CLONE_FS
{"fs", CLONE_FS},
#endif
#ifdef CLONE_NEWIPC
{"ipc", CLONE_NEWIPC},
#endif
@@ -2333,6 +2446,7 @@ static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
#endif
#ifdef CLONE_NEWNS
{"ns", CLONE_NEWNS},
{"fs", CLONE_NEWNS},
{"mount", CLONE_NEWNS},
#endif
#ifdef CLONE_SYSVSEM
@@ -2356,7 +2470,7 @@ static int uwsgi_get_unshare_id(char *name) {
return -1;
}
void uwsgi_build_unshare(char *what) {
void uwsgi_build_unshare(char *what, int *mask) {
char *list = uwsgi_str(what);
@@ -2364,7 +2478,7 @@ void uwsgi_build_unshare(char *what) {
while (p != NULL) {
int u_id = uwsgi_get_unshare_id(p);
if (u_id != -1) {
uwsgi.unshare |= u_id;
*mask |= u_id;
}
p = strtok(NULL, ",");
}
@@ -3304,6 +3418,13 @@ error:
return -1;
}
int uwsgi_call_symbol(char *symbol) {
void (*func)(void) = dlsym(RTLD_DEFAULT, symbol);
if (!func) return -1;
func();
return 0;
}
int uwsgi_plugin_modifier1(char *plugin) {
int ret = -1;
char *symbol_name = uwsgi_concat2(plugin, "_plugin");
@@ -3736,3 +3857,9 @@ void uwsgi_envdirs(struct uwsgi_string_list *envdirs) {
void uwsgi_opt_envdir(char *opt, char *value, void *foobar) {
uwsgi_envdir(value);
}
void uwsgi_exit(int status) {
uwsgi.last_exit_code = status;
// disable macro expansion
(exit)(status);
}
+165 -17
View File
@@ -59,7 +59,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possibie)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI, 0},
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose, 0},
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
@@ -72,6 +72,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"config", required_argument, 0, "load configuration using the pluggable system", uwsgi_opt_load_config, NULL, UWSGI_OPT_IMMEDIATE},
{"fallback-config", required_argument, 0, "re-exec uwsgi with the specified config when exit code is 1", uwsgi_opt_set_str, &uwsgi.fallback_config, UWSGI_OPT_IMMEDIATE},
{"strict", no_argument, 0, "enable strict mode (placeholder cannot be used)", uwsgi_opt_true, &uwsgi.strict, UWSGI_OPT_IMMEDIATE},
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
@@ -192,6 +194,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
#endif
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
@@ -204,6 +209,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
@@ -284,6 +290,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
{"add-gid", required_argument, 0, "add the specified group id to the process credentials", uwsgi_opt_add_string_list, &uwsgi.additional_gids, 0},
{"immediate-uid", required_argument, 0, "setuid to the specified user/uid IMMEDIATELY", uwsgi_opt_set_immediate_uid, NULL, UWSGI_OPT_IMMEDIATE},
{"immediate-gid", required_argument, 0, "setgid to the specified group/gid IMMEDIATELY", uwsgi_opt_set_immediate_gid, NULL, UWSGI_OPT_IMMEDIATE},
{"no-initgroups", no_argument, 0, "disable additional groups set via initgroups()", uwsgi_opt_true, &uwsgi.no_initgroups, 0},
@@ -291,8 +298,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"cap", required_argument, 0, "set process capability", uwsgi_opt_set_cap, NULL, 0},
#endif
#ifdef __linux__
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, 0},
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
#endif
{"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
{"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
{"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0},
{"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0},
@@ -301,6 +311,42 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
{"exec-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.exec_as_vassal, 0},
{"exec-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.exec_as_emperor, 0},
{"wait-for-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-for-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-for-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-for-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
{"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0},
{"call-as-root", required_argument, 0, "call the specified function before privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_root, 0},
{"call-as-user", required_argument, 0, "call the specified function after privileges drop", uwsgi_opt_add_string_list, &uwsgi.call_as_user, 0},
{"call-as-user-atexit", required_argument, 0, "call the specified function before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.call_as_user_atexit, 0},
{"call-pre-app", required_argument, 0, "call the specified function before app loading", uwsgi_opt_add_string_list, &uwsgi.call_pre_app, 0},
{"call-post-app", required_argument, 0, "call the specified function after app loading", uwsgi_opt_add_string_list, &uwsgi.call_post_app, 0},
{"call-as-vassal", required_argument, 0, "call the specified function() before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal, 0},
{"call-as-vassal1", required_argument, 0, "call the specified function(char *) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal1, 0},
{"call-as-vassal3", required_argument, 0, "call the specified function(char *, uid_t, gid_t) before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.call_as_vassal3, 0},
{"call-as-emperor", required_argument, 0, "call the specified function() in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor, 0},
{"call-as-emperor1", required_argument, 0, "call the specified function(char *) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor1, 0},
{"call-as-emperor2", required_argument, 0, "call the specified function(char *, pid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor2, 0},
{"call-as-emperor4", required_argument, 0, "call the specified function(char *, pid_t, uid_t, gid_t) in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.call_as_emperor4, 0},
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
#ifdef UWSGI_YAML
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
@@ -510,6 +556,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
{"force-cwd", required_argument, 0, "force the initial working directory to the specified value", uwsgi_opt_set_str, &uwsgi.force_cwd, 0},
{"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
{"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
@@ -688,6 +735,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"loop-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
@@ -699,6 +747,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"daemons-honour-stdin", no_argument, 0, "do not change the stdin of external daemons to /dev/null", uwsgi_opt_true, &uwsgi.daemons_honour_stdin, UWSGI_OPT_MASTER},
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"need-plugins", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"need-plugin", required_argument, 0, "load uWSGI plugins (exit on error)", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"plugin-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
{"plugins-list", no_argument, 0, "list enabled plugins", uwsgi_opt_true, &uwsgi.plugins_list, 0},
@@ -1103,6 +1153,10 @@ void grace_them_all(int signum) {
uwsgi_log("...gracefully killing workers...\n");
#ifdef UWSGI_SSL
uwsgi_legion_announce_death();
#endif
if (uwsgi.unsubscribe_on_graceful_reload) {
uwsgi_unsubscribe_all();
}
@@ -1172,6 +1226,10 @@ void reap_them_all(int signum) {
uwsgi_log("...brutally killing workers...\n");
#ifdef UWSGI_SSL
uwsgi_legion_announce_death();
#endif
// unsubscribe if needed
uwsgi_unsubscribe_all();
@@ -1253,7 +1311,7 @@ void what_i_am_doing() {
for (i = 0; i < uwsgi.cores; i++) {
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req;
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
@@ -1270,7 +1328,7 @@ void what_i_am_doing() {
else {
wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[0].req;
if (wsgi_req->uri_len > 0) {
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage, 26);
#else
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, ctime_storage);
@@ -1309,15 +1367,21 @@ struct uwsgi_plugin unconfigured_plugin = {
void uwsgi_exec_atexit(void) {
if (getpid() == masterpid) {
// now run exit scripts needed by the user
struct uwsgi_string_list *usl = uwsgi.exec_as_user_atexit;
while (usl) {
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_as_user_atexit) {
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
}
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_as_user_atexit) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
}
}
@@ -1359,6 +1423,13 @@ static void vacuum(void) {
}
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_UNIX && uwsgi_sock->name[0] != '@') {
struct stat st;
if (!stat(uwsgi_sock->name, &st)) {
if (st.st_ino != uwsgi_sock->inode) {
uwsgi_log("VACUUM WARNING: unix socket %s changed inode. Skip removal\n", uwsgi_sock->name);
goto next;
}
}
if (unlink(uwsgi_sock->name)) {
uwsgi_error("unlink()");
}
@@ -1366,6 +1437,7 @@ static void vacuum(void) {
uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
}
}
next:
uwsgi_sock = uwsgi_sock->next;
}
}
@@ -1423,14 +1495,17 @@ void signal_pidfile(int sig, char *filename) {
exit(0);
}
void fixup_argv_and_environ(int argc, char **argv, char **environ) {
static void fixup_argv_and_environ(int argc, char **argv, char **environ, char **envp) {
uwsgi.orig_argv = argv;
uwsgi.argv = argv;
uwsgi.argc = argc;
uwsgi.environ = environ;
// avoid messing with fake environ
if (envp && *environ != *envp) return;
#if defined(__linux__) || defined(__sun__)
int i;
@@ -1761,6 +1836,8 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_register_clock(&uwsgi_unix_clock);
uwsgi_set_clock("unix");
// fallback config
atexit(uwsgi_fallback_config);
// manage/flush logs
atexit(uwsgi_flush_logs);
// clear sockets, pidfiles...
@@ -1842,7 +1919,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
// ok we can now safely play with argv and environ
fixup_argv_and_environ(argc, argv, environ);
fixup_argv_and_environ(argc, argv, environ, envp);
if (gethostname(uwsgi.hostname, 255)) {
uwsgi_error("gethostname()");
@@ -1942,7 +2019,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
// setup master logging
if (uwsgi.log_master)
if (uwsgi.log_master && !uwsgi.daemonize2)
uwsgi_setup_log_master();
// setup offload engines
@@ -2104,6 +2181,12 @@ int main(int argc, char *argv[], char *envp[]) {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
// we could now patch the binary
if (uwsgi.privileged_binary_patch) {
uwsgi.argv[0] = uwsgi.privileged_binary_patch;
@@ -2156,6 +2239,23 @@ int uwsgi_start(void *v_argv) {
}
#endif
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.exec_in_jail) {
uwsgi_log("running \"%s\" (in-jail)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
}
uwsgi_foreach(usl, uwsgi.call_in_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
uwsgi_file_write_do(uwsgi.file_write_list);
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
@@ -2465,6 +2565,11 @@ int uwsgi_start(void *v_argv) {
else if (!uwsgi.sockets && ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.master_process) {
// here we will have a zombie... sorry
uwsgi_log("...you should enable the master process... really...\n");
if (uwsgi.force_gateway) {
struct uwsgi_gateway *ug = &ushared->gateways[0];
ug->loop(0, ug->data);
// when we are here the gateway is dead :(
}
exit(0);
}
@@ -2599,7 +2704,7 @@ unsafe:
}
}
// initialize locks and socket as soon as possibile, as the master could enqueue tasks
// initialize locks and socket as soon as possible, as the master could enqueue tasks
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
struct uwsgi_spooler *uspool = uwsgi.spoolers;
@@ -2820,7 +2925,7 @@ next2:
exit(1);
}
if (uwsgi.sockets->fd != 0) {
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
if (dup2(uwsgi.sockets->fd, 0) < 0) {
uwsgi_error("dup2()");
}
@@ -2858,6 +2963,34 @@ next2:
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->post_fork) {
uwsgi.gp[i]->post_fork();
}
}
if (uwsgi.worker_exec2) {
char *w_argv[2];
w_argv[0] = uwsgi.worker_exec2;
w_argv[1] = NULL;
uwsgi.sockets->arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.sockets->fd, F_SETFL, uwsgi.sockets->arg) < 0) {
uwsgi_error("fcntl()");
exit(1);
}
if (uwsgi.sockets->fd != 0 && !uwsgi.honour_stdin) {
if (dup2(uwsgi.sockets->fd, 0) < 0) {
uwsgi_error("dup2()");
}
}
execvp(w_argv[0], w_argv);
// never here
uwsgi_error("execvp()");
exit(1);
}
uwsgi_worker_run();
// never here
_exit(0);
@@ -3155,7 +3288,7 @@ void build_options() {
/*
this function build the help output from the uwsgi.options structure
this function builds the help output from the uwsgi.options structure
*/
void uwsgi_help(char *opt, char *val, void *none) {
@@ -3209,6 +3342,12 @@ void uwsgi_init_all_apps() {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_pre_app) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->init_apps) {
@@ -3268,6 +3407,11 @@ void uwsgi_init_all_apps() {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_post_app) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
}
@@ -3664,8 +3808,8 @@ void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
}
#endif
#ifdef __linux__
void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
uwsgi_build_unshare(value);
void uwsgi_opt_set_unshare(char *opt, char *value, void *mask) {
uwsgi_build_unshare(value, (int *) mask);
}
#endif
@@ -3710,6 +3854,10 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
if (uwsgi_load_plugin(-1, p, NULL)) {
build_options();
}
else if (!uwsgi_startswith(opt, "need-", 5)) {
uwsgi_log("unable to load plugin \"%s\"\n", p);
exit(1);
}
p = strtok(NULL, ",");
}
free(p);
@@ -4095,7 +4243,7 @@ void uwsgi_opt_cflags(char *opt, char *filename, void *foobar) {
}
char *uwsgi_get_cflags() {
size_t len = sizeof(UWSGI_CFLAGS);
size_t len = sizeof(UWSGI_CFLAGS) -1;
char *src = UWSGI_CFLAGS;
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
View File
+2
View File
@@ -9,6 +9,8 @@ end
major,minor = RUBY_VERSION.split('.')
if major.to_i >= 2 or (major.to_i == 1 and minor.to_i >= 9)
# a trick for installations with messy PATH
ENV['UWSGICONFIG_RUBYPATH'] = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
system("bash install.sh ruby2 #{Dir.pwd}/uwsgi.ruby")
else
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
-54
View File
@@ -1,54 +0,0 @@
import uwsgi
if uwsgi.loop == 'gevent':
import gevent
from threading import Thread
import time
from uwsgidecorators import postfork
def foobar():
while True:
time.sleep(3)
print "threee second elapsed in worker %d" % uwsgi.worker_id()
@postfork
def spawn_thread():
t = Thread(target=foobar)
t.daemon = True
t.start()
@postfork
def spawn_thread2():
t = Thread(target=foobar)
t.daemon = True
t.start()
def gl_func():
while True:
gevent.sleep(2)
print "i am a greenltet running in worker %d" % uwsgi.worker_id()
@postfork
def spawn_greenlet():
gevent.spawn(gl_func)
print uwsgi.version
print uwsgi.workers()
try:
uwsgi.cache_set('foo', "Hello World from cache")
except:
pass
def application(env, start_response):
print env['wsgi.input'].read()
if uwsgi.loop == 'gevent':
gevent.sleep()
start_response('200 OK', [('Content-Type', 'text/html')])
yield "foobar<br/>"
if uwsgi.loop == 'gevent':
gevent.sleep(3)
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
try:
yield uwsgi.cache_get('foo')
except:
pass
-31
View File
@@ -1,31 +0,0 @@
import uwsgi
import time
import rrdtool
# rrdtool create test.rrd --start 1270879004 -s 10 DS:requests:COUNTER:300:U:U RRA:AVERAGE:0.5:3:105120
s_freq = 10
# this task will be executed every s_freq seconds
def rrdtool_updater(sig, sec):
rrdtool.update('test.rrd', str(int(time.time()))+':'+str(uwsgi.total_requests()))
uwsgi.register_timer(0, s_freq, uwsgi.KIND_WORKER, rrdtool_updater)
def hello_world(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
return 'Hello world !'
def graph(env, start_response):
start_response('200 Ok', [('Content-type', 'image/png')])
now = int(time.time())
graph_range = (3600*24)
rrdtool.graph('uwsgi_graph.png', '--start', str(now - graph_range), '--end', str(now), 'DEF:urequests=test.rrd:requests:AVERAGE', 'LINE2:urequests#00FF00')
# send file to client
uwsgi.sendfile('uwsgi_graph.png')
uwsgi.applications = {'/': hello_world, '/graph':graph}
+6
View File
@@ -82,6 +82,12 @@ void linux_namespace_start(void *argv) {
usl = usl->next;
}
uwsgi_foreach(usl, uwsgi.call_post_jail) {
if (uwsgi_call_symbol(usl->value)) {
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
}
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
+12 -9
View File
@@ -201,7 +201,18 @@ edge:
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
wsgi_req->start_of_request = uwsgi_micros();
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
goto edge;
}
// in case of errors (or thundering herd, just rest it)
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
goto clear;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
@@ -209,14 +220,6 @@ edge:
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
if (uwsgi_sock->retry && uwsgi_sock->retry[wsgi_req->async_id]) {
goto edge;
}
goto clear;
}
// here we spawn an async {} block
CV *async_xs_call = newXS(NULL, XS_coroae_accept_request, "uwsgi::coroae");
+8 -8
View File
@@ -164,14 +164,6 @@ edge:
// mark core as used
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
free_req_queue;
@@ -183,6 +175,14 @@ edge:
goto clear;
}
wsgi_req->start_of_request = uwsgi_micros();
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
// enter harakiri mode
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
// hack to easily pass wsgi_req pointer to the greenlet
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
+299
View File
@@ -0,0 +1,299 @@
#include <uwsgi.h>
#include <api/glfs.h>
#ifdef UWSGI_MATHEVAL
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
#endif
extern struct uwsgi_server uwsgi;
/*
Author: Roberto De Ioris
--glusterfs-mount mountpoint=/foo,server=192.168.173.13:24007;192.168.173.17:0,volfile=foo.vol;volume=unbit001
*/
struct uwsgi_plugin glusterfs_plugin;
struct uwsgi_glusterfs {
int timeout;
struct uwsgi_string_list *mountpoints;
} uglusterfs;
static struct uwsgi_option uwsgi_glusterfs_options[] = {
{"glusterfs-mount", required_argument, 0, "virtual mount the specified glusterfs volume in a uri", uwsgi_opt_add_string_list, &uglusterfs.mountpoints, UWSGI_OPT_MIME},
{"glusterfs-timeout", required_argument, 0, "timeout for glusterfs async mode", uwsgi_opt_set_int, &uglusterfs.timeout, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static int uwsgi_glusterfs_read_sync(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
while(remains > 0) {
char buf[8192];
ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0);
if (rlen <= 0) return -1;
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) return -1;
remains -= rlen;
}
return 0;
}
/*
async read of a resource
the uwsgi_glusterfs_async_io structure is passed between threads
the callback simply signal the main core about the availability of data
*/
struct uwsgi_glusterfs_async_io {
int fd[2];
ssize_t rlen;
};
static void uwsgi_glusterfs_read_async_cb(glfs_fd_t *fd, ssize_t rlen, void *data) {
struct uwsgi_glusterfs_async_io *aio = (struct uwsgi_glusterfs_async_io *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("[glusterfs-cb] rlen = %d\n", rlen);
#endif
aio->rlen = rlen;
// signal the core
if (write(aio->fd[1], "\1", 1) <= 0) {
uwsgi_error("uwsgi_glusterfs_read_async_cb()/write()");
}
}
static int uwsgi_glusterfs_read_async(struct wsgi_request *wsgi_req, glfs_fd_t *fd, size_t remains) {
char buf[8192];
struct uwsgi_glusterfs_async_io aio;
int ret = -1;
if (pipe(aio.fd)) {
uwsgi_error("uwsgi_glusterfs_read_async()/pipe()");
return -1;
}
aio.rlen = -1;
while(remains > 0) {
// trigger an async read
if (glfs_read_async(fd, buf, 8192, 0, uwsgi_glusterfs_read_async_cb, &aio)) goto end;
// wait for the callback to be executed
if (uwsgi.wait_read_hook(aio.fd[0], uglusterfs.timeout) <= 0) goto end;
if (aio.rlen <= 0) goto end;
if (uwsgi_response_write_body_do(wsgi_req, buf, aio.rlen)) goto end;
remains -= aio.rlen;
}
ret = 0;
end:
close(aio.fd[0]);
close(aio.fd[1]);
return ret;
}
static int uwsgi_glusterfs_try(struct uwsgi_app *ua, char *node) {
int ret = -1;
char *colon = strchr(node, ':');
// unix socket
if (!colon) {
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "unix", node, 0)) {
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
return -1;
}
goto connect;
}
*colon = 0;
if (glfs_set_volfile_server((glfs_t *)ua->interpreter, "tcp", node, atoi(colon+1))) {
uwsgi_error("[glusterfs] glfs_set_volfile_server()");
return -1;
}
connect:
ret = glfs_init((glfs_t *)ua->interpreter);
if (ret) { uwsgi_error("[glusterfs] glfs_init()"); }
else {
if (colon) *colon = ':';
uwsgi_log("[glusterfs] worker %d connected to %s\n", uwsgi.mywid, node);
}
return ret;
}
static void uwsgi_glusterfs_connect_do(struct uwsgi_app *ua) {
char *servers = uwsgi_str(ua->callable);
char *p = strtok(servers, ";");
while(p) {
uwsgi_log("[glusterfs] try connect to %s for mountpoint %.*s on worker %d ...\n", p, ua->mountpoint_len, ua->mountpoint, uwsgi.mywid);
if (uwsgi_glusterfs_try(ua, p)) {
goto end;
}
p = strtok(NULL, ";");
}
end:
free(servers);
}
static void uwsgi_glusterfs_connect() {
int i;
// search for all of the glusterfs apps and connect to the server-based ones
for (i = 0; i < uwsgi_apps_cnt; i++) {
if (uwsgi_apps[i].modifier1 != glusterfs_plugin.modifier1) continue;
if (!uwsgi_apps[i].callable) {
if (glfs_init((glfs_t *)uwsgi_apps[i].interpreter)) {
uwsgi_error("[glusterfs] glfs_init()");
exit(1);
}
uwsgi_log("[glusterfs] worker %d connected using volfile\n", uwsgi.mywid);
continue;
}
uwsgi_glusterfs_connect_do(&uwsgi_apps[i]);
}
}
static void uwsgi_glusterfs_add_mountpoint(char *arg, size_t arg_len) {
char *ugfs_mountpoint = NULL;
char *ugfs_server = NULL;
char *ugfs_volfile = NULL;
char *ugfs_volume = NULL;
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
"mountpoint", &ugfs_mountpoint,
"server", &ugfs_server,
"servers", &ugfs_server,
"volfile", &ugfs_volfile,
"volume", &ugfs_volume,
NULL)) {
uwsgi_log("unable to parse glusterfs mountpoint definition\n");
exit(1);
}
if (!ugfs_mountpoint || (!ugfs_server && !ugfs_volfile) || !ugfs_volume) {
uwsgi_log("[glusterfs] mount requires a mountpoint, a volume and at least one server or volfile\n");
exit(1);
}
int id = uwsgi_apps_cnt;
time_t now = uwsgi_now();
uwsgi_log("[glusterfs] mounting %s ...\n", ugfs_mountpoint);
// this should fail only if memory is not available
glfs_t *volume = glfs_new(ugfs_volume);
if (!volume) {
uwsgi_error("unable to initialize glusterfs mountpoint: glfs_new()");
exit(1);
}
if (ugfs_volfile) {
if (glfs_set_volfile(volume, ugfs_volfile)) {
uwsgi_error("unable to set glusterfs volfile: glfs_set_volfile\n");
exit(1);
}
}
/*
here we pass ugfs_server as the callable field.
After fork() if this field is defined we will start trying to connect to each one of the configuratio nodes
This is required to have fallback management
*/
struct uwsgi_app *ua = uwsgi_add_app(id, glusterfs_plugin.modifier1, ugfs_mountpoint, strlen(ugfs_mountpoint), volume, ugfs_server);
if (!ua) {
uwsgi_log("[glusterfs] unable to mount %s\n", ugfs_mountpoint);
exit(1);
}
ua->started_at = now;
ua->startup_time = uwsgi_now() - now;
uwsgi_log("GlusterFS app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, ugfs_mountpoint, (int) ua->startup_time, volume);
}
// we translate the string list to an app representation
// this happens before fork() if not in lazy/lazy-apps mode
static void uwsgi_glusterfs_setup() {
if (!uglusterfs.timeout) {
uglusterfs.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
struct uwsgi_string_list *usl = uglusterfs.mountpoints;
while(usl) {
uwsgi_glusterfs_add_mountpoint(usl->value, usl->len);
usl = usl->next;
}
}
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) {
char filename[PATH_MAX+1];
/* Standard GlusterFS request */
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Empty GlusterFS request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
// blocks empty paths
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1);
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) {
wsgi_req->app_id = uwsgi.default_app;
}
}
if (wsgi_req->app_id == -1) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
filename[wsgi_req->path_info_len] = 0;
glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY);
if (!fd) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct stat st;
if (glfs_fstat(fd, &st)) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
size_t mime_type_len = 0;
char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len);
if (mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
}
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end;
// skip body on HEAD
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
size_t remains = st.st_size;
if (uwsgi.async > 1) {
if (uwsgi_glusterfs_read_async(wsgi_req, fd, remains)) goto end;
}
else {
if (uwsgi_glusterfs_read_sync(wsgi_req, fd, remains)) goto end;
}
}
end:
glfs_close(fd);
return UWSGI_OK;
}
struct uwsgi_plugin glusterfs_plugin = {
.name = "glusterfs",
.modifier1 = 27,
.options = uwsgi_glusterfs_options,
.post_fork = uwsgi_glusterfs_setup,
.fixup = uwsgi_glusterfs_connect,
.request = uwsgi_glusterfs_request,
.after_request = log_request,
};
+7
View File
@@ -0,0 +1,7 @@
import os
NAME='glusterfs'
CFLAGS = os.popen('pkg-config --cflags glusterfs-api').read().rstrip().split()
LDFLAGS = []
LIBS = os.popen('pkg-config --libs glusterfs-api').read().rstrip().split()
GCC_LIST = ['glusterfs']
+27 -4
View File
@@ -10,6 +10,7 @@ struct uwsgi_http uhttp;
struct uwsgi_option http_options[] = {
{"http", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
{"httprouter", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0},
#ifdef UWSGI_SSL
{"https", required_argument, 0, "add an https router/server on the specified address with specified certificate and key", uwsgi_opt_https, &uhttp, 0},
{"https2", required_argument, 0, "add an https/spdy router/server using keyval options", uwsgi_opt_https2, &uhttp, 0},
@@ -207,8 +208,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
while (ptr < watermark) {
if (*ptr == '?' && !query_string) {
// PATH_INFO must be url-decoded !!!
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
if (!hr->path_info) {
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
}
else {
size_t new_path_info = ptr - base;
if (new_path_info > hr->path_info_len) {
char *tmp_buf = realloc(hr->path_info, new_path_info);
if (!tmp_buf) return -1;
hr->path_info = tmp_buf;
}
hr->path_info_len = new_path_info;
}
http_url_decode(base, &hr->path_info_len, hr->path_info);
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
query_string = ptr + 1;
@@ -219,8 +231,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
if (uwsgi_buffer_append_keyval(out, "REQUEST_URI", 11, base, ptr - base)) return -1;
if (!query_string) {
// PATH_INFO must be url-decoded !!!
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
if (!hr->path_info) {
hr->path_info_len = ptr - base;
hr->path_info = uwsgi_malloc(hr->path_info_len);
}
else {
size_t new_path_info = ptr - base;
if (new_path_info > hr->path_info_len) {
char *tmp_buf = realloc(hr->path_info, new_path_info);
if (!tmp_buf) return -1;
hr->path_info = tmp_buf;
}
hr->path_info_len = new_path_info;
}
http_url_decode(base, &hr->path_info_len, hr->path_info);
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, hr->path_info, hr->path_info_len)) return -1;
if (uwsgi_buffer_append_keyval(out, "QUERY_STRING", 12, "", 0)) return -1;
+2
View File
@@ -28,6 +28,7 @@ struct uwsgi_jvm {
jclass list_class;
jclass set_class;
jclass iterator_class;
jclass bool_class;
jclass runtime_exception;
jclass io_exception;
@@ -101,6 +102,7 @@ int uwsgi_jvm_call_bool(jobject, jmethodID, ...);
int uwsgi_jvm_consume_input_stream(struct wsgi_request *, size_t, jobject);
jobject uwsgi_jvm_num(long);
jobject uwsgi_jvm_request_body_input_stream(void);
jobject uwsgi_jvm_bool(long);
size_t uwsgi_jvm_array_len(jobject);
jobject uwsgi_jvm_array_get(jobject, long);
+19 -3
View File
@@ -896,6 +896,19 @@ jobject uwsgi_jvm_num(long num) {
return o;
}
jobject uwsgi_jvm_bool(long b) {
static jmethodID mid = 0;
if (!mid) {
mid = uwsgi_jvm_get_method_id(ujvm.int_class, "<init>", "(I)V");
if (!mid) return NULL;
}
jobject o = (*ujvm_env)->NewObject(ujvm_env, ujvm.bool_class, mid, b);
if (uwsgi_jvm_exception()) {
return NULL;
}
return o;
}
jobject uwsgi_jvm_str(char *str, size_t len) {
jobject new_str;
if (len > 0) {
@@ -1063,6 +1076,9 @@ static void uwsgi_jvm_create(void) {
ujvm.int_class = uwsgi_jvm_class("java/lang/Integer");
if (!ujvm.int_class) exit(1);
ujvm.bool_class = uwsgi_jvm_class("java/lang/Boolean");
if (!ujvm.bool_class) exit(1);
ujvm.long_class = uwsgi_jvm_class("java/lang/Long");
if (!ujvm.long_class) exit(1);
@@ -1116,7 +1132,7 @@ static void uwsgi_jvm_create(void) {
jobject j_opt_value = uwsgi_jvm_hashmap_get(opt_hm, (jobject) j_opt_key);
if (uwsgi_jvm_object_is_instance(j_opt_value, ujvm.list_class)) {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(j_opt_value, (jobject) 1);
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_list_add(j_opt_value, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
@@ -1126,7 +1142,7 @@ static void uwsgi_jvm_create(void) {
jobject ll = uwsgi_jvm_list();
uwsgi_jvm_list_add(ll, j_opt_value);
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_list_add(ll, (jobject) 1);
uwsgi_jvm_list_add(ll, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_list_add(ll, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
@@ -1136,7 +1152,7 @@ static void uwsgi_jvm_create(void) {
}
else {
if (uwsgi.exported_opts[j]->value == NULL) {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, (jobject) 1);
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_bool(JNI_TRUE));
}
else {
uwsgi_jvm_hashmap_put(opt_hm, j_opt_key, uwsgi_jvm_str(uwsgi.exported_opts[j]->value, 0));
+1 -1
View File
@@ -77,7 +77,7 @@ struct uwsgi_mono {
struct uwsgi_option uwsgi_mono_options[] = {
{"mono-app", required_argument, 0, "load a Mono asp.net app from the specified directory", uwsgi_opt_add_string_list, &umono.app, 0},
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default, run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
{"mono-gc-freq", required_argument, 0, "run the Mono GC every <n> requests (default: run after every request)", uwsgi_opt_set_64bit, &umono.gc_freq, 0},
{"mono-key", required_argument, 0, "select the ApplicationHost based on the specified CGI var", uwsgi_opt_add_string_list, &umono.key, 0},
{"mono-version", required_argument, 0, "set the Mono jit version", uwsgi_opt_set_str, &umono.version, 0},
{"mono-config", required_argument, 0, "set the Mono config file", uwsgi_opt_set_str, &umono.config, 0},
+5 -1
View File
@@ -1,5 +1,5 @@
#undef __USE_GNU
#include "../../uwsgi.h"
#include <uwsgi.h>
#ifdef __APPLE__
#define HAS_BOOL 1
@@ -50,6 +50,9 @@ struct uwsgi_perl {
SV *atexit;
int loaded;
struct uwsgi_string_list *exec;
struct uwsgi_string_list *exec_post_fork;
};
void init_perl_embedded_module(void);
@@ -66,3 +69,4 @@ int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
PerlInterpreter *uwsgi_perl_new_interpreter(void);
int uwsgi_perl_mule(char *);
void uwsgi_perl_run_hook(SV *);
void uwsgi_perl_exec(char *);
+17
View File
@@ -483,6 +483,16 @@ void uwsgi_psgi_app() {
//load app in the main interpreter list
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
}
// create a perl environment (if needed)
else if (uperl.exec) {
PERL_SET_CONTEXT(uperl.main[0]);
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec) {
uwsgi_perl_exec(usl->value);
}
}
@@ -502,3 +512,10 @@ int uwsgi_perl_mule(char *opt) {
}
void uwsgi_perl_exec(char *filename) {
size_t size = 0;
char *buf = uwsgi_open_and_read(filename, &size, 1, NULL);
perl_eval_pv(buf, 0);
free(buf);
}
+7
View File
@@ -21,6 +21,8 @@ struct uwsgi_option uwsgi_perl_options[] = {
#endif
{"perl-args", required_argument, 0, "add items (space separated) to @ARGV", uwsgi_opt_set_str, &uperl.argv_items, 0},
{"perl-arg", required_argument, 0, "add an item to @ARGV", uwsgi_opt_add_string_list, &uperl.argv_item, 0},
{"perl-exec", required_argument, 0, "exec the specified perl file before fork()", uwsgi_opt_add_string_list, &uperl.exec, 0},
{"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -588,6 +590,11 @@ void uwsgi_perl_post_fork() {
SvREADONLY_on(GvSV(tmpgv));
}
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uperl.exec_post_fork) {
uwsgi_perl_exec(usl->value);
}
if (uperl.postfork) {
uwsgi_perl_run_hook(uperl.postfork);
}
+308
View File
@@ -0,0 +1,308 @@
#include <uwsgi.h>
#ifdef __linux__
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
#endif
#ifndef __FreeBSD__
#include <utmp.h>
#endif
extern struct uwsgi_server uwsgi;
struct uwsgi_pty_client {
int fd;
struct uwsgi_pty_client *prev;
struct uwsgi_pty_client *next;
};
static struct uwsgi_pty {
char *addr;
char *remote;
int queue;
int server_fd;
int master_fd;
int slave_fd;
int log;
int original_log;
int input;
int original_input;
int no_isig;
char *command;
pid_t command_pid;
struct uwsgi_pty_client *head;
struct uwsgi_pty_client *tail;
} upty;
static struct uwsgi_pty_client *uwsgi_pty_client_new(int fd) {
struct uwsgi_pty_client *upc = uwsgi_calloc(sizeof(struct uwsgi_pty_client));
upc->fd = fd;
if (upty.tail) {
upc->prev = upty.tail;
upty.tail->next = upc;
}
upty.tail = upc;
if (!upty.head) upty.head = upc;
return upc;
}
static void uwsgi_pty_client_remove(struct uwsgi_pty_client *upc) {
struct uwsgi_pty_client *prev = upc->prev;
struct uwsgi_pty_client *next = upc->next;
if (prev) {
prev->next = next;
}
if (next) {
next->prev = prev;
}
if (upc == upty.head) {
upty.head = next;
}
if (upc == upty.tail) {
upty.tail = prev;
}
close(upc->fd);
free(upc);
}
static struct uwsgi_option uwsgi_pty_options[] = {
{"pty-socket", required_argument, 0, "bind the pty server on the specified address", uwsgi_opt_set_str, &upty.addr, 0},
{"pty-log", no_argument, 0, "send stdout/stderr to the log engine too", uwsgi_opt_true, &upty.log, 0},
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
{"pty-exec", no_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void uwsgi_pty_setterm(int fd) {
struct termios tio;
tcgetattr(fd, &tio);
tio.c_iflag |= IGNPAR;
tio.c_iflag &= ~(ISTRIP | IMAXBEL | BRKINT | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
#ifdef IUCLC
tio.c_iflag &= ~IUCLC;
#endif
tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
if (upty.no_isig) {
tio.c_lflag &= ~(ISIG);
}
#ifdef IEXTEN
tio.c_lflag &= ~IEXTEN;
#endif
tio.c_oflag &= ~OPOST;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
#ifdef B38400
cfsetispeed(&tio, B38400);
cfsetospeed(&tio, B38400);
#endif
tcsetattr(fd, TCSANOW, &tio);
}
static void *uwsgi_pty_loop(void *arg) {
/*
if slave is ready there is something to send to the clients (and logs)
if client is ready we have something to write to the master pty
*/
for(;;) {
char buf[8192];
int interesting_fd = -1;
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
if (ret == 0) continue;
if (ret < 0) continue;
if (upty.input && interesting_fd == upty.original_input) {
ssize_t rlen = read(upty.original_input, buf, 8192);
if (rlen <= 0) continue;
if (write(upty.master_fd, buf, rlen) != rlen) {
// what to do ?
}
continue;
}
if (interesting_fd == upty.master_fd) {
ssize_t rlen = read(upty.master_fd, buf, 8192);
if (rlen == 0) exit(1);
if (rlen < 0) {
uwsgi_error("uwsgi_pty_loop()/read()");
}
if (upty.log && upty.original_log >= 0) {
if (write(upty.original_log, buf, rlen) != rlen) {
// what to do ?
}
}
struct uwsgi_pty_client *upc = upty.head;
while(upc) {
if (write(upc->fd, buf, rlen) != rlen) {
struct uwsgi_pty_client *tmp_upc = upc->next;
uwsgi_pty_client_remove(upc);
upc = tmp_upc;
continue;
}
upc = upc->next;
}
continue;
}
if (interesting_fd == upty.server_fd) {
struct sockaddr_un client_src;
memset(&client_src, 0, sizeof(struct sockaddr_un));
socklen_t client_src_len = 0;
int client_fd = accept(upty.server_fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
continue;
}
struct uwsgi_pty_client *upc = uwsgi_pty_client_new(client_fd);
event_queue_add_fd_read(upty.queue, upc->fd);
continue;
}
struct uwsgi_pty_client *upc = upty.head;
while(upc) {
if (interesting_fd == upc->fd) {
ssize_t rlen = read(upc->fd, buf, 8192);
if (rlen <= 0) {
uwsgi_pty_client_remove(upc);
break;
}
if (write(upty.master_fd, buf, rlen) != rlen) {
}
break;
}
upc = upc->next;
}
continue;
}
}
static void uwsgi_pty_init() {
if (!upty.addr) return;
if (!uwsgi.master_process) return;
if (uwsgi.mywid > 1) return;
char *tcp_port = strrchr(upty.addr, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
upty.server_fd = bind_to_tcp(upty.addr, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
upty.server_fd = bind_to_unix(upty.addr, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
if (upty.log) {
upty.original_log = dup(1);
}
if (upty.input) {
upty.original_input = dup(0);
}
if (openpty(&upty.master_fd, &upty.slave_fd, NULL, NULL, NULL)) {
uwsgi_error("uwsgi_pty_init()/openpty()");
exit(1);
}
uwsgi_log("pty server %s (fd: %d) enabled on %s master: %d slave: %d\n", upty.addr, upty.server_fd, ttyname(upty.slave_fd), upty.master_fd, upty.slave_fd);
upty.queue = event_queue_init();
event_queue_add_fd_read(upty.queue, upty.master_fd);
event_queue_add_fd_read(upty.queue, upty.server_fd);
if (upty.input) {
event_queue_add_fd_read(upty.queue, upty.original_input);
uwsgi_pty_setterm(upty.original_input);
}
login_tty(upty.slave_fd);
if (upty.command) {
upty.command_pid = uwsgi_run_command(upty.command, NULL, -1);
}
pthread_t t;
pthread_create(&t, NULL, uwsgi_pty_loop, NULL);
}
static int uwsgi_pty_client() {
if (!upty.remote) return 0;
uwsgi_log("[pty] connecting to %s ...\n", upty.remote);
// save current terminal settings
if (!tcgetattr(0, &uwsgi.termios)) {
uwsgi.restore_tc = 1;
}
upty.server_fd = uwsgi_connect(upty.remote, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (upty.server_fd < 0) {
uwsgi_error("uwsgi_pty_client()/connect()");
exit(1);
}
uwsgi_socket_nb(upty.server_fd);
uwsgi_socket_nb(0);
uwsgi_log("[pty] connected.\n");
uwsgi_pty_setterm(0);
upty.queue = event_queue_init();
event_queue_add_fd_read(upty.queue, upty.server_fd);
event_queue_add_fd_read(upty.queue, 0);
for(;;) {
char buf[8192];
int interesting_fd = -1;
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
if (ret <= 0) break;
if (interesting_fd == 0) {
ssize_t rlen = read(0, buf, 8192);
if (rlen <= 0) break;
if (write(upty.server_fd, buf, rlen) != rlen) break;
continue;
}
if (interesting_fd == upty.server_fd) {
ssize_t rlen = read(upty.server_fd, buf, 8192);
if (rlen <= 0) break;
if (write(0, buf, rlen) != rlen) break;
continue;
}
}
exit(0);
// never here
return 0;
}
struct uwsgi_plugin pty_plugin = {
.name = "pty",
.options = uwsgi_pty_options,
.init = uwsgi_pty_client,
.post_fork = uwsgi_pty_init,
};
+12
View File
@@ -0,0 +1,12 @@
NAME='pty'
import os
uwsgi_os = os.uname()[0]
CFLAGS = []
LDFLAGS = []
if uwsgi_os in ('Linux', 'FreeBSD'):
LIBS = ['-lutil']
else:
LIBS = []
GCC_LIST = ['pty']
+52 -38
View File
@@ -25,11 +25,11 @@ struct uwsgi_pypy {
} upypy;
// the functions exposed by libpypy-c
char *(*rpython_startup_code)(void);
int (*pypy_setup_home)(char *, int);
int (*pypy_execute_source)(char *);
void (*pypy_thread_attach)(void);
void (*pypy_init_threads)(void);
char *(*u_rpython_startup_code)(void);
int (*u_pypy_setup_home)(char *, int);
int (*u_pypy_execute_source)(char *);
void (*u_pypy_thread_attach)(void);
void (*u_pypy_init_threads)(void);
// the hooks you can override with pypy
void (*uwsgi_pypy_hook_loader)(char *);
@@ -52,12 +52,18 @@ static int uwsgi_pypy_init() {
exit(1);
}
if (upypy.lib) {
if (dlsym(RTLD_DEFAULT, "rpython_startup_code")) {
uwsgi_log("PyPy runtime detected, skipping libpypy-c loading\n");
goto ready;
}
else if (upypy.lib) {
upypy.handler = dlopen(upypy.lib, RTLD_NOW | RTLD_GLOBAL);
}
else {
if (upypy.home) {
#ifdef __APPLE__
#ifdef __CYGWIN__
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
#elif defined(__APPLE__)
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
#else
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
@@ -69,7 +75,9 @@ static int uwsgi_pypy_init() {
}
// fallback to standard library search path
if (!upypy.handler) {
#ifdef __APPLE__
#ifdef __CYGWIN__
upypy.handler = dlopen("libpypy-c.dll", RTLD_NOW | RTLD_GLOBAL);
#elif defined(__APPLE__)
upypy.handler = dlopen("libpypy-c.dylib", RTLD_NOW | RTLD_GLOBAL);
#else
upypy.handler = dlopen("libpypy-c.so", RTLD_NOW | RTLD_GLOBAL);
@@ -82,35 +90,24 @@ static int uwsgi_pypy_init() {
exit(1);
}
rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!rpython_startup_code) {
u_rpython_startup_code = dlsym(upypy.handler, "rpython_startup_code");
if (!u_rpython_startup_code) {
uwsgi_log("unable to find rpython_startup_code() symbol\n");
exit(1);
}
pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!pypy_setup_home) {
u_pypy_setup_home = dlsym(upypy.handler, "pypy_setup_home");
if (!u_pypy_setup_home) {
uwsgi_log("unable to find pypy_setup_home() symbol\n");
exit(1);
}
pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!pypy_init_threads) {
u_pypy_init_threads = dlsym(upypy.handler, "pypy_init_threads");
if (!u_pypy_init_threads) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_init_threads, multithreading will not work !!!\n");
}
rpython_startup_code();
u_rpython_startup_code();
if (!upypy.home) {
upypy.home = getenv("PYPY_HOME");
@@ -120,11 +117,11 @@ static int uwsgi_pypy_init() {
}
}
if (pypy_setup_home(upypy.home, 0)) {
if (u_pypy_setup_home(upypy.home, 0)) {
char *retry = uwsgi_concat2(upypy.home, "/lib_pypy");
if (uwsgi_is_dir(retry)) {
// this time we use debug
if (!pypy_setup_home(retry, 1)) {
if (!u_pypy_setup_home(retry, 1)) {
free(retry);
goto ready;
}
@@ -134,12 +131,29 @@ static int uwsgi_pypy_init() {
}
ready:
u_pypy_execute_source = dlsym(upypy.handler, "pypy_execute_source");
if (!u_pypy_execute_source) {
uwsgi_log("unable to find pypy_execute_source() symbol\n");
exit(1);
}
u_pypy_thread_attach = dlsym(upypy.handler, "pypy_thread_attach");
if (!u_pypy_thread_attach) {
uwsgi_log("!!! WARNING your libpypy-c does not export pypy_thread_attach, multithreading will not work !!!\n");
}
if (upypy.setup) {
buffer = uwsgi_open_and_read(upypy.setup, &rlen, 1, NULL);
}
else {
char *start = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_start");
if (!start) {
start = dlsym(RTLD_DEFAULT, "_uwsgi_pypy_setup_start");
}
char *end = dlsym(RTLD_DEFAULT, "uwsgi_pypy_setup_end");
if (!end) {
end = dlsym(RTLD_DEFAULT, "_uwsgi_pypy_setup_end");
}
if (start && end) {
buffer = uwsgi_concat2n(start, end-start, "", 0);
}
@@ -149,7 +163,7 @@ ready:
uwsgi_log("you have to load a pypy setup file with --pypy-setup\n");
exit(1);
}
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -170,7 +184,7 @@ static void uwsgi_pypy_preinit_apps() {
struct uwsgi_string_list *usl = upypy.eval;
while(usl) {
if (pypy_execute_source(usl->value)) {
if (u_pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
@@ -180,7 +194,7 @@ static void uwsgi_pypy_preinit_apps() {
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -243,14 +257,14 @@ static struct uwsgi_option uwsgi_pypy_options[] = {
};
static void uwsgi_pypy_enable_threads() {
if (pypy_init_threads) {
pypy_init_threads();
if (u_pypy_init_threads) {
u_pypy_init_threads();
}
}
static void uwsgi_pypy_init_thread() {
if (pypy_thread_attach) {
pypy_thread_attach();
if (u_pypy_thread_attach) {
u_pypy_thread_attach();
}
}
@@ -274,7 +288,7 @@ static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t a
static void uwsgi_pypy_post_fork() {
struct uwsgi_string_list *usl = upypy.eval_post_fork;
while(usl) {
if (pypy_execute_source(usl->value)) {
if (u_pypy_execute_source(usl->value)) {
exit(1);
}
usl = usl->next;
@@ -283,7 +297,7 @@ static void uwsgi_pypy_post_fork() {
while(usl) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(usl->value, &rlen, 1, NULL);
if (pypy_execute_source(buffer)) {
if (u_pypy_execute_source(buffer)) {
exit(1);
}
free(buffer);
@@ -306,7 +320,7 @@ static int uwsgi_pypy_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
size_t rlen = 0;
char *buffer = uwsgi_open_and_read(opt, &rlen, 1, NULL);
pypy_execute_source(buffer);
u_pypy_execute_source(buffer);
free(buffer);
return 1;
}
+38 -4
View File
@@ -125,6 +125,20 @@ struct uwsgi_buffer {
...;
};
struct uwsgi_lock_item {
...;
};
struct uwsgi_cache {
struct uwsgi_lock_item *lock;
...;
};
struct uwsgi_cache_item {
uint64_t keysize;
...;
};
struct uwsgi_server {
char hostname[];
int mywid;
@@ -184,6 +198,11 @@ int uwsgi_cache_magic_set(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t
int uwsgi_cache_magic_del(char *, uint16_t, char *);
int uwsgi_cache_magic_exists(char *, uint16_t, char *);
int uwsgi_cache_magic_clear(char *);
struct uwsgi_cache *uwsgi_cache_by_name(char *);
void uwsgi_cache_rlock(struct uwsgi_cache *);
void uwsgi_cache_rwunlock(struct uwsgi_cache *);
char *uwsgi_cache_item_key(struct uwsgi_cache_item *);
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *, uint64_t *, struct uwsgi_cache_item **);
int uwsgi_add_file_monitor(uint8_t, char *);
int uwsgi_add_timer(uint8_t, int);
@@ -244,8 +263,9 @@ it sucks, i will fix it in the near future...
"""
wsgi_application = None
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
# fix argv if needed
if len(sys.argv) == 0:
sys.argv.insert(0, ffi.string(lib.uwsgi_binary_path()))
"""
@@ -332,7 +352,7 @@ class WSGIinput(object):
self.wsgi_req = wsgi_req
def read(self, size=0):
rlen = ffi.new('int64_t*')
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
@@ -473,7 +493,6 @@ def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
rpc_func = uwsgi_pypy_RPC(func)
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
uwsgi_gc.append(cb)
print lib.pypy_plugin
if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0:
raise Exception("unable to register rpc func %s" % name)
uwsgi.register_rpc = uwsgi_pypy_uwsgi_register_rpc
@@ -541,6 +560,21 @@ def uwsgi_pypy_uwsgi_cache_del(key, cache=ffi.NULL):
raise Exception('unable to delete item from the cache')
uwsgi.cache_del = uwsgi_pypy_uwsgi_cache_del
def uwsgi_pypy_uwsgi_cache_keys(cache=ffi.NULL):
uc = lib.uwsgi_cache_by_name(cache)
if uc == ffi.NULL:
raise Exception('no local uWSGI cache available')
l = []
lib.uwsgi_cache_rlock(uc)
pos = ffi.new('uint64_t *')
uci = ffi.new('struct uwsgi_cache_item **')
while True:
uci[0] = lib.uwsgi_cache_keys(uc, pos, uci)
if uci[0] == ffi.NULL: break
l.append(ffi.string(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize))
lib.uwsgi_cache_rwunlock(uc)
return l
uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys
def uwsgi_pypy_uwsgi_add_timer(signum, secs):
if lib.uwsgi_add_timer(signum, secs) < 0:
+1 -1
View File
@@ -2,7 +2,7 @@ NAME='pypy'
LDFLAGS = []
LIBS = []
GCC_LIST = ['pypy_plugin']
BINARY_LIST = [ ('uwsgi_pypy_setup','pypy_setup.py')]
BINARY_LIST = [ ('_uwsgi_pypy_setup','pypy_setup.py')]
CFLAGS = []
try:
import __pypy__
+9
View File
@@ -13,6 +13,15 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
}
#endif
#ifdef PYTHREE
#undef PyString_AsString
static char *PyString_AsString(PyObject *o) {
PyObject *zero = PyUnicode_AsLatin1String(o);
if (!zero) return "";
return PyBytes_AsString(zero);
}
#endif
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
static uint64_t last_ts = 0;
+46 -1
View File
@@ -607,6 +607,52 @@ PyObject *uwsgi_file_loader(void *arg1) {
}
PyObject *uwsgi_pecan_loader(void *arg1) {
char *pecan = (char *) arg1;
PyObject *pecan_module, *pecan_dict, *pecan_deploy;
PyObject *pecan_arg, *pecan_app;
uwsgi_log( "Loading pecan environment: %s\n", pecan);
pecan_module = PyImport_ImportModule("pecan.deploy");
if (!pecan_module) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_dict = PyModule_GetDict(pecan_module);
if (!pecan_dict) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_deploy = PyDict_GetItemString(pecan_dict, "deploy");
if (!pecan_deploy) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_arg = PyTuple_New(1);
if (!pecan_arg) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
if (PyTuple_SetItem(pecan_arg, 0, UWSGI_PYFROMSTRING(pecan))) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
pecan_app = PyEval_CallObject(pecan_deploy, pecan_arg);
if (!pecan_app) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
return pecan_app;
}
PyObject *uwsgi_paste_loader(void *arg1) {
char *paste = (char *) arg1;
@@ -668,7 +714,6 @@ PyObject *uwsgi_paste_loader(void *arg1) {
exit(UWSGI_FAILED_APP_CODE);
}
return paste_app;
}
+7
View File
@@ -121,6 +121,9 @@ struct uwsgi_option uwsgi_python_options[] = {
{"pyargv", required_argument, 0, "manually set sys.argv", uwsgi_opt_set_str, &up.argv, 0},
{"optimize", required_argument, 'O', "set python optimization level", uwsgi_opt_set_int, &up.optimize, 0},
{"pecan", required_argument, 0, "load a pecan config file", uwsgi_opt_set_str, &up.pecan, 0},
{"paste", required_argument, 0, "load a paste.deploy config file", uwsgi_opt_set_str, &up.paste, 0},
{"paste-logger", no_argument, 0, "enable paste fileConfig logger", uwsgi_opt_true, &up.paste_logger, 0},
@@ -1058,6 +1061,7 @@ void uwsgi_python_init_apps() {
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
up.loaders[LOADER_UWSGI] = uwsgi_uwsgi_loader;
up.loaders[LOADER_FILE] = uwsgi_file_loader;
up.loaders[LOADER_PECAN] = uwsgi_pecan_loader;
up.loaders[LOADER_PASTE] = uwsgi_paste_loader;
up.loaders[LOADER_EVAL] = uwsgi_eval_loader;
up.loaders[LOADER_MOUNT] = uwsgi_mount_loader;
@@ -1123,6 +1127,9 @@ next:
if (up.file_config != NULL) {
init_uwsgi_app(LOADER_FILE, up.file_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.pecan != NULL) {
init_uwsgi_app(LOADER_PECAN, up.pecan, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
if (up.paste != NULL) {
init_uwsgi_app(LOADER_PASTE, up.paste, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
+58
View File
@@ -27,9 +27,20 @@ char *uwsgi_python_get_exception_type(PyObject *exc) {
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
if (module_name) {
#ifdef PYTHREE
char *mod_name = NULL;
PyObject *zero = PyUnicode_AsUTF8String(module_name);
if (zero) {
mod_name = PyString_AsString(zero);
}
#else
char *mod_name = PyString_AsString(module_name);
#endif
if (mod_name && strcmp(mod_name, "exceptions") ) {
char *ret = uwsgi_concat3(mod_name, ".", class_name);
#ifdef PYTHREE
Py_DECREF(zero);
#endif
Py_DECREF(module_name);
return ret;
}
@@ -81,6 +92,38 @@ struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
int64_t line_no = PyInt_AsLong(tb_lineno);
#ifdef PYTHREE
PyObject *zero = PyUnicode_AsUTF8String(tb_filename);
if (!zero) goto end0;
// filename
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
// lineno
if (uwsgi_buffer_append_valnum(ub, line_no)) goto end0;
zero = PyUnicode_AsUTF8String(tb_function);
if (!zero) goto end0;
// function
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
zero = PyUnicode_AsUTF8String(tb_text);
if (!zero) goto end0;
// text
if (uwsgi_buffer_u16le(ub, PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
if (uwsgi_buffer_append(ub, PyString_AsString(zero), PyString_Size(zero))) { Py_DECREF(zero); goto end0; }
Py_DECREF(zero);
#else
// filename
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_filename))) goto end0;
if (uwsgi_buffer_append(ub, PyString_AsString(tb_filename), PyString_Size(tb_filename))) goto end0;
@@ -95,6 +138,7 @@ struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *wsgi_req) {
// text
if (uwsgi_buffer_u16le(ub, PyString_Size(tb_text))) goto end0;
if (uwsgi_buffer_append(ub, PyString_AsString(tb_text), PyString_Size(tb_text))) goto end0;
#endif
// custom (unused)
if (uwsgi_buffer_u16le(ub, 0)) goto end0;
@@ -152,15 +196,29 @@ struct uwsgi_buffer *uwsgi_python_exception_msg(struct wsgi_request *wsgi_req) {
// value could be NULL ?
if (!value) goto end;
#ifdef PYTHREE
char *msg = NULL;
PyObject *zero = PyUnicode_AsUTF8String( PyObject_Str(value) );
if (zero) {
msg = PyString_AsString( zero );
}
#else
char *msg = PyString_AsString( PyObject_Str(value) );
#endif
if (msg) {
size_t msg_len = strlen(msg);
ub = uwsgi_buffer_new(msg_len);
if (uwsgi_buffer_append(ub, msg, msg_len)) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
uwsgi_buffer_destroy(ub);
ub = NULL;
goto end;
}
#ifdef PYTHREE
Py_DECREF(zero);
#endif
}
end:
PyErr_Restore(type, value, traceback);
+35
View File
@@ -1805,6 +1805,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
if (PyString_Check(pybody)) {
body = PyString_AsString(pybody);
body_len = PyString_Size(pybody);
Py_INCREF(pybody);
uwsgi_py_dict_del(spool_dict, "body");
}
}
@@ -1896,6 +1897,10 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
UWSGI_GET_GIL
if (pybody) {
Py_DECREF(pybody);
}
if (priority) {
free(priority);
@@ -3104,6 +3109,35 @@ PyObject *py_uwsgi_cache_num(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_cache_keys(PyObject * self, PyObject * args) {
char *cache = NULL;
struct uwsgi_cache_item *uci = NULL;
uint64_t pos = 0;
if (!PyArg_ParseTuple(args, "|s:cache_keys", &cache)) {
return NULL;
}
struct uwsgi_cache *uc = uwsgi_cache_by_name(cache);
if (!uc) {
return PyErr_Format(PyExc_ValueError, "no local uWSGI cache available");
}
PyObject *l = PyList_New(0);
uwsgi_rlock(uc->lock);
for(;;) {
uci = uwsgi_cache_keys(uc, &pos, &uci);
if (!uci) break;
PyObject *ci = PyString_FromStringAndSize(uci->key, uci->keysize);
PyList_Append(l, ci);
Py_DECREF(ci);
}
uwsgi_rwunlock(uc->lock);
return l;
}
static PyMethodDef uwsgi_cache_methods[] = {
{"cache_get", py_uwsgi_cache_get, METH_VARARGS, ""},
{"cache_set", py_uwsgi_cache_set, METH_VARARGS, ""},
@@ -3116,6 +3150,7 @@ static PyMethodDef uwsgi_cache_methods[] = {
{"cache_mul", py_uwsgi_cache_mul, METH_VARARGS, ""},
{"cache_div", py_uwsgi_cache_div, METH_VARARGS, ""},
{"cache_num", py_uwsgi_cache_num, METH_VARARGS, ""},
{"cache_keys", py_uwsgi_cache_keys, METH_VARARGS, ""},
{NULL, NULL},
};
+5 -1
View File
@@ -81,8 +81,9 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
#define LOADER_CALLABLE 5
#define LOADER_STRING_CALLABLE 6
#define LOADER_MOUNT 7
#define LOADER_PECAN 8
#define LOADER_MAX 8
#define LOADER_MAX 9
typedef struct uwsgi_Input {
PyObject_HEAD
@@ -124,6 +125,8 @@ struct uwsgi_python {
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
char *pecan;
char *wsgi_config;
char *file_config;
char *paste;
@@ -218,6 +221,7 @@ PyObject *uwsgi_uwsgi_loader(void *);
PyObject *uwsgi_dyn_loader(void *);
PyObject *uwsgi_file_loader(void *);
PyObject *uwsgi_eval_loader(void *);
PyObject *uwsgi_pecan_loader(void *);
PyObject *uwsgi_paste_loader(void *);
PyObject *uwsgi_callable_loader(void *);
PyObject *uwsgi_string_callable_loader(void *);
+3
View File
@@ -468,6 +468,9 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
if (wsgi_req->sendfile_fd >= 0) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
}
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
+34 -6
View File
@@ -28,6 +28,11 @@ struct uwsgi_option uwsgi_rack_options[] = {
{"ruby-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
{"rb-gc-freq", required_argument, 0, "set ruby GC frequency", uwsgi_opt_set_int, &ur.gc_freq, 0},
#ifdef RUBY19
{"rb-lib", required_argument, 0, "add a directory to the ruby libdir search path", uwsgi_opt_add_string_list, &ur.libdir, 0},
{"ruby-lib", required_argument, 0, "add a directory to the ruby libdir search path", uwsgi_opt_add_string_list, &ur.libdir, 0},
#endif
{"rb-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"ruby-require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
{"rbrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
@@ -456,9 +461,9 @@ static void rack_hack_dollar_zero(VALUE name, ID id) {
int uwsgi_rack_init(){
#ifdef RUBY19
int argc = 2;
char *sargv[] = { (char *) "uwsgi", (char *) "-e0" };
char **argv = sargv;
int argc = 2;
char *sargv[] = { (char *) "uwsgi", (char *) "-e0" };
char **argv = sargv;
#endif
if (ur.gemset) {
@@ -467,13 +472,37 @@ int uwsgi_rack_init(){
#ifdef RUBY19
ruby_sysinit(&argc, &argv);
RUBY_INIT_STACK
RUBY_INIT_STACK
#ifdef UWSGI_RUBY_HEROKU
uwsgi_log("*** Heroku system detected ***\n");
#endif
#ifdef RUBY_EXEC_PREFIX
if (!strcmp(RUBY_EXEC_PREFIX, "")) {
uwsgi_log("*** detected a ruby vm built with --enable-load-relative ***\n");
uwsgi_log("*** if you get errors about rubygems.rb, you can:\n");
uwsgi_log("*** 1) add a directory to the libdir search path using --ruby-libdir ***\n");
uwsgi_log("*** 2) force the RUBY_EXEC_PREFIX with --chdir ***\n");
#ifdef UWSGI_RUBY_LIBDIR
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_LIBDIR);
#endif
#ifdef UWSGI_RUBY_ARCHDIR
uwsgi_string_new_list(&ur.libdir, UWSGI_RUBY_ARCHDIR);
#endif
}
#endif
ruby_init();
ruby_process_options(argc, argv);
struct uwsgi_string_list *usl = ur.libdir;
while(usl) {
ruby_incpush(usl->value);
uwsgi_log("[ruby-libdir] pushed %s\n", usl->value);
usl = usl->next;
}
ruby_options(argc, argv);
#else
ruby_init();
ruby_init_loadpath();
#endif
ruby_show_version();
ruby_script("uwsgi");
@@ -487,7 +516,6 @@ int uwsgi_rack_init(){
rb_gc_register_address(&ur.signals_protector);
rb_gc_register_address(&ur.rpc_protector);
uwsgi_rack_init_api();
return 0;
+1
View File
@@ -54,6 +54,7 @@ struct uwsgi_rack {
char *gemset;
struct uwsgi_string_list *libdir;
};
void uwsgi_rack_init_api(void);
+14
View File
@@ -47,5 +47,19 @@ if has_shared == 'yes':
os.environ['LD_RUN_PATH'] = libpath
LIBS.append(os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip())
else:
rubylibdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['rubylibdir']\"").read().rstrip()
rubyarchdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['archdir']\"").read().rstrip()
# detect Heroku system
heroku = False
if rubylibdir.startswith('/tmp/build_'):
heroku = True
rubylibdir = '/app/' + '/'.join(rubylibdir.split('/')[3:])
if rubyarchdir.startswith('/tmp/build_'):
heroku = True
rubyarchdir = '/app/' + '/'.join(rubyarchdir.split('/')[3:])
if heroku:
CFLAGS.append('-DUWSGI_RUBY_HEROKU')
CFLAGS.append('-DUWSGI_RUBY_LIBDIR="\\"%s\\""' % rubylibdir)
CFLAGS.append('-DUWSGI_RUBY_ARCHDIR="\\"%s\\""' % rubyarchdir)
GCC_LIST.append("%s/%s" % (libpath, os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LIBRUBY_A']\"" % rbconfig).read().rstrip()))
+125
View File
@@ -0,0 +1,125 @@
#include <uwsgi.h>
#ifdef UWSGI_ROUTING
extern struct uwsgi_server uwsgi;
/*
by Unbit
syntax:
route = /^foobar1(.*)/ expires:filename=foo$1poo,value=30
route = /^foobar1(.*)/ expires:unix=${time[unix]},value=30
*/
struct uwsgi_router_expires_conf {
char *filename;
size_t filename_len;
char *unixt;
size_t unixt_len;
char *value;
size_t value_len;
};
static int uwsgi_routing_func_expires(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_expires_conf *urec = (struct uwsgi_router_expires_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t expires = 0;
if (urec->filename) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->filename, urec->filename_len);
if (!ub) return UWSGI_ROUTE_BREAK;
struct stat st;
if (stat(ub->buf, &st)) {
uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
expires = st.st_mtime;
uwsgi_buffer_destroy(ub);
}
else if (urec->unixt) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->unixt, urec->unixt_len);
if (!ub) return UWSGI_ROUTE_BREAK;
expires = strtoul(ub->buf, NULL, 10);
uwsgi_buffer_destroy(ub);
}
if (urec->value) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urec->value, urec->value_len);
if (!ub) return UWSGI_ROUTE_BREAK;
expires += atoi(ub->buf);
uwsgi_buffer_destroy(ub);
}
char expires_str[7 + 2 + 31];
int len = uwsgi_http_date((time_t) expires, expires_str + 9);
if (!len) return UWSGI_ROUTE_BREAK;
memcpy(expires_str, "Expires: ", 9);
uwsgi_additional_header_add(wsgi_req, expires_str, 9 + len);
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_expires(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_expires;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_expires_conf *urec = uwsgi_calloc(sizeof(struct uwsgi_router_expires_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"filename", &urec->filename,
"file", &urec->filename,
"unix", &urec->unixt,
"value", &urec->value,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (urec->filename) {
urec->filename_len = strlen(urec->filename);
}
if (urec->unixt) {
urec->unixt_len = strlen(urec->unixt);
}
if (urec->value) {
urec->value_len = strlen(urec->value);
}
ur->data2 = urec;
return 0;
}
static void router_expires_register() {
uwsgi_register_router("expires", uwsgi_router_expires);
}
struct uwsgi_plugin router_expires_plugin = {
.name = "router_expires",
.on_load = router_expires_register,
};
#else
struct uwsgi_plugin router_expires_plugin = {
.name = "router_expires",
};
#endif
+6
View File
@@ -0,0 +1,6 @@
NAME='router_expires'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['expires']
+1 -1
View File
@@ -73,7 +73,7 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
// drop newline
if (message[len-1] == '\n') len--;
#ifdef __sun__
#if defined(__sun__) && !defined(__clang__)
ctime_r(&current_time, ctime_storage, 26);
#else
ctime_r(&current_time, ctime_storage);
View File
View File
View File
+17 -17
View File
@@ -3,11 +3,11 @@ import uwsgi
import time
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type','text/html')])
return """
@@ -20,19 +20,19 @@ def application(env, sr):
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
@@ -43,13 +43,13 @@ def application(env, sr):
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/foobar/':
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
print "websockets..."
while True:
msg = uwsgi.websocket_recv()
-45
View File
@@ -1,45 +0,0 @@
#!./uwsgi
import uwsgi
from bottle import route, default_app, request, response, redirect
@route('/')
def chat():
return """<iframe src="/recv"></iframe>
<iframe src="/sender"></iframe>"""
@route('/sender')
def sender():
return """<form method="GET" action="/send">
<textarea name="message"></textarea><br/>
<input type="submit" value="send" />
</form>"""
@route('/recv')
def recv():
response.header['Transfer-Encoding'] = 'chunked'
# this will flush headers
yield ""
running = True
while running:
# this will put the core in pause (for max 10 seconds) and remove it from the sched queue, so the /send can write to its socket
if not uwsgi.green_pause(10):
running = False
# this will maintain the connection opened if no data arrives
yield "<span/>"
@route('/send')
def send():
# this will write to all the core in PAUSED state
uwsgi.green_write_all(request.GET['message'] + "<br/>")
# this will unpause all the paused cores, so they will be re-inserted in the sched queue
uwsgi.green_unpause_all()
redirect('/sender')
application = default_app()
-76
View File
@@ -1,76 +0,0 @@
import uuid
import uwsgi
import os
def application(env, start_response):
print(env.__class__)
print(env['PATH_INFO'])
print(env['REQUEST_METHOD'])
print(env['wsgi.input'])
if env['PATH_INFO'].startswith('/progress/'):
start_response('200 Ok', [('Content-type', 'application/json')])
filename = 'foobar/' + env['PATH_INFO'][10:]
print filename
if os.path.exists(filename):
return uwsgi.sendfile(filename)
else:
return "{ 'state': 'done' }"
if env['REQUEST_METHOD'] == 'POST':
start_response('200 Ok', [('Content-type', 'text/plain')])
#for x in env['wsgi.input']:
# yield x
body = env['wsgi.input'].read(int(env['CONTENT_LENGTH']))
body += env['wsgi.input'].readline()
#print body
body += env['wsgi.input'].read(100)
body += env['wsgi.input'].read(100)
body += env['wsgi.input'].read()
return body
else:
start_response('200 Ok', [('Content-type', 'text/html')])
x_progress_id = str(uuid.uuid4())
return """
<html>
<head>
<script src="/static/jquery-1.5.1.min.js" /></script>
<script language="Javascript">
var interval;
function redrawProgressBar() {
interval = setInterval(getData, 1000);
}
function getData() {
var jsr = $.getJSON("/progress/%s.js",
function(data) {
if (data) {
if (data.state == 'uploading') {
$('#progress').html(data.received + '/' + data.size);
return;
}
}
alert("fine");
clearInterval(interval);
}
);
jsr.error(function() { clearInterval(interval); });
}
</script>
</head>
<body>
upload progress: <div id="progress"> 0%%</div>
<form method="POST" enctype="multipart/form-data" action="?X-Progress-ID=%s" onsubmit="redrawProgressBar(); return true;">
<textarea name="pluto">
</textarea>
<input type="file" name="pippo" />
<input type="submit" value="invia" />
</form>
</body>
</html>
""" % (x_progress_id, x_progress_id)
+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-07-21'
s.date = '2013-08-29'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+64 -3
View File
@@ -130,6 +130,7 @@ extern "C" {
uwsgi.gp_cnt++;\
}\
#define uwsgi_foreach(x, y) for(x=y;x;x = x->next)
#ifndef __need_IOV_MAX
@@ -137,9 +138,13 @@ extern "C" {
#endif
#ifdef __sun__
#ifndef _XPG4_2
#define _XPG4_2
#endif
#ifndef __EXTENSIONS__
#define __EXTENSIONS__
#endif
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -165,6 +170,7 @@ extern "C" {
#endif
#endif
#include <sys/socket.h>
#include <net/if.h>
#ifdef __linux__
#ifndef MSG_FASTOPEN
#define MSG_FASTOPEN 0x20000000
@@ -609,6 +615,8 @@ struct uwsgi_legion {
int quorum;
int changed;
// if set the next packet will be a death-announce
int dead;
// set to 1 first time when quorum is reached
int joined;
@@ -926,6 +934,9 @@ struct uwsgi_socket {
int lazy;
int shared;
int from_shared;
// used for avoiding vacuum mess
ino_t inode;
};
struct uwsgi_server;
@@ -1561,12 +1572,17 @@ void uwsgi_opt_load_config(char *, char *, void *);
#define uwsgi_instance_is_dying (uwsgi.status.gracefully_destroying || uwsgi.status.brutally_destroying)
#define uwsgi_instance_is_reloading (uwsgi.status.gracefully_reloading || uwsgi.status.brutally_reloading)
#define exit(x) uwsgi_exit(x)
struct uwsgi_server {
// store the machine hostname
char hostname[256];
int hostname_len;
// used to store the exit code for atexit hooks
int last_exit_code;
int (*proto_hooks[UWSGI_PROTO_MAX_CHECK]) (struct wsgi_request *, char *, char *, uint16_t);
struct uwsgi_configurator *configurators;
@@ -1635,6 +1651,9 @@ struct uwsgi_server {
// kill the stack on SIGTERM (instead of brutal reloading)
int die_on_term;
// force the first gateway without a master
int force_gateway;
// disable fd passing on unix socket
int no_fd_passing;
@@ -1752,6 +1771,8 @@ struct uwsgi_server {
int dump_options;
// show ini representation of the current config
int show_config;
// enable strict mode (only registered options can be used)
int strict;
// list loaded features
int cheaper_algo_list;
@@ -1783,6 +1804,7 @@ struct uwsgi_server {
char *uidname;
char *gidname;
int no_initgroups;
struct uwsgi_string_list *additional_gids;
#ifdef UWSGI_CAP
cap_value_t *cap;
@@ -1791,7 +1813,9 @@ struct uwsgi_server {
#ifdef __linux__
int unshare;
int emperor_clone;
#endif
int refork;
int ignore_sigpipe;
int ignore_write_errors;
@@ -1809,8 +1833,9 @@ struct uwsgi_server {
// mostly useless
char *mode;
// binary path the worker image
// binary patch the worker image
char *worker_exec;
char *worker_exec2;
// this must be UN-shared
struct uwsgi_gateway_socket *gateway_sockets;
@@ -1877,6 +1902,30 @@ struct uwsgi_server {
struct uwsgi_string_list *exec_pre_app;
struct uwsgi_string_list *exec_post_app;
struct uwsgi_string_list *exec_as_vassal;
struct uwsgi_string_list *exec_as_emperor;
struct uwsgi_string_list *call_pre_jail;
struct uwsgi_string_list *call_post_jail;
struct uwsgi_string_list *call_in_jail;
struct uwsgi_string_list *call_as_root;
struct uwsgi_string_list *call_as_user;
struct uwsgi_string_list *call_as_user_atexit;
struct uwsgi_string_list *call_pre_app;
struct uwsgi_string_list *call_post_app;
struct uwsgi_string_list *call_as_vassal;
struct uwsgi_string_list *call_as_vassal1;
struct uwsgi_string_list *call_as_vassal3;
struct uwsgi_string_list *call_as_emperor;
struct uwsgi_string_list *call_as_emperor1;
struct uwsgi_string_list *call_as_emperor2;
struct uwsgi_string_list *call_as_emperor4;
struct uwsgi_string_list *wait_for_interface;
int wait_for_interface_timeout;
char *privileged_binary_patch;
char *unprivileged_binary_patch;
char *privileged_binary_patch_arg;
@@ -2160,7 +2209,7 @@ struct uwsgi_server {
mode_t chmod_logfile_value;
int listen_queue;
char *file_config;
char *fallback_config;
#ifdef UWSGI_ROUTING
struct uwsgi_router *routers;
@@ -2180,6 +2229,7 @@ struct uwsgi_server {
int skip_zero;
int skip_atexit;
char *force_cwd;
char *chdir;
char *chdir2;
@@ -3109,6 +3159,8 @@ void uwsgi_add_sockets_to_queue(int, int);
void uwsgi_del_sockets_from_queue(int);
int uwsgi_run_command_and_wait(char *, char *);
int uwsgi_run_command_putenv_and_wait(char *, char *, char **, unsigned int);
int uwsgi_call_symbol(char *);
void uwsgi_manage_signal_cron(time_t);
pid_t uwsgi_run_command(char *, int *, int);
@@ -3249,7 +3301,7 @@ int uwsgi_is_bad_connection(int);
int uwsgi_long2str2n(unsigned long long, char *, int);
#ifdef __linux__
void uwsgi_build_unshare(char *);
void uwsgi_build_unshare(char *, int *);
#ifdef MADV_MERGEABLE
void uwsgi_linux_ksm_map(void);
#endif
@@ -3872,6 +3924,7 @@ void uwsgi_opt_legion_hook(char *, char *, void *);
void uwsgi_legion_register_hook(struct uwsgi_legion *, char *, char *);
void uwsgi_opt_legion_scroll(char *, char *, void *);
void uwsgi_legion_add(struct uwsgi_legion *);
void uwsgi_legion_announce_death(void);
char *uwsgi_ssl_rand(size_t);
void uwsgi_start_legions(void);
int uwsgi_legion_announce(struct uwsgi_legion *);
@@ -4122,6 +4175,14 @@ int uwsgi_register_fsmon(struct uwsgi_string_list *);
int uwsgi_fsmon_event(int);
void uwsgi_fsmon_setup();
void uwsgi_exit(int) __attribute__ ((__noreturn__));
void uwsgi_fallback_config();
struct uwsgi_cache_item *uwsgi_cache_keys(struct uwsgi_cache *, uint64_t *, struct uwsgi_cache_item **);
void uwsgi_cache_rlock(struct uwsgi_cache *);
void uwsgi_cache_rwunlock(struct uwsgi_cache *);
char *uwsgi_cache_item_key(struct uwsgi_cache_item *);
#ifdef __cplusplus
}
#endif
+22 -8
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.14'
uwsgi_version = '1.9.15'
import os
import re
@@ -570,6 +570,14 @@ class uConf(object):
if additional_include_paths:
for ipath in additional_include_paths.split():
self.include_path.append(ipath)
if 'UWSGI_REMOVE_INCLUDES' in os.environ:
for inc in os.environ['UWSGI_REMOVE_INCLUDES'].split(','):
try:
self.include_path.remove(inc)
except:
pass
if not mute:
print("detected include path: %s" % self.include_path)
@@ -649,6 +657,10 @@ class uConf(object):
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
if 'UWSGI_AS_LIB' in os.environ:
self.set('as_shared_library', 'true')
self.set('bin_name', os.environ['UWSGI_AS_LIB'])
if self.has_include('ifaddrs.h'):
self.cflags.append('-DUWSGI_HAS_IFADDRS')
report['ifaddrs'] = True
@@ -918,10 +930,11 @@ class uConf(object):
self.libs.append('-lcap')
report['capabilities'] = True
if self.has_include('matheval.h'):
self.cflags.append("-DUWSGI_MATHEVAL")
self.libs.append('-lmatheval')
report['matheval'] = True
if self.get('matheval'):
if (self.get('matheval') == 'auto' and self.has_include('matheval.h')) or self.get('matheval') == 'true':
self.cflags.append("-DUWSGI_MATHEVAL")
self.libs.append('-lmatheval')
report['matheval'] = True
has_json = False
has_uuid = False
@@ -1113,7 +1126,7 @@ class uConf(object):
report['xml'] = 'expat'
if self.get('plugin_dir'):
self.cflags.append('-DUWSGI_PLUGIN_DIR=\\"%s\\"' % self.get('plugin_dir'))
self.cflags.append('-DUWSGI_PLUGIN_DIR="\\"%s\\""' % self.get('plugin_dir'))
report['plugin_dir'] = self.get('plugin_dir')
if self.get('debug'):
@@ -1322,10 +1335,10 @@ if __name__ == "__main__":
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
try:
bconf = sys.argv[3]
if not bconf.endswith('.ini'):
bconf += '.ini'
except:
pass
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
uc = uConf(bconf)
@@ -1350,6 +1363,7 @@ if __name__ == "__main__":
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':
os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/ proto/ lib/ apache2/")
+13 -1
View File
@@ -49,7 +49,19 @@ uwsgi.post_fork_hook = postfork_chain_hook
class postfork(object):
def __init__(self, f):
postfork_chain.append(f)
if callable(f):
self.wid = 0
self.f = f
else:
self.f = None
self.wid = f
postfork_chain.append(self)
def __call__(self, *args, **kwargs):
if self.f:
if self.wid > 0 and self.wid != uwsgi.worker_id():
return
return self.f()
self.f = args[0]
class _spoolraw(object):