mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50954d34db | ||
|
|
ef2d9e781f | ||
|
|
a9bb310a20 | ||
|
|
86f37556da | ||
|
|
a57617c09a | ||
|
|
63ac62cf1d | ||
|
|
ac371730fd | ||
|
|
4ed6588c80 | ||
|
|
81d20edc4c | ||
|
|
a9fc6adccf | ||
|
|
21ad94ba4e | ||
|
|
571b9f27e1 | ||
|
|
cbf9ccf062 | ||
|
|
dd8fd8f19c | ||
|
|
1535b8ee13 | ||
|
|
f2491536dd | ||
|
|
88ce0181b3 | ||
|
|
4ad2658090 | ||
|
|
8d80c5e84d | ||
|
|
bae9235103 | ||
|
|
8ae2d0d00c | ||
|
|
373b89e70c | ||
|
|
c14e18b270 | ||
|
|
68ec3afd1a | ||
|
|
8918e81256 | ||
|
|
469fd697cb | ||
|
|
20844ebfca | ||
|
|
38652076d3 | ||
|
|
f13ae47fc0 | ||
|
|
ad4ee9d5c3 | ||
|
|
03a4e900ea | ||
|
|
b52dbf2aa0 | ||
|
|
c7a22c3b53 | ||
|
|
775aae3f1e | ||
|
|
862731ba91 | ||
|
|
8c302eee51 | ||
|
|
b6d34067c4 | ||
|
|
dbe15195b7 | ||
|
|
5642aa1eb5 | ||
|
|
5dd465ccc1 | ||
|
|
ae78c3007e | ||
|
|
16211d9439 | ||
|
|
515619fe2a | ||
|
|
a7d550165d | ||
|
|
efceacd9e5 | ||
|
|
ea5ebc2d15 | ||
|
|
fba82c203c | ||
|
|
a50516af7a | ||
|
|
6056b51653 | ||
|
|
23a3170c59 | ||
|
|
e136128408 | ||
|
|
fce94e0f54 | ||
|
|
06fa65bc5d | ||
|
|
571ec5ca72 | ||
|
|
39bc0ecd46 | ||
|
|
7a5373360c | ||
|
|
15453ffef6 | ||
|
|
a25747a096 | ||
|
|
bb1ef59b52 | ||
|
|
6bb3af840d | ||
|
|
0223c74ecc | ||
|
|
c7004d7ba4 | ||
|
|
915d2e9192 | ||
|
|
df79b9367b | ||
|
|
ce3d026037 | ||
|
|
d0f6c4130b | ||
|
|
26bcf28182 | ||
|
|
272d1ccc03 | ||
|
|
6c440af24e | ||
|
|
8954520cb9 | ||
|
|
31bde74fab | ||
|
|
13c64a383c | ||
|
|
809028f11b | ||
|
|
dee9d2ba1e | ||
|
|
29d80ce061 | ||
|
|
abcd3242d8 | ||
|
|
f4762299f9 | ||
|
|
107f4309a4 | ||
|
|
d2a8df19ea | ||
|
|
29efd15534 | ||
|
|
e7fb216a8d | ||
|
|
952b96cdcb | ||
|
|
8ee82fc296 | ||
|
|
afe2bfb856 | ||
|
|
5b63e9aea0 | ||
|
|
91f70259e2 | ||
|
|
f120cacc03 | ||
|
|
aff1d782b8 | ||
|
|
b489fd8a24 | ||
|
|
47e0eb68c2 | ||
|
|
9498e25245 | ||
|
|
a33e18b589 | ||
|
|
f2dcdf2289 | ||
|
|
74c53e8a61 | ||
|
|
1feed87c10 | ||
|
|
f89742d81a | ||
|
|
340b9d603e | ||
|
|
1c0fc64243 | ||
|
|
1d5173d923 | ||
|
|
49a8bf0b9b | ||
|
|
0a7e5a41a2 | ||
|
|
43ff563429 | ||
|
|
2daf6f1f66 | ||
|
|
985f56768f | ||
|
|
35278588f5 | ||
|
|
f6545be647 | ||
|
|
f387d27582 | ||
|
|
5d8e5d943f | ||
|
|
4046f76cb2 | ||
|
|
8baeb0af2f | ||
|
|
63e0105a0f | ||
|
|
70daa57caf | ||
|
|
db0f7951a9 | ||
|
|
45a7a3066d | ||
|
|
c73a6723d7 | ||
|
|
fb55f57531 | ||
|
|
8cf4d5802a | ||
|
|
e3c042e567 | ||
|
|
5435f8927c | ||
|
|
e1e65c46ac | ||
|
|
e1f3665a8e | ||
|
|
ef09a010cf | ||
|
|
3f5d79c755 | ||
|
|
3b5468f39f | ||
|
|
5598c7cc22 | ||
|
|
d6fdb812a2 | ||
|
|
e6d5f6c612 | ||
|
|
8f10daa2bf | ||
|
|
f027153452 | ||
|
|
0ebda93a50 | ||
|
|
dc4e8950d2 | ||
|
|
0f5336028f | ||
|
|
e02341bffe | ||
|
|
ac92ff4079 | ||
|
|
a5da77bc54 | ||
|
|
0441e88b82 | ||
|
|
815f4abec0 | ||
|
|
4f9e2ff3f6 | ||
|
|
ce8dd001bf | ||
|
|
d4e90f5215 | ||
|
|
da13562890 | ||
|
|
d320075ab0 | ||
|
|
4061826da4 | ||
|
|
2854321891 | ||
|
|
c4181cdc55 | ||
|
|
327582b695 | ||
|
|
f56b9be4c5 | ||
|
|
28ccace24f | ||
|
|
13f82176e3 | ||
|
|
be4d324f6b | ||
|
|
36486caabb | ||
|
|
b3af255727 | ||
|
|
a56f726f7d | ||
|
|
24d6470f38 | ||
|
|
7e079e4c40 | ||
|
|
0d9bc03c53 | ||
|
|
7598666768 | ||
|
|
cd6f027705 | ||
|
|
0803a7f0b0 | ||
|
|
0eb956db4a | ||
|
|
76c6ae6d16 | ||
|
|
40054e3494 | ||
|
|
8927dfd538 | ||
|
|
68f734fcad | ||
|
|
af4c7f74d5 | ||
|
|
4581d1e7ce | ||
|
|
d465f61506 | ||
|
|
5cae9b9ba4 | ||
|
|
428a2d9366 | ||
|
|
1c00b54b06 | ||
|
|
6228fb91da | ||
|
|
307cf3a0ef | ||
|
|
f723a804c0 | ||
|
|
24ac19e2d6 | ||
|
|
38147d50ff | ||
|
|
9f7db10582 | ||
|
|
ed35a50e6c | ||
|
|
fae08f49cf | ||
|
|
35f5b5b2eb | ||
|
|
b785c8fccf | ||
|
|
597c3cd7f1 | ||
|
|
bbbe01ef4b | ||
|
|
ea1e1cb65f | ||
|
|
a1d31ae954 | ||
|
|
fa0ed9489a | ||
|
|
7bb7b351e0 | ||
|
|
cb45f207a6 | ||
|
|
82ffb60bdd | ||
|
|
ec38ce9a26 | ||
|
|
8279926bab | ||
|
|
ac17b0910e | ||
|
|
aae3e7ff17 | ||
|
|
4cfff98cd1 | ||
|
|
19ee50949c | ||
|
|
ec27d624c3 | ||
|
|
0dc8803ff8 | ||
|
|
e8ea1a55f9 | ||
|
|
a0cb71ca78 | ||
|
|
5c5aef3827 | ||
|
|
737a7f4d51 | ||
|
|
c3ee774d56 | ||
|
|
2d5adacc65 | ||
|
|
b7a8cc0297 | ||
|
|
317b0f79a8 |
@@ -9,3 +9,5 @@
|
||||
/uwsgibuild.*
|
||||
|
||||
/t/ring/target
|
||||
|
||||
core/dot_h.c
|
||||
|
||||
@@ -24,3 +24,4 @@ Stephen Pierce
|
||||
Mingli Yuan
|
||||
Natanael Copa
|
||||
Roberto Leandrini
|
||||
Ryan Petrello
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
|
||||
inherit = base
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
matheval = false
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rados
|
||||
inherit = base
|
||||
+2
-3
@@ -184,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
|
||||
// map instances to the log
|
||||
char *list = uwsgi_str(alarms);
|
||||
char *p = strtok(list, ",");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) {
|
||||
free(list);
|
||||
@@ -205,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
else {
|
||||
ual->alarms = uall;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+29
-1
@@ -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) {
|
||||
@@ -169,6 +172,16 @@ int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
|
||||
uint8_t buf[4];
|
||||
uint32_t *pnum = (uint32_t *) #
|
||||
buf[3] = (uint8_t) (*pnum & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
@@ -192,6 +205,20 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
|
||||
uint8_t buf[8];
|
||||
uint64_t *pnum = (uint64_t *) #
|
||||
buf[7] = (uint8_t) (*pnum & 0xff);
|
||||
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
if (!inet_ntop(AF_INET, addr, ip, INET_ADDRSTRLEN)) {
|
||||
@@ -271,8 +298,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
|
||||
|
||||
+40
-9
@@ -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) {
|
||||
@@ -1190,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->store = c_store;
|
||||
|
||||
if (c_nodes) {
|
||||
char *p = strtok(c_nodes, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_sync) {
|
||||
char *p = strtok(c_sync, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_sync, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_udp_servers) {
|
||||
char *p = strtok(c_udp_servers, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->udp_servers, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1920,3 +1918,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;
|
||||
}
|
||||
|
||||
+19
-3
@@ -55,10 +55,9 @@ int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
|
||||
|
||||
int uwsgi_logic_opt_for(char *key, char *value) {
|
||||
|
||||
char *p = strtok(uwsgi.logic_opt_data, " ");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -458,6 +457,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
|
||||
}
|
||||
}
|
||||
|
||||
+23
-6
@@ -77,8 +77,14 @@ void uwsgi_daemons_smart_check() {
|
||||
else {
|
||||
ud->pidfile_checks++;
|
||||
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
if (!ud->has_daemonized) {
|
||||
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
|
||||
ud->pidfile_checks = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,10 +105,20 @@ void uwsgi_daemons_smart_check() {
|
||||
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
if (ud->pid == diedpid) {
|
||||
if (!ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!ud->has_daemonized) {
|
||||
ud->has_daemonized = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -251,6 +267,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->has_daemonized = 0;
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
ud->pidfile_checks = 0;
|
||||
|
||||
+174
-18
@@ -620,7 +620,7 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
// remove uWSGI instance
|
||||
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_stop()/write()");
|
||||
}
|
||||
|
||||
c_ui->status = 1;
|
||||
@@ -634,7 +634,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_respawn/write()");
|
||||
}
|
||||
|
||||
// push the config to the config pipe (if needed)
|
||||
@@ -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,86 @@ 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
|
||||
uwsgi_hooks_run(uwsgi.hook_as_emperor, "as-emperor", 0);
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
|
||||
uwsgi_log("mounting \"%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);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
|
||||
uwsgi_log("un-mounting \"%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);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
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", (int) n_ui->pid); argv[1] = argv_pid;
|
||||
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", (int) n_ui->uid); argv[2] = argv_uid;
|
||||
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", (int) 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 +961,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 +987,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 +1024,25 @@ 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);
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -1009,6 +1099,15 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
@@ -1037,6 +1136,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 +1148,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 +1160,60 @@ 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);
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_vassal, "as-vassal", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_vassal) {
|
||||
uwsgi_log("mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_vassal) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 +1221,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) {
|
||||
@@ -1369,10 +1521,14 @@ void emperor_loop() {
|
||||
while (ui_current) {
|
||||
if (ui_current->last_heartbeat > 0) {
|
||||
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
// set last_heartbeat to 0 avoiding races
|
||||
ui_current->last_heartbeat = 0;
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
if (ui_current->pid > 0) {
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_current = ui_current->ui_next;
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
the --master-fifo option create a unix named pipe (fifo) you can use to send management
|
||||
commands to the master:
|
||||
|
||||
echo r > myfifo
|
||||
|
||||
*/
|
||||
|
||||
// this var can be accessed by plugins and hooks
|
||||
void (*uwsgi_fifo_table[256])(int);
|
||||
|
||||
static char *uwsgi_fifo_by_slot() {
|
||||
int count = 0;
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.master_fifo) {
|
||||
if (count == uwsgi.master_fifo_slot) return usl->value;
|
||||
count++;
|
||||
}
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
|
||||
|
||||
/*
|
||||
|
||||
this is called as soon as possibile allowing plugins (or hooks) to override it
|
||||
|
||||
*/
|
||||
void uwsgi_master_fifo_prepare() {
|
||||
int i;
|
||||
for(i=0;i<256;i++) {
|
||||
uwsgi_fifo_table[i] = NULL;
|
||||
}
|
||||
|
||||
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
|
||||
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
|
||||
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
|
||||
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
|
||||
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
|
||||
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
|
||||
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
|
||||
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
|
||||
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
|
||||
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['f'] = uwsgi_refork_master;
|
||||
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
|
||||
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
|
||||
uwsgi_fifo_table['p'] = suspend_resume_them_all;
|
||||
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
|
||||
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
|
||||
uwsgi_fifo_table['Q'] = kill_them_all;
|
||||
uwsgi_fifo_table['r'] = grace_them_all;
|
||||
uwsgi_fifo_table['R'] = reap_them_all;
|
||||
uwsgi_fifo_table['s'] = stats;
|
||||
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
|
||||
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo() {
|
||||
|
||||
char *path = uwsgi_fifo_by_slot();
|
||||
|
||||
unlink(path);
|
||||
|
||||
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_master_fifo()/open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_master_fifo_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
close(fd);
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_fifo_table[(int) cmd]) {
|
||||
uwsgi_fifo_table[(int) cmd](0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -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++;
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
advanced (pluggable) hooks
|
||||
|
||||
they are executed before the other hooks, and can be extended by plugins
|
||||
|
||||
if a plugin tries to register an hook with a name already available in the list, its function
|
||||
will be overridden
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
|
||||
struct uwsgi_hook *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
return uh;
|
||||
}
|
||||
uh = uh->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
uh->func = func;
|
||||
return;
|
||||
}
|
||||
old_uh = uh;
|
||||
uh = uh->next;
|
||||
}
|
||||
|
||||
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
|
||||
uh->name = name;
|
||||
uh->func = func;
|
||||
|
||||
if (old_uh) {
|
||||
old_uh->next = uh;
|
||||
}
|
||||
else {
|
||||
uwsgi.hooks = uh;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chdir(char *arg) {
|
||||
int ret = chdir(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chdir()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exit(char *arg) {
|
||||
int exit_code = 0;
|
||||
if (strlen(arg) > 1) {
|
||||
exit_code = atoi(arg);
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_print(char *arg) {
|
||||
char *line = uwsgi_concat2(arg, "\n");
|
||||
uwsgi_log(line);
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callint(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(num);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_call(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(space + 1);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callintret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(num);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(space + 1);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("mount", uwsgi_mount_hook);
|
||||
uwsgi_register_hook("umount", uwsgi_umount_hook);
|
||||
|
||||
uwsgi_register_hook("call", uwsgi_hook_call);
|
||||
uwsgi_register_hook("callret", uwsgi_hook_callret);
|
||||
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
}
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
char *colon = strchr(usl->value, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid hook syntax, must be hook:args\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
|
||||
if (!uh) {
|
||||
uwsgi_log("hook not found: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
-6
@@ -172,6 +172,11 @@ void uwsgi_init_default() {
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
|
||||
// clear reforked status
|
||||
uwsgi.master_is_reforked = 0;
|
||||
|
||||
uwsgi_master_fifo_prepare();
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -216,21 +221,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
|
||||
p = original_proc_name;
|
||||
p = strstr(p, "uwsgi_");
|
||||
if (p != NULL) {
|
||||
plugins_requested = strtok(uwsgi_str(p + 6), "_");
|
||||
while (plugins_requested) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
|
||||
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
|
||||
uwsgi_load_plugin(-1, plugins_requested, NULL);
|
||||
plugins_requested = strtok(NULL, "_");
|
||||
}
|
||||
}
|
||||
|
||||
plugins_requested = getenv("UWSGI_PLUGINS");
|
||||
if (plugins_requested) {
|
||||
plugins_requested = uwsgi_concat2(plugins_requested, "");
|
||||
char *p = strtok(plugins_requested, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
|
||||
uwsgi_load_plugin(-1, p, NULL);
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +360,7 @@ void uwsgi_setup_workers() {
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.response_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
@@ -387,6 +391,8 @@ pid_t uwsgi_daemonize2() {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
|
||||
if (uwsgi.log_master) uwsgi_setup_log_master();
|
||||
|
||||
return uwsgi.mypid;
|
||||
}
|
||||
|
||||
@@ -449,6 +455,19 @@ void sanitize_args() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* here we try to choose if thunder lock is a good thing */
|
||||
#ifdef UNBIT
|
||||
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
|
||||
|
||||
+25
-2
@@ -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) {
|
||||
|
||||
+35
-6
@@ -493,7 +493,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
@@ -504,7 +504,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
}
|
||||
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
@@ -512,7 +512,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -532,7 +532,13 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,7 +555,13 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -574,6 +586,8 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
if (uwsgi.persistent_ipcsem) return;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers)
|
||||
@@ -594,12 +608,27 @@ clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
#ifdef GETPID
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
int ret = semctl(semid, 0, GETPID);
|
||||
if (ret > 0) {
|
||||
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
|
||||
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
uli = uwsgi.registered_locks;
|
||||
#endif
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
+564
-78
@@ -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);
|
||||
@@ -120,17 +120,54 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
|
||||
|
||||
|
||||
static void fix_logpipe_buf(int *fd) {
|
||||
int so_bufsize;
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
|
||||
if (getsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/getsockopt()");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
|
||||
so_bufsize = uwsgi.log_master_bufsize;
|
||||
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/setsockopt()");
|
||||
}
|
||||
}
|
||||
|
||||
if (getsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/getsockopt()");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
|
||||
so_bufsize = uwsgi.log_master_bufsize;
|
||||
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create the logpipe
|
||||
void create_logpipe(void) {
|
||||
|
||||
if (uwsgi.log_master_stream) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
fix_logpipe_buf(uwsgi.shared->worker_log_pipe);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
|
||||
@@ -149,13 +186,22 @@ void create_logpipe(void) {
|
||||
}
|
||||
|
||||
if (uwsgi.req_log_master) {
|
||||
if (uwsgi.log_master_req_stream) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
fix_logpipe_buf(uwsgi.shared->worker_req_log_pipe);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
|
||||
@@ -287,6 +333,8 @@ void logto(char *logfile) {
|
||||
|
||||
|
||||
void uwsgi_setup_log() {
|
||||
|
||||
uwsgi_setup_log_encoders();
|
||||
|
||||
if (uwsgi.daemonize) {
|
||||
if (uwsgi.has_emperor) {
|
||||
@@ -440,7 +488,6 @@ void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen,
|
||||
|
||||
void uwsgi_check_logrotate(void) {
|
||||
|
||||
char message[1024];
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
|
||||
@@ -464,70 +511,81 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
|
||||
if (need_rotation) {
|
||||
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
uwsgi_log_rotate();
|
||||
}
|
||||
else if (need_reopen) {
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
uwsgi_log_reopen();
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
|
||||
void uwsgi_log_reopen() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
@@ -616,7 +674,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 +1093,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 +1118,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 +1317,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;
|
||||
@@ -1328,6 +1404,45 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_logger *ul, char *msg, size_t len) {
|
||||
struct uwsgi_string_list *usl = encoders;
|
||||
// note: msg must not be freed !!!
|
||||
char *new_msg = msg;
|
||||
size_t new_msg_len = len;
|
||||
while(usl) {
|
||||
struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
|
||||
if (ule->use_for) {
|
||||
if (ul && ul->id) {
|
||||
if (strcmp(ule->use_for, ul->id)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
size_t rlen = 0;
|
||||
char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
|
||||
if (new_msg != msg) {
|
||||
free(new_msg);
|
||||
}
|
||||
new_msg = buf;
|
||||
new_msg_len = rlen;
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
if (ul) {
|
||||
ul->func(ul, new_msg, new_msg_len);
|
||||
}
|
||||
else {
|
||||
new_msg_len = (size_t) write(uwsgi.original_log_fd, new_msg, new_msg_len);
|
||||
}
|
||||
if (new_msg != msg) {
|
||||
free(new_msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_log(void) {
|
||||
|
||||
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
|
||||
@@ -1361,7 +1476,7 @@ int uwsgi_master_log(void) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
|
||||
if (ul_route) {
|
||||
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
@@ -1379,14 +1494,14 @@ int uwsgi_master_log(void) {
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, ul, uwsgi.log_master_buf, rlen);
|
||||
raw_log = 0;
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
if (raw_log) {
|
||||
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, NULL, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1405,7 +1520,7 @@ int uwsgi_master_req_log(void) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
|
||||
if (ul_route) {
|
||||
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
@@ -1423,14 +1538,14 @@ int uwsgi_master_req_log(void) {
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul, uwsgi.log_master_buf, rlen);
|
||||
raw_log = 0;
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
if (raw_log) {
|
||||
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, NULL, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1493,3 +1608,374 @@ void uwsgi_threaded_logger_spawn() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_register_log_encoder(char *name, char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *)) {
|
||||
struct uwsgi_log_encoder *old_ule = NULL, *ule = uwsgi.log_encoders;
|
||||
|
||||
while(ule) {
|
||||
if (!strcmp(ule->name, name)) {
|
||||
ule->func = func;
|
||||
return;
|
||||
}
|
||||
old_ule = ule;
|
||||
ule = ule->next;
|
||||
}
|
||||
|
||||
ule = uwsgi_calloc(sizeof(struct uwsgi_log_encoder));
|
||||
ule->name = name;
|
||||
ule->func = func;
|
||||
|
||||
if (old_ule) {
|
||||
old_ule->next = ule;
|
||||
}
|
||||
else {
|
||||
uwsgi.log_encoders = ule;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_log_encoder *uwsgi_log_encoder_by_name(char *name) {
|
||||
struct uwsgi_log_encoder *ule = uwsgi.log_encoders;
|
||||
while(ule) {
|
||||
if (!strcmp(name, ule->name)) return ule;
|
||||
ule = ule->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_encoders() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) *space = 0;
|
||||
char *use_for = strchr(usl->value, ':');
|
||||
if (use_for) *use_for = 0;
|
||||
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
|
||||
if (!ule) {
|
||||
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
|
||||
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
|
||||
if (use_for) {
|
||||
ule2->use_for = uwsgi_str(use_for+1);
|
||||
*use_for = ':';
|
||||
}
|
||||
// we use a copy
|
||||
if (space) {
|
||||
*space = ' ';
|
||||
ule2->args = uwsgi_str(space+1);
|
||||
}
|
||||
else {
|
||||
ule2->args = uwsgi_str("");
|
||||
}
|
||||
|
||||
usl->custom_ptr = ule2;
|
||||
uwsgi_log("[log-encoder] registered %s\n", usl->value);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) *space = 0;
|
||||
char *use_for = strchr(usl->value, ':');
|
||||
if (use_for) *use_for = 0;
|
||||
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
|
||||
if (!ule) {
|
||||
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
|
||||
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
|
||||
if (use_for) {
|
||||
ule2->use_for = uwsgi_str(use_for+1);
|
||||
*use_for = ':';
|
||||
}
|
||||
// we use a copy
|
||||
if (space) {
|
||||
*space = ' ';
|
||||
ule2->args = uwsgi_str(space+1);
|
||||
}
|
||||
else {
|
||||
ule2->args = uwsgi_str("");
|
||||
}
|
||||
usl->custom_ptr = ule2;
|
||||
uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
static char *uwsgi_log_encoder_gzip(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
struct uwsgi_buffer *ub = uwsgi_gzip(msg, len);
|
||||
if (!ub) return NULL;
|
||||
*rlen = ub->pos;
|
||||
// avoid destruction
|
||||
char *buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *uwsgi_log_encoder_compress(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
size_t c_len = (size_t) compressBound(len);
|
||||
uLongf destLen = c_len;
|
||||
char *buf = uwsgi_malloc(c_len);
|
||||
if (compress((Bytef *) buf, &destLen, (Bytef *)msg, (uLong) len) == Z_OK) {
|
||||
*rlen = destLen;
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a prefix
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_prefix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a newline
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_nl(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + 1);
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
if (uwsgi_buffer_byte(ub, '\n')) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a suffix
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_suffix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
|
||||
char *ptr = ule->args;
|
||||
size_t remains = strlen(ptr);
|
||||
char *base = ptr;
|
||||
size_t base_len = 0;
|
||||
char *var = NULL;
|
||||
size_t var_len = 0;
|
||||
int status = 0; // 1 -> $ 2-> { end -> }
|
||||
while(remains--) {
|
||||
char b = *ptr++;
|
||||
if (status == 1) {
|
||||
if (b == '{') {
|
||||
status = 2;
|
||||
continue;
|
||||
}
|
||||
base_len+=2;
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
else if (status == 2) {
|
||||
if (b == '}') {
|
||||
status = 0;
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(var, var_len, "", 0));
|
||||
usl->custom = 1;
|
||||
var = NULL;
|
||||
var_len = 0;
|
||||
base = NULL;
|
||||
base_len = 0;
|
||||
continue;
|
||||
}
|
||||
if (!var) var = (ptr-1);
|
||||
var_len++;
|
||||
continue;
|
||||
}
|
||||
// status == 0
|
||||
if (b == '$') {
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
if (!base) base = (ptr-1);
|
||||
base_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (base) {
|
||||
if (status == 1) {
|
||||
base_len+=2;
|
||||
}
|
||||
else if (status == 2) {
|
||||
base_len+=3;
|
||||
}
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// format: foo ${var} bar
|
||||
msg (the logline)
|
||||
msgnl (the logine with newline)
|
||||
unix (the time_t value)
|
||||
micros (current microseconds)
|
||||
strftime (strftime)
|
||||
*/
|
||||
static char *uwsgi_log_encoder_format(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
|
||||
if (!ule->configured) {
|
||||
uwsgi_log_encoder_parse_vars(ule);
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
|
||||
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
|
||||
char *buf = NULL;
|
||||
while(usl) {
|
||||
if (usl->custom) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
if (msg[len-1] == '\n') {
|
||||
if (uwsgi_buffer_append(ub, msg, len-1)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
|
||||
}
|
||||
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9,"", 0);
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
if (uwsgi_buffer_append(ub, sftime, strftime_len)) goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
|
||||
if (!ule->configured) {
|
||||
uwsgi_log_encoder_parse_vars(ule);
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
|
||||
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
|
||||
char *buf = NULL;
|
||||
while(usl) {
|
||||
if (usl->custom) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
size_t msg_len = len;
|
||||
if (msg[len-1] == '\n') msg_len--;
|
||||
char *e_json = uwsgi_malloc(msg_len * 2);
|
||||
escape_json(msg, msg_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
char *e_json = uwsgi_malloc(len * 2);
|
||||
escape_json(msg, len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
|
||||
}
|
||||
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9, "", 0);
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
char *e_json = uwsgi_malloc(strftime_len * 2);
|
||||
escape_json(sftime, strftime_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_log_encoders_register_embedded() {
|
||||
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
|
||||
uwsgi_register_log_encoder("suffix", uwsgi_log_encoder_suffix);
|
||||
uwsgi_register_log_encoder("nl", uwsgi_log_encoder_nl);
|
||||
uwsgi_register_log_encoder("format", uwsgi_log_encoder_format);
|
||||
uwsgi_register_log_encoder("json", uwsgi_log_encoder_json);
|
||||
#ifdef UWSGI_ZLIB
|
||||
uwsgi_register_log_encoder("gzip", uwsgi_log_encoder_gzip);
|
||||
uwsgi_register_log_encoder("compress", uwsgi_log_encoder_compress);
|
||||
#endif
|
||||
}
|
||||
|
||||
+83
-42
@@ -222,8 +222,8 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
#elif defined(__FreeBSD__)
|
||||
if (!uwsgi.shared->ti.__tcpi_sacked) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
|
||||
@@ -242,12 +242,12 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
|
||||
@@ -306,7 +306,6 @@ int master_loop(char **argv, char **environ) {
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
uwsgi_set_processname(uwsgi.procname_master);
|
||||
}
|
||||
@@ -346,6 +345,11 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
if (uwsgi.master_fifo) {
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
@@ -393,7 +397,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;
|
||||
@@ -477,7 +481,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
|
||||
// update exec touches
|
||||
struct uwsgi_string_list *usl = uwsgi.touch_exec;
|
||||
while(usl) {
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
@@ -489,16 +493,16 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
@@ -741,7 +745,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
|
||||
// resubscribe every 10 cycles by default
|
||||
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
uwsgi_subscribe_all(0, 0);
|
||||
}
|
||||
|
||||
@@ -765,40 +769,34 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
continue;
|
||||
}
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_reload_workers();
|
||||
continue;
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
if (touched) {
|
||||
if (uwsgi.status.chain_reloading == 0) {
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
}
|
||||
}
|
||||
|
||||
// be sure to run it as the last touch check
|
||||
touched = uwsgi_check_touches(uwsgi.touch_exec);
|
||||
if (touched) {
|
||||
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
|
||||
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -815,12 +813,18 @@ int master_loop(char **argv, char **environ) {
|
||||
// reload gateways and daemons only on normal workflow (+outworld status)
|
||||
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
|
||||
|
||||
if (uwsgi_master_check_emperor_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_emperor_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -885,8 +889,9 @@ next:
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
if (!uwsgi.workers[thewid].cursed_at)
|
||||
uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -905,6 +910,11 @@ next:
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_BRUTAL_RELOAD_CODE) {
|
||||
uwsgi_log("!!! inconsistent state reported by worker %d (pid: %d) !!!\n", thewid, (int) diedpid);
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
@@ -959,3 +969,34 @@ next:
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
void uwsgi_reload_workers() {
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
void uwsgi_chain_reload() {
|
||||
if (!uwsgi.status.chain_reloading) {
|
||||
uwsgi_log_verbose("chain reload starting...\n");
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("chain reload already running...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_brutally_reload_workers() {
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,17 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
int i;
|
||||
int needed_procs = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
|
||||
needed_procs++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.status.chain_reloading > needed_procs) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
}
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
|
||||
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
|
||||
+115
-16
@@ -115,7 +115,43 @@ int uwsgi_calc_cheaper(void) {
|
||||
|
||||
last_check = now;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
int ignore_algo = 0;
|
||||
int needed_workers = 0;
|
||||
|
||||
// first check if memory usage is not exceeded
|
||||
if (uwsgi.cheaper_rss_limit_soft) {
|
||||
unsigned long long total_rss = 0;
|
||||
int i;
|
||||
int active_workers = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (!uwsgi.workers[i].cheaped) {
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && active_workers > 1 && total_rss >= uwsgi.cheaper_rss_limit_hard) {
|
||||
uwsgi_log("cheaper hard rss memory limit exceeded, cheap one of %d workers\n", active_workers);
|
||||
needed_workers = -1;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
else if (total_rss >= uwsgi.cheaper_rss_limit_soft) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cheaper soft rss memory limit exceeded, can't spawn more workers\n");
|
||||
#endif
|
||||
ignore_algo = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// then check for fifo
|
||||
if (uwsgi.cheaper_fifo_delta != 0) {
|
||||
if (!ignore_algo) {
|
||||
needed_workers = uwsgi.cheaper_fifo_delta;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
}
|
||||
|
||||
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
@@ -152,6 +188,11 @@ int uwsgi_calc_cheaper(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fake algo to allow control with the fifo
|
||||
int uwsgi_cheaper_algo_manual(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
|
||||
@@ -326,23 +367,30 @@ void uwsgi_reload(char **argv) {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
if (!uwsgi.master_is_reforked) {
|
||||
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("fork()'ing uWSGI...\n");
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
@@ -529,6 +577,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
|
||||
@@ -1485,3 +1534,53 @@ void uwsgi_add_reload_fds() {
|
||||
add_reload_fds(uwsgi.reload_on_fd, "graceful");
|
||||
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
|
||||
}
|
||||
|
||||
void uwsgi_refork_master() {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("uwsgi_refork_master()/fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
|
||||
return;
|
||||
}
|
||||
|
||||
// detach from the old master
|
||||
setsid();
|
||||
|
||||
uwsgi.master_is_reforked = 1;
|
||||
uwsgi_reload(uwsgi.argv);
|
||||
// never here
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_increase() {
|
||||
uwsgi.cheaper_fifo_delta++;
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_decrease() {
|
||||
uwsgi.cheaper_fifo_delta--;
|
||||
}
|
||||
|
||||
void uwsgi_go_cheap() {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
if (uwsgi.status.is_cheap) return;
|
||||
uwsgi_log_verbose("going cheap...\n");
|
||||
uwsgi.status.is_cheap = 1;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_go_cheap()/waitpid()");
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
|
||||
|
||||
to simplify setups (expecially because the mount command could not be available in
|
||||
the initial phase of jailing, we need an api to mount/umount filesystems
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, int flags);
|
||||
int uwsgi_umount(char *where, int flags);
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
char *key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_BIND
|
||||
{"bind", MS_BIND},
|
||||
#endif
|
||||
#ifdef MS_DIRSYNC
|
||||
{"dirsync", MS_DIRSYNC},
|
||||
#endif
|
||||
#ifdef MS_MANDLOCK
|
||||
{"mandlock", MS_MANDLOCK},
|
||||
#endif
|
||||
#ifdef MS_MOVE
|
||||
{"move", MS_MOVE},
|
||||
#endif
|
||||
#ifdef MS_NOATIME
|
||||
{"noatime", MS_NOATIME},
|
||||
#endif
|
||||
#ifdef MS_NODEV
|
||||
{"nodev", MS_NODEV},
|
||||
#endif
|
||||
#ifdef MS_NOEXEC
|
||||
{"noexec", MS_NOEXEC},
|
||||
#endif
|
||||
#ifdef MS_RDONLY
|
||||
{"rdonly", MS_RDONLY},
|
||||
{"readonly", MS_RDONLY},
|
||||
{"ro", MS_RDONLY},
|
||||
#endif
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
#ifdef MNT_FORCE
|
||||
{"force", MNT_FORCE},
|
||||
#endif
|
||||
#ifdef MNT_DETACH
|
||||
{"detach", MNT_DETACH},
|
||||
#endif
|
||||
#ifdef MS_REC
|
||||
{"rec", MS_REC},
|
||||
{"recursive", MS_REC},
|
||||
#endif
|
||||
#ifdef MS_PRIVATE
|
||||
{"private", MS_PRIVATE},
|
||||
#endif
|
||||
#ifdef MS_SHARED
|
||||
{"shared", MS_SHARED},
|
||||
#endif
|
||||
#ifdef MNT_RDONLY
|
||||
{"rdonly", MNT_RDONLY},
|
||||
{"readonly", MNT_RDONLY},
|
||||
{"ro", MNT_RDONLY},
|
||||
#endif
|
||||
#ifdef MNT_NOEXEC
|
||||
{"noexec", MNT_NOEXEC},
|
||||
#endif
|
||||
#ifdef MNT_NOSUID
|
||||
{"nosuid", MNT_NOSUID},
|
||||
#endif
|
||||
#ifdef MNT_NOATIME
|
||||
{"noatime", MNT_NOATIME},
|
||||
#endif
|
||||
#ifdef MNT_SNAPSHOT
|
||||
{"snapshot", MNT_SNAPSHOT},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
struct uwsgi_mount_flag *umf = umflags;
|
||||
while(umf->key) {
|
||||
if (!strcmp(umf->key, mflag)) return umf->value;
|
||||
umf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
#ifdef __FreeBSD__
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown mount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
#elif defined(__FreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
iov[1].iov_base = fs;
|
||||
iov[1].iov_len = strlen(fs) + 1;
|
||||
|
||||
iov[2].iov_base = "fspath";
|
||||
iov[2].iov_len = 7;
|
||||
iov[3].iov_base = where;
|
||||
iov[3].iov_len = strlen(where) + 1;
|
||||
|
||||
iov[4].iov_base = "target";
|
||||
iov[4].iov_len = 7;
|
||||
iov[5].iov_base = what;
|
||||
iov[5].iov_len = strlen(what) + 1;
|
||||
|
||||
return nmount(iov, 6, (int) mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount(char *where, char *flags) {
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown umount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
// we need a special case for recursive umount
|
||||
if (mountflags & MS_REC) {
|
||||
mountflags &= ~MS_REC;
|
||||
int unmounted = 1;
|
||||
char *slashed = uwsgi_concat2(where, "/");
|
||||
while (unmounted) {
|
||||
unmounted = 0;
|
||||
FILE *procmounts = fopen("/proc/self/mounts", "r");
|
||||
if (!procmounts) {
|
||||
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
char line[1024];
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
char *delim0 = strchr(line, ' ');
|
||||
if (!delim0) continue;
|
||||
delim0++;
|
||||
char *delim1 = strchr(delim0, ' ');
|
||||
if (!delim1) continue;
|
||||
*delim1 = 0;
|
||||
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
|
||||
continue;
|
||||
unmountable:
|
||||
if (!umount2(delim0, mountflags)) unmounted++;
|
||||
}
|
||||
fclose(procmounts);
|
||||
}
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__)
|
||||
return unmount(where, mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_mount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *fs = tmp_arg;
|
||||
char *what = strchr(fs, ' ');
|
||||
if (!what) goto error;
|
||||
*what = 0; what++;
|
||||
char *where = strchr(what, ' ');
|
||||
if (!where) goto error;
|
||||
*where = 0; where++;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
error:
|
||||
free(tmp_arg);
|
||||
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *where = tmp_arg;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_umount(where, flags)) {
|
||||
uwsgi_error("uwsgi_umount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
}
|
||||
+2
-4
@@ -453,8 +453,8 @@ void uwsgi_setup_mules_and_farms() {
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mules_list, ",", p, ctx) {
|
||||
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
|
||||
if (!um) {
|
||||
uwsgi_log("invalid mule id: %s\n", p);
|
||||
@@ -462,8 +462,6 @@ void uwsgi_setup_mules_and_farms() {
|
||||
}
|
||||
|
||||
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
|
||||
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
|
||||
|
||||
|
||||
+15
-1
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
if (!strcmp(p, "requires")) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
if (!plugin_already_loaded(equal+1)) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
@@ -98,6 +100,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 +165,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) {
|
||||
|
||||
+90
-1
@@ -180,6 +180,10 @@ int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_
|
||||
r_goto = &wsgi_req->error_route_goto;
|
||||
r_pc = &wsgi_req->error_route_pc;
|
||||
}
|
||||
else if (routes == uwsgi.response_routes) {
|
||||
r_goto = &wsgi_req->response_route_goto;
|
||||
r_pc = &wsgi_req->response_route_pc;
|
||||
}
|
||||
else if (routes == uwsgi.final_routes) {
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
@@ -306,6 +310,20 @@ int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
|
||||
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
int uwsgi_apply_response_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.response_routes) return 0;
|
||||
if (wsgi_req->response_routes_applied) return 0;
|
||||
|
||||
// do not forget to check it !!!
|
||||
if (wsgi_req->is_response_routing) return 0;
|
||||
|
||||
wsgi_req->is_response_routing = 1;
|
||||
|
||||
int ret = uwsgi_apply_routes_do(uwsgi.response_routes, wsgi_req, NULL, 0);
|
||||
wsgi_req->response_routes_applied = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
@@ -337,6 +355,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
ur = uwsgi.error_routes;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
|
||||
ur = uwsgi.response_routes;
|
||||
}
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
old_ur = ur;
|
||||
@@ -354,6 +375,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
uwsgi.error_routes = ur;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
|
||||
uwsgi.response_routes = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
}
|
||||
@@ -701,6 +725,11 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
}
|
||||
else if (wsgi_req->is_response_routing) {
|
||||
routes = uwsgi.response_routes;
|
||||
r_goto = &wsgi_req->response_route_goto;
|
||||
r_pc = &wsgi_req->response_route_pc;
|
||||
}
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
|
||||
@@ -806,6 +835,31 @@ static int uwsgi_router_remheader(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clearheaders route
|
||||
static int uwsgi_router_clearheaders_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub->buf, ub->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_clearheaders(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_clearheaders_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// signal route
|
||||
@@ -1630,6 +1684,8 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("addheader", uwsgi_router_addheader);
|
||||
uwsgi_register_router("delheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("remheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("clearheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("resetheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("signal", uwsgi_router_signal);
|
||||
uwsgi_register_router("send", uwsgi_router_send);
|
||||
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
|
||||
@@ -1750,6 +1806,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
|
||||
}
|
||||
|
||||
void uwsgi_routing_dump() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (!routes) goto next;
|
||||
uwsgi_log("*** dumping internal routing table ***\n");
|
||||
@@ -1784,8 +1841,25 @@ next:
|
||||
}
|
||||
uwsgi_log("*** end of the internal error routing table ***\n");
|
||||
next2:
|
||||
routes = uwsgi.response_routes;
|
||||
if (!routes) goto next3;
|
||||
uwsgi_log("*** dumping internal response routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal response routing table ***\n");
|
||||
next3:
|
||||
routes = uwsgi.final_routes;
|
||||
if (!routes) return;
|
||||
if (!routes) goto next4;
|
||||
uwsgi_log("*** dumping internal final routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
@@ -1800,5 +1874,20 @@ next2:
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal final routing table ***\n");
|
||||
|
||||
next4:
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid collect header syntax, must be <header> <var>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
usl->custom = strlen(usl->value);
|
||||
*space = ' ';
|
||||
usl->custom_ptr = space+1;
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+9
-6
@@ -4,6 +4,11 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
// sendfile() abstraction
|
||||
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
|
||||
if (uwsgi.disable_sendfile) goto no_sendfile;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sf_len = len;
|
||||
@@ -18,12 +23,11 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#else
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
if (pos > 0) {
|
||||
if (lseek(filefd, pos, SEEK_SET)) {
|
||||
if (lseek(filefd, pos, SEEK_SET) < 0) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/seek()");
|
||||
return -1;
|
||||
}
|
||||
@@ -34,7 +38,6 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
return write(sockfd, buf, rlen);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
+37
-4
@@ -187,6 +187,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
@@ -1645,8 +1653,8 @@ void uwsgi_map_sockets() {
|
||||
}
|
||||
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
|
||||
enabled = 0;
|
||||
char *p = strtok(colon + 1, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
|
||||
int w = atoi(p);
|
||||
if (w < 1 || w > uwsgi.numproc) {
|
||||
uwsgi_log("invalid worker num: %d\n", w);
|
||||
@@ -1657,7 +1665,6 @@ void uwsgi_map_sockets() {
|
||||
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
|
||||
break;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1714,6 +1721,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
|
||||
@@ -1781,7 +1792,8 @@ void uwsgi_bind_sockets() {
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
uwsgi_log("WARNING: unable to remap stdin, /dev/null not available\n");
|
||||
goto stdin_done;
|
||||
}
|
||||
if (fd != 0) {
|
||||
if (dup2(fd, 0) < 0) {
|
||||
@@ -1799,6 +1811,8 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
}
|
||||
|
||||
stdin_done:
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1951,3 +1965,22 @@ void uwsgi_tcp_nodelay(int fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_accept(int server_fd) {
|
||||
struct sockaddr_un client_src;
|
||||
memset(&client_src, 0, sizeof(struct sockaddr_un));
|
||||
socklen_t client_src_len = 0;
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
return accept4(server_fd, (struct sockaddr *) &client_src, &client_src_len, SOCK_NONBLOCK);
|
||||
#elif defined(__linux__)
|
||||
int client_fd = accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd >= 0) {
|
||||
uwsgi_socket_nb(client_fd);
|
||||
}
|
||||
return client_fd;
|
||||
#else
|
||||
return accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,11 @@ SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen,
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
|
||||
#else
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
|
||||
#endif
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return sess;
|
||||
}
|
||||
|
||||
+481
-55
@@ -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;
|
||||
|
||||
@@ -342,6 +344,8 @@ void uwsgi_as_root() {
|
||||
}
|
||||
#endif
|
||||
|
||||
int in_jail = 0;
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
if (uwsgi.unshare && !uwsgi.reloads) {
|
||||
|
||||
@@ -352,9 +356,221 @@ void uwsgi_as_root() {
|
||||
else {
|
||||
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare);
|
||||
}
|
||||
in_jail = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
if (uwsgi.jail && !uwsgi.reloads) {
|
||||
|
||||
struct jail ujail;
|
||||
char *jarg = uwsgi_str(uwsgi.jail);
|
||||
char *j_hostname = NULL;
|
||||
char *j_name = NULL;
|
||||
|
||||
char *space = strchr(jarg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
j_hostname = space + 1;
|
||||
space = strchr(j_hostname, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
j_name = space + 1;
|
||||
}
|
||||
}
|
||||
ujail.version = JAIL_API_VERSION;
|
||||
ujail.path = jarg;
|
||||
ujail.hostname = j_hostname ? j_hostname : "";
|
||||
ujail.jailname = j_name;
|
||||
ujail.ip4s = 0;
|
||||
ujail.ip6s = 0;
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip4) {
|
||||
ujail.ip4s++;
|
||||
}
|
||||
struct in_addr *saddr = uwsgi_calloc(sizeof(struct in_addr) * ujail.ip4s);
|
||||
int i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip4) {
|
||||
if (!inet_pton(AF_INET, usl->value, &saddr[i].s_addr)) {
|
||||
uwsgi_error("jail()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ujail.ip4 = saddr;
|
||||
#ifdef AF_INET6
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip6) {
|
||||
ujail.ip6s++;
|
||||
}
|
||||
|
||||
struct in6_addr *saddr6 = uwsgi_calloc(sizeof(struct in6_addr) * ujail.ip6s);
|
||||
i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip6) {
|
||||
if (!inet_pton(AF_INET6, usl->value, &saddr6[i].s6_addr)) {
|
||||
uwsgi_error("jail()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ujail.ip6 = saddr6;
|
||||
#endif
|
||||
|
||||
int jail_id = jail(&ujail);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jail()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.jidfile) {
|
||||
if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
|
||||
uwsgi_log("unable to write jidfile\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_HAS_FREEBSD_LIBJAIL
|
||||
if (uwsgi.jail_attach && !uwsgi.reloads) {
|
||||
struct jailparam jparam;
|
||||
uwsgi_log("attaching to FreeBSD jail %s ...\n", uwsgi.jail_attach);
|
||||
if (!is_a_number(uwsgi.jail_attach)) {
|
||||
if (jailparam_init(&jparam, "name")) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (jailparam_init(&jparam, "jid")) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
jailparam_import(&jparam, uwsgi.jail_attach);
|
||||
int jail_id = jailparam_set(&jparam, 1, JAIL_UPDATE|JAIL_ATTACH);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jailparam_set()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
jailparam_free(&jparam, 1);
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
|
||||
if (uwsgi.jail2 && !uwsgi.reloads) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
unsigned nparams = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail2) {
|
||||
nparams++;
|
||||
}
|
||||
struct jailparam *params = uwsgi_malloc(sizeof(struct jailparam) * nparams);
|
||||
int i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail2) {
|
||||
uwsgi_log("FreeBSD libjail applying %s\n", usl->value);
|
||||
char *equal = strchr(usl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
}
|
||||
if (jailparam_init(¶ms[i], usl->value)) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
if (equal) {
|
||||
jailparam_import(¶ms[i], equal+1);
|
||||
*equal = '=';
|
||||
}
|
||||
else {
|
||||
jailparam_import(¶ms[i], "1");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int jail_id = jailparam_set(params, nparams, JAIL_CREATE|JAIL_ATTACH);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jailparam_set()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
jailparam_free(params, nparams);
|
||||
|
||||
if (uwsgi.jidfile) {
|
||||
if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
|
||||
uwsgi_log("unable to write jidfile\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (in_jail) {
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_post_jail) {
|
||||
uwsgi_log("mounting \"%s\" (post-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_post_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (post-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.exec_post_jail) {
|
||||
uwsgi_log("running \"%s\" (post-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_post_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.refork_post_jail) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->post_jail) {
|
||||
uwsgi.gp[i]->post_jail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.chroot && !uwsgi.reloads) {
|
||||
if (!uwsgi.master_as_root)
|
||||
@@ -370,18 +586,110 @@ void uwsgi_as_root() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi.pivot_root && !uwsgi.reloads) {
|
||||
char *arg = uwsgi_str(uwsgi.pivot_root);
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid pivot_root syntax, new_root and put_old must be separated by a space\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
if (chdir(arg)) {
|
||||
uwsgi_error("pivot_root()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
space += 1+strlen(arg);
|
||||
if (space[0] == '/') space++;
|
||||
if (pivot_root(".", space)) {
|
||||
uwsgi_error("pivot_root()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
|
||||
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
|
||||
}
|
||||
free(arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.refork_as_root) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_root) {
|
||||
uwsgi_log("mounting \"%s\" (as root)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_root) {
|
||||
uwsgi_log("un-mounting \"%s\" (as root)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 +788,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 +869,45 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_user, "as user", 1);
|
||||
|
||||
// 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);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// we could now patch the binary
|
||||
if (uwsgi.unprivileged_binary_patch) {
|
||||
uwsgi.argv[0] = uwsgi.unprivileged_binary_patch;
|
||||
@@ -1361,6 +1721,11 @@ int uwsgi_file_exists(char *filename) {
|
||||
return !access(filename, R_OK);
|
||||
}
|
||||
|
||||
int uwsgi_file_executable(char *filename) {
|
||||
// TODO check for http url or stdin
|
||||
return !access(filename, R_OK|X_OK);
|
||||
}
|
||||
|
||||
char *magic_sub(char *buffer, size_t len, size_t *size, char *magic_table[]) {
|
||||
|
||||
size_t i;
|
||||
@@ -1514,14 +1879,12 @@ char *uwsgi_get_optname_by_index(int index) {
|
||||
int uwsgi_list_has_num(char *list, int num) {
|
||||
|
||||
char *list2 = uwsgi_concat2(list, "");
|
||||
|
||||
char *p = strtok(list2, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, ",", p, ctx) {
|
||||
if (atoi(p) == num) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -1531,14 +1894,12 @@ int uwsgi_list_has_num(char *list, int num) {
|
||||
int uwsgi_list_has_str(char *list, char *str) {
|
||||
|
||||
char *list2 = uwsgi_str(list);
|
||||
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
if (!strcasecmp(p, str)) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -1921,9 +2282,19 @@ void uwsgi_sig_pause() {
|
||||
sigsuspend(&mask);
|
||||
}
|
||||
|
||||
char *uwsgi_binsh() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.binsh) {
|
||||
if (uwsgi_file_executable(usl->value)) {
|
||||
return usl->value;
|
||||
}
|
||||
}
|
||||
return "/bin/sh";
|
||||
}
|
||||
|
||||
void uwsgi_exec_command_with_args(char *cmdline) {
|
||||
char *argv[4];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = cmdline;
|
||||
argv[3] = NULL;
|
||||
@@ -1932,23 +2303,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)) {
|
||||
@@ -1957,7 +2314,7 @@ int uwsgi_run_command_and_wait(char *command, char *arg) {
|
||||
#endif
|
||||
|
||||
if (command == NULL) {
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = arg;
|
||||
argv[3] = NULL;
|
||||
@@ -1976,6 +2333,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];
|
||||
@@ -2062,12 +2467,12 @@ pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = command;
|
||||
argv[3] = NULL;
|
||||
|
||||
execvp("/bin/sh", argv);
|
||||
execvp(uwsgi_binsh(), argv);
|
||||
|
||||
uwsgi_error("execvp()");
|
||||
//never here
|
||||
@@ -2319,9 +2724,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 +2735,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,17 +2759,15 @@ 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);
|
||||
|
||||
char *p = strtok(list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
int u_id = uwsgi_get_unshare_id(p);
|
||||
if (u_id != -1) {
|
||||
uwsgi.unshare |= u_id;
|
||||
*mask |= u_id;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
@@ -2455,8 +2856,8 @@ void uwsgi_build_cap(char *what) {
|
||||
int pos = 0;
|
||||
uwsgi.cap_count = 0;
|
||||
|
||||
char *p = strtok(caps, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(caps, ",", p, ctx) {
|
||||
if (is_a_number(p)) {
|
||||
uwsgi.cap_count++;
|
||||
}
|
||||
@@ -2466,15 +2867,14 @@ void uwsgi_build_cap(char *what) {
|
||||
uwsgi.cap_count++;
|
||||
}
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(caps);
|
||||
|
||||
uwsgi.cap = uwsgi_malloc(sizeof(cap_value_t) * uwsgi.cap_count);
|
||||
|
||||
caps = uwsgi_str(what);
|
||||
p = strtok(caps, ",");
|
||||
while (p != NULL) {
|
||||
ctx = NULL;
|
||||
uwsgi_foreach_token(caps, ",", p, ctx) {
|
||||
if (is_a_number(p)) {
|
||||
cap_id = atoi(p);
|
||||
}
|
||||
@@ -2486,7 +2886,6 @@ void uwsgi_build_cap(char *what) {
|
||||
uwsgi_log("setting capability %s [%d]\n", p, cap_id);
|
||||
pos++;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(caps);
|
||||
|
||||
@@ -2875,12 +3274,20 @@ char *uwsgi_chomp2(char *str) {
|
||||
|
||||
|
||||
int uwsgi_tmpfd() {
|
||||
int fd = -1;
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
#ifdef O_TMPFILE
|
||||
fd = open(tmpdir, O_TMPFILE | O_RDWR);
|
||||
if (fd >= 0) {
|
||||
return fd;
|
||||
}
|
||||
// fallback to old style
|
||||
#endif
|
||||
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
|
||||
int fd = mkstemp(template);
|
||||
fd = mkstemp(template);
|
||||
unlink(template);
|
||||
free(template);
|
||||
return fd;
|
||||
@@ -2931,15 +3338,21 @@ void uwsgi_emulate_cow_for_apps(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_write_intfile(char *filename, int n) {
|
||||
FILE *pidfile = fopen(filename, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_write_pidfile(char *pidfile_name) {
|
||||
uwsgi_log("writing pidfile to %s\n", pidfile_name);
|
||||
FILE *pidfile = fopen(pidfile_name, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(pidfile_name);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
if (uwsgi_write_intfile(pidfile_name, (int) getpid())) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
}
|
||||
@@ -3304,6 +3717,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 +4156,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);
|
||||
}
|
||||
|
||||
+422
-49
@@ -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,9 +194,13 @@ 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},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
{"vassals-include", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
@@ -204,6 +210,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},
|
||||
|
||||
@@ -220,6 +227,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
|
||||
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"persistent-ipcsem", no_argument, 0, "do not remove ipcsem's on shutdown", uwsgi_opt_true, &uwsgi.persistent_ipcsem, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
@@ -255,7 +263,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"spooler-external", required_argument, 0, "map spoolers requests to a spooler directory managed by an external instance", uwsgi_opt_add_spooler, (void *) UWSGI_SPOOLER_EXTERNAL, UWSGI_OPT_MASTER},
|
||||
{"spooler-ordered", no_argument, 0, "try to order the execution of spooler tasks", uwsgi_opt_true, &uwsgi.spooler_ordered, 0},
|
||||
{"spooler-chdir", required_argument, 0, "chdir() to specified directory before each spooler task", uwsgi_opt_set_str, &uwsgi.spooler_chdir, 0},
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, 0},
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, UWSGI_OPT_IMMEDIATE},
|
||||
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
|
||||
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
|
||||
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SPOOLER_HARAKIRI, 0},
|
||||
@@ -282,8 +290,14 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"pidfile", required_argument, 0, "create pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile, 0},
|
||||
{"pidfile2", required_argument, 0, "create pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile2, 0},
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
#ifdef __linux__
|
||||
{"pivot-root", required_argument, 0, "pivot_root() to the specified directories (new_root and put_old must be separated with a space)", uwsgi_opt_set_str, &uwsgi.pivot_root, 0},
|
||||
{"pivot_root", required_argument, 0, "pivot_root() to the specified directories (new_root and put_old must be separated with a space)", uwsgi_opt_set_str, &uwsgi.pivot_root, 0},
|
||||
#endif
|
||||
|
||||
{"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 +305,41 @@ 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
|
||||
#ifdef __FreeBSD__
|
||||
{"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0},
|
||||
{"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0},
|
||||
{"jail-ip6", required_argument, 0, "add an ipv6 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip6, 0},
|
||||
{"jidfile", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0},
|
||||
{"jid-file", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0},
|
||||
#ifdef UWSGI_HAS_FREEBSD_LIBJAIL
|
||||
{"jail2", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0},
|
||||
{"libjail", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0},
|
||||
{"jail-attach", required_argument, 0, "attach to the FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail_attach, 0},
|
||||
#endif
|
||||
#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},
|
||||
{"refork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0},
|
||||
{"re-fork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0},
|
||||
{"refork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
|
||||
{"re-fork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
|
||||
|
||||
{"hook-asap", required_argument, 0, "run the specified hook as soon as possible", uwsgi_opt_add_string_list, &uwsgi.hook_asap, 0},
|
||||
{"hook-pre-jail", required_argument, 0, "run the specified hook before jailing", uwsgi_opt_add_string_list, &uwsgi.hook_pre_jail, 0},
|
||||
{"hook-post-jail", required_argument, 0, "run the specified hook after jailing", uwsgi_opt_add_string_list, &uwsgi.hook_post_jail, 0},
|
||||
{"hook-in-jail", required_argument, 0, "run the specified hook in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.hook_in_jail, 0},
|
||||
{"hook-as-root", required_argument, 0, "run the specified hook before privileges drop", uwsgi_opt_add_string_list, &uwsgi.hook_as_root, 0},
|
||||
{"hook-as-user", required_argument, 0, "run the specified hook after privileges drop", uwsgi_opt_add_string_list, &uwsgi.hook_as_user, 0},
|
||||
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
|
||||
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
|
||||
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
|
||||
|
||||
{"hook-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
|
||||
{"hook-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
|
||||
|
||||
{"exec-asap", required_argument, 0, "run the specified command as soon as possible", uwsgi_opt_add_string_list, &uwsgi.exec_asap, 0},
|
||||
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
|
||||
{"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0},
|
||||
{"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0},
|
||||
@@ -301,6 +348,61 @@ 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},
|
||||
|
||||
{"mount-asap", required_argument, 0, "mount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.mount_asap, 0},
|
||||
{"mount-pre-jail", required_argument, 0, "mount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.mount_pre_jail, 0},
|
||||
{"mount-post-jail", required_argument, 0, "mount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.mount_post_jail, 0},
|
||||
{"mount-in-jail", required_argument, 0, "mount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.mount_in_jail, 0},
|
||||
{"mount-as-root", required_argument, 0, "mount filesystem before privileges drop", uwsgi_opt_add_string_list, &uwsgi.mount_as_root, 0},
|
||||
|
||||
{"mount-as-vassal", required_argument, 0, "mount filesystem before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.mount_as_vassal, 0},
|
||||
{"mount-as-emperor", required_argument, 0, "mount filesystem in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.mount_as_emperor, 0},
|
||||
|
||||
{"umount-asap", required_argument, 0, "unmount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.umount_asap, 0},
|
||||
{"umount-pre-jail", required_argument, 0, "unmount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.umount_pre_jail, 0},
|
||||
{"umount-post-jail", required_argument, 0, "unmount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.umount_post_jail, 0},
|
||||
{"umount-in-jail", required_argument, 0, "unmount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.umount_in_jail, 0},
|
||||
{"umount-as-root", required_argument, 0, "unmount filesystem before privileges drop", uwsgi_opt_add_string_list, &uwsgi.umount_as_root, 0},
|
||||
|
||||
{"umount-as-vassal", required_argument, 0, "unmount filesystem before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.umount_as_vassal, 0},
|
||||
{"umount-as-emperor", required_argument, 0, "unmount filesystem in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.umount_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-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
|
||||
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
|
||||
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
|
||||
{"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0},
|
||||
{"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},
|
||||
@@ -360,7 +462,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
|
||||
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
|
||||
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal management", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
|
||||
@@ -393,6 +495,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
|
||||
|
||||
{"master-fifo", required_argument, 0, "enable the master fifo", uwsgi_opt_add_string_list, &uwsgi.master_fifo, UWSGI_OPT_MASTER},
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -464,6 +568,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"logger-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
|
||||
{"loggers-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
|
||||
{"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
|
||||
|
||||
{"log-encoder", required_argument, 0, "add an item in the log encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-req-encoder", required_argument, 0, "add an item in the log req encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_req_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-drain", required_argument, 0, "drain (do not show) log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_drain_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-filter", required_argument, 0, "show only log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_filter_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -492,6 +602,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_int, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
@@ -510,6 +622,12 @@ 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},
|
||||
|
||||
{"drop-after-init", no_argument, 0, "run privileges drop after plugin initialization", uwsgi_opt_true, &uwsgi.drop_after_init, 0},
|
||||
{"drop-after-apps", no_argument, 0, "run privileges drop after apps loading", uwsgi_opt_true, &uwsgi.drop_after_apps, 0},
|
||||
|
||||
{"force-cwd", required_argument, 0, "force the initial working directory to the specified value", uwsgi_opt_set_str, &uwsgi.force_cwd, 0},
|
||||
{"binsh", required_argument, 0, "override /bin/sh (used by exec hooks, it always fallback to /bin/sh)", uwsgi_opt_add_string_list, &uwsgi.binsh, 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},
|
||||
@@ -523,6 +641,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cheaper-algo-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-algos-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-rss-limit-soft", required_argument, 0, "don't spawn new workers if total resident memory usage of all workers is higher than this limit", uwsgi_opt_set_64bit, &uwsgi.cheaper_rss_limit_soft, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-rss-limit-hard", required_argument, 0, "if total workers resident memory usage is higher try to stop workers", uwsgi_opt_set_64bit, &uwsgi.cheaper_rss_limit_hard, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, UWSGI_OPT_MASTER},
|
||||
{"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
|
||||
{"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
|
||||
@@ -580,6 +700,20 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"response-route", required_argument, 0, "add a response route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"response-route-status", required_argument, 0, "add a response route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"response-route-host", required_argument, 0, "add a response route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"response-route-uri", required_argument, 0, "add a response route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"response-route-qs", required_argument, 0, "add a response route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"response-route-remote-addr", required_argument, 0, "add a response route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"response-route-user-agent", required_argument, 0, "add a response route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"response-route-remote-user", required_argument, 0, "add a response route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"response-route-referer", required_argument, 0, "add a response route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"response-route-label", required_argument, 0, "add a response routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"response-route-if", required_argument, 0, "add a response route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"response-route-if-not", required_argument, 0, "add a response route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"response-route-run", required_argument, 0, "always run the specified response route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -604,6 +738,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
|
||||
{"rem-header", required_argument, 0, "automatically remove specified HTTP header from the response", uwsgi_opt_add_string_list, &uwsgi.remove_headers, 0},
|
||||
{"del-header", required_argument, 0, "automatically remove specified HTTP header from the response", uwsgi_opt_add_string_list, &uwsgi.remove_headers, 0},
|
||||
{"collect-header", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
{"response-header-collect", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
@@ -615,8 +751,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-safe", required_argument, 0, "skip security checks if the file is under the specified path", uwsgi_opt_add_string_list, &uwsgi.static_safe, UWSGI_OPT_MIME},
|
||||
{"static-cache-paths", required_argument, 0, "put resolved paths in the uWSGI cache for the specified amount of seconds", uwsgi_opt_set_int, &uwsgi.use_static_cache_paths, UWSGI_OPT_MIME|UWSGI_OPT_MASTER},
|
||||
{"static-cache-paths-name", required_argument, 0, "use the specified cache for static paths", uwsgi_opt_set_str, &uwsgi.static_cache_paths_name, UWSGI_OPT_MIME|UWSGI_OPT_MASTER},
|
||||
#ifdef __APPLE__
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/apache2/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/apache2/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
#else
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
#endif
|
||||
|
||||
{"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
|
||||
{"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
|
||||
@@ -646,6 +787,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
|
||||
{"disable-sendfile", no_argument, 0, "disable sendfile() and rely on boring read()/write()", uwsgi_opt_true, &uwsgi.disable_sendfile, 0},
|
||||
|
||||
{"check-cache", optional_argument, 0, "check for response data in the specified cache (empty for default cache)", uwsgi_opt_set_str, &uwsgi.use_check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
|
||||
@@ -688,6 +831,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 +843,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},
|
||||
@@ -733,6 +879,7 @@ void show_config(void) {
|
||||
}
|
||||
|
||||
int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char *value) {
|
||||
int configured;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
@@ -758,11 +905,10 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
p = strtok(tmp_val, " ");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -777,8 +923,8 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
p = strtok(tmp_opt, ";");
|
||||
while (p) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
@@ -809,9 +955,11 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
// we can ignore its return value
|
||||
(void) uwsgi_manage_opt(new_key, new_value);
|
||||
p = strtok(NULL, ";");
|
||||
retry:
|
||||
configured = uwsgi_manage_opt(new_key, new_value);
|
||||
if (!configured && uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(new_key)) goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
clear:
|
||||
@@ -922,11 +1070,15 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
|
||||
int base = '0';
|
||||
char *to_split = uwsgi_str(magic_table['d']);
|
||||
char *p = strtok(to_split, "/");
|
||||
while (p && base <= '9') {
|
||||
magic_table[base] = p;
|
||||
base++;
|
||||
p = strtok(NULL, "/");
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(to_split, "/", p, ctx) {
|
||||
if (base <= '9') {
|
||||
magic_table[base] = p;
|
||||
base++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp)
|
||||
@@ -1079,6 +1231,28 @@ void kill_them_all(int signum) {
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
|
||||
// gracefully destroy
|
||||
void gracefully_kill_them_all(int signum) {
|
||||
|
||||
if (uwsgi_instance_is_dying) return;
|
||||
uwsgi.status.gracefully_destroying = 1;
|
||||
|
||||
// unsubscribe if needed
|
||||
uwsgi_unsubscribe_all();
|
||||
|
||||
uwsgi_log_verbose("graceful shutdown triggered...\n");
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
|
||||
|
||||
// graceful reload
|
||||
void grace_them_all(int signum) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
|
||||
@@ -1103,6 +1277,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 +1350,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 +1435,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 +1452,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);
|
||||
@@ -1308,16 +1490,24 @@ struct uwsgi_plugin unconfigured_plugin = {
|
||||
|
||||
void uwsgi_exec_atexit(void) {
|
||||
if (getpid() == masterpid) {
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_user_atexit, "atexit", 0);
|
||||
// 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 +1549,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 +1563,7 @@ static void vacuum(void) {
|
||||
uwsgi_log("VACUUM: unix socket %s removed.\n", uwsgi_sock->name);
|
||||
}
|
||||
}
|
||||
next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
@@ -1423,14 +1621,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 +1962,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 +2045,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()");
|
||||
@@ -1858,6 +2061,10 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_embedded_routers();
|
||||
#endif
|
||||
|
||||
// call here to allows plugin to override hooks
|
||||
uwsgi_register_base_hooks();
|
||||
uwsgi_log_encoders_register_embedded();
|
||||
|
||||
//initialize embedded plugins
|
||||
UWSGI_LOAD_EMBEDDED_PLUGINS
|
||||
// now a bit of magic, if the executable basename contains a 'uwsgi_' string,
|
||||
@@ -1875,6 +2082,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
uwsgi.magic_table['['] = "\033";
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -1905,6 +2113,32 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
// run "asap" hooks
|
||||
uwsgi_hooks_run(uwsgi.hook_asap, "asap", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_asap) {
|
||||
uwsgi_log("mounting \"%s\" (asap)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.umount_asap) {
|
||||
uwsgi_log("un-mounting \"%s\" (asap)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.exec_asap) {
|
||||
uwsgi_log("running \"%s\" (asap)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.call_asap) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// manage envdirs ASAP
|
||||
uwsgi_envdirs(uwsgi.envdirs);
|
||||
|
||||
@@ -1942,7 +2176,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
|
||||
@@ -1955,6 +2189,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// setup cheaper algos
|
||||
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
|
||||
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
|
||||
uwsgi_register_cheaper_algo("manual", uwsgi_cheaper_algo_manual);
|
||||
|
||||
// setup imperial monitors
|
||||
uwsgi_register_imperial_monitor("dir", uwsgi_imperial_monitor_directory_init, uwsgi_imperial_monitor_directory);
|
||||
@@ -2082,6 +2317,8 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_routing_dump();
|
||||
#else
|
||||
uwsgi_log("!!! no internal routing support, rebuild with pcre support !!!\n");
|
||||
#endif
|
||||
|
||||
// initialize shared sockets
|
||||
@@ -2092,16 +2329,38 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_emperor_start();
|
||||
}
|
||||
|
||||
// run the pre-jail scripts
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_pre_jail;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (pre-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);
|
||||
if (!uwsgi.reloads) {
|
||||
uwsgi_hooks_run(uwsgi.hook_pre_jail, "pre-jail", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_pre_jail) {
|
||||
uwsgi_log("mounting \"%s\" (pre-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_pre_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (pre-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
// run the pre-jail scripts
|
||||
uwsgi_foreach(usl, uwsgi.exec_pre_jail) {
|
||||
uwsgi_log("running \"%s\" (pre-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_pre_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
// we could now patch the binary
|
||||
@@ -2156,9 +2415,44 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_in_jail, "in-jail", 1);
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_in_jail) {
|
||||
uwsgi_log("mounting \"%s\" (in-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_in_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (in-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
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("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi_file_write_do(uwsgi.file_write_list);
|
||||
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket && !uwsgi.drop_after_init && !uwsgi.drop_after_apps) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
@@ -2263,7 +2557,11 @@ int uwsgi_start(void *v_argv) {
|
||||
// build mime.types dictionary
|
||||
if (uwsgi.build_mime_dict) {
|
||||
if (!uwsgi.mime_file)
|
||||
#ifdef __APPLE__
|
||||
uwsgi_string_new_list(&uwsgi.mime_file, "/etc/apache2/mime.types");
|
||||
#else
|
||||
uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
|
||||
#endif
|
||||
struct uwsgi_string_list *umd = uwsgi.mime_file;
|
||||
while (umd) {
|
||||
if (!access(umd->value, R_OK)) {
|
||||
@@ -2306,6 +2604,12 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
// setup locking
|
||||
uwsgi_setup_locking();
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
uwsgi_log("thunder lock: enabled\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("thunder lock: disabled (you can enable it with --thunder-lock)\n");
|
||||
}
|
||||
|
||||
// allocate rpc structures
|
||||
uwsgi_rpc_init();
|
||||
@@ -2398,6 +2702,11 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.drop_after_init) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
|
||||
/* gp/plugin initialization */
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->post_init) {
|
||||
@@ -2465,6 +2774,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 +2913,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;
|
||||
@@ -2632,6 +2946,10 @@ next:
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
|
||||
if (uwsgi.drop_after_apps) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
// postinit apps (setup specific features after app initialization)
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->postinit_apps) {
|
||||
@@ -2820,7 +3138,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 +3176,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);
|
||||
@@ -2934,8 +3280,8 @@ void uwsgi_worker_run() {
|
||||
|
||||
// eventually remap plugins
|
||||
if (uwsgi.remap_modifier) {
|
||||
char *map = strtok(uwsgi.remap_modifier, ",");
|
||||
while (map != NULL) {
|
||||
char *map, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.remap_modifier, ",", map, ctx) {
|
||||
char *colon = strchr(map, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
@@ -2944,7 +3290,6 @@ void uwsgi_worker_run() {
|
||||
uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
|
||||
uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
|
||||
}
|
||||
map = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3155,7 +3500,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) {
|
||||
@@ -3197,6 +3542,8 @@ void uwsgi_init_all_apps() {
|
||||
|
||||
int i, j;
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_pre_app, "pre app", 1);
|
||||
|
||||
// now run the pre-app scripts
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_pre_app;
|
||||
while (usl) {
|
||||
@@ -3209,6 +3556,13 @@ 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);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_apps) {
|
||||
@@ -3257,6 +3611,8 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_post_app, "post app", 1);
|
||||
|
||||
usl = uwsgi.exec_post_app;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
|
||||
@@ -3268,6 +3624,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 +4025,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
|
||||
|
||||
@@ -3702,15 +4063,18 @@ void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
|
||||
char *plugins_list = uwsgi_concat2(value, "");
|
||||
char *p = strtok(plugins_list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_list, ",", p, ctx) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("loading plugin %s\n", p);
|
||||
#endif
|
||||
if (uwsgi_load_plugin(-1, p, NULL)) {
|
||||
build_options();
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
else if (!uwsgi_startswith(opt, "need-", 5)) {
|
||||
uwsgi_log("unable to load plugin \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
free(plugins_list);
|
||||
@@ -4095,7 +4459,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;
|
||||
@@ -4199,3 +4563,12 @@ void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_update_pidfiles() {
|
||||
if (uwsgi.pidfile) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile);
|
||||
}
|
||||
if (uwsgi.pidfile2) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,19 @@ error:
|
||||
|
||||
//each protocol has its header generator
|
||||
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
|
||||
// collect the header ?
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
wsgi_req->write_errors++ ; return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
@@ -171,6 +184,16 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
while(ah) {
|
||||
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
|
||||
@@ -221,6 +244,19 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
*** WORK IN PROGRESS ***
|
||||
|
||||
Zeus mode
|
||||
|
||||
A Zeus instance can load all of the available imperial monitor plugins, but instead of spawning
|
||||
vassals it delegates actions to Emperors connected to it.
|
||||
|
||||
The Zeus instance try to distribute vassals evenly between Emperors.
|
||||
|
||||
Emperors register to one (ore more, maybe...) Zeus instance, passing various informations (like the maximum number
|
||||
of vassals it can manage)
|
||||
|
||||
to spawn a Zeus:
|
||||
|
||||
|
||||
# unencrypted mode
|
||||
uwsgi --zeus "192.168.173.17:4040 /etc/uwsgi/vassals"
|
||||
# crypted mode
|
||||
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key /etc/uwsgi/vassals"
|
||||
# crypted + authentication mode
|
||||
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key,clients.pem /etc/uwsgi/vassals"
|
||||
|
||||
|
||||
to connect an Emperor to Zeus
|
||||
|
||||
# unencrypted mode
|
||||
uwsgi --emperor zeus:192.168.173.17:4040
|
||||
# crypted mode
|
||||
uwsgi --emperor zeus-ssl:192.168.173.17:4040
|
||||
# crypted + authentication mode
|
||||
uwsgi --emperor zeus-ssl:192.168.173.17:4040,myself.key
|
||||
|
||||
|
||||
Protocol
|
||||
|
||||
(each message is a basic uwsgi packet: modifier1 pktsize modifier2 payload)
|
||||
|
||||
modifier2 identifies the type of the message
|
||||
|
||||
0 -> I_AM_ALIVE {node: 'node001', max_vassals: '100', running_vassals: '17'} [ emperor -> zeus ]
|
||||
|
||||
1 -> NEW_VASSAL {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
2 -> ACCEPTED_VASSAL {name: 'foobar.ini'} [ emperor -> zeus ]
|
||||
|
||||
3 -> CONFIG_CHUNK {name: 'foobar.ini', body: '[uwsgi].....'} [ zeus -> the choosen emperor ]
|
||||
|
||||
4 -> CONFIG_END {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
5 -> VASSAL_SPAWNED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
6 -> VASSAL_REJECTED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
7 -> VASSAL_RELOAD {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
8 -> VASSAL_UPDATE {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
9 -> VASSAL_DESTROY {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
10 -> VASSAL_RELOADED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
11 -> VASSAL_DESTROYED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
*/
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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}
|
||||
+15
-1
@@ -66,11 +66,17 @@ void linux_namespace_start(void *argv) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if defined(MS_REC) && defined(MS_PRIVATE)
|
||||
if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
|
||||
@@ -82,6 +88,13 @@ void linux_namespace_start(void *argv) {
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
|
||||
pid = waitpid(pid, &waitpid_status, 0);
|
||||
if (pid < 0) {
|
||||
@@ -167,6 +180,7 @@ void linux_namespace_jail() {
|
||||
uwsgi_log("remounting /proc\n");
|
||||
if (mount("proc", "/proc", "proc", 0, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.ns_keep_mount;
|
||||
|
||||
@@ -71,8 +71,8 @@ static void carbon_post_init() {
|
||||
u_server->healthy = 1;
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p = strtok(usl->value, ":");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(usl->value, ":", p, ctx) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
@@ -81,7 +81,6 @@ static void carbon_post_init() {
|
||||
}
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
|
||||
@@ -828,8 +828,8 @@ clear2:
|
||||
// set the start position of args in argv
|
||||
i = 1;
|
||||
if (helper) i = 2;
|
||||
char *p = strtok(qs, "+");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(qs, "+", p, ctx) {
|
||||
// create a copy for the url_decoded string
|
||||
char *arg_copy = uwsgi_str(p);
|
||||
uint16_t arg_copy_len = strlen(p);
|
||||
@@ -838,7 +838,6 @@ clear2:
|
||||
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
|
||||
+12
-9
@@ -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");
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
|
||||
uWSGI forkpty-router
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
#include "../corerouter/cr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#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
|
||||
|
||||
|
||||
static struct uwsgi_forkptyrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
char *cmd;
|
||||
} ufpty;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct forkptyrouter_session {
|
||||
struct corerouter_session session;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static struct uwsgi_option forkptyrouter_options[] = {
|
||||
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
|
||||
|
||||
{"forkptyrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufpty.cr.fallback, 0},
|
||||
|
||||
{"forkptyrouter-events", required_argument, 0, "set the maximum number of concufptyent events", uwsgi_opt_set_int, &ufpty.cr.nevents, 0},
|
||||
{"forkptyrouter-cheap", no_argument, 0, "run the forkptyrouter in cheap mode", uwsgi_opt_true, &ufpty.cr.cheap, 0},
|
||||
|
||||
{"forkptyrouter-timeout", required_argument, 0, "set forkptyrouter timeout", uwsgi_opt_set_int, &ufpty.cr.socket_timeout, 0},
|
||||
|
||||
{"forkptyrouter-stats", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-stats-server", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-ss", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-harakiri", required_argument, 0, "enable forkptyrouter harakiri", uwsgi_opt_set_int, &ufpty.cr.harakiri, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
// write to backend
|
||||
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_write(peer, "fpty_instance_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
|
||||
// the chunk has been sent, start (again) reading from client and instances
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the buffer
|
||||
peer->out->pos = 0;
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// write to client
|
||||
static ssize_t fpty_write(struct corerouter_peer *main_peer) {
|
||||
ssize_t len = cr_write(main_peer, "fpty_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
|
||||
// ok this response chunk is sent, let's start reading again
|
||||
if (cr_write_complete(main_peer)) {
|
||||
// reset the buffer
|
||||
main_peer->out->pos = 0;
|
||||
cr_reset_hooks(main_peer);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// read from backend
|
||||
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_read(peer, "fpty_instance_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
// set the input buffer as the main output one
|
||||
peer->session->main_peer->out = peer->in;
|
||||
peer->session->main_peer->out_pos = 0;
|
||||
|
||||
cr_write_to_main(peer, fpty_write);
|
||||
return len;
|
||||
}
|
||||
|
||||
// read from client
|
||||
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
|
||||
ssize_t len = cr_read(main_peer, "fpty_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
main_peer->session->peers->out_pos = 0;
|
||||
|
||||
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void fpty_session_close(struct corerouter_session *cs) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
if (fpty_session->pid > 0) {
|
||||
int waitpid_status = 0;
|
||||
if (waitpid(fpty_session->pid, &waitpid_status, WNOHANG) < 0) {
|
||||
uwsgi_error("fpty_session_close()/waitpid()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// allocate a new session
|
||||
static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
|
||||
// set default read hook
|
||||
cs->main_peer->last_hook_read = fpty_read;
|
||||
|
||||
// wait4() on close
|
||||
cs->close = fpty_session_close;
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
|
||||
// add a new peer
|
||||
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
|
||||
|
||||
// on new connection generate a new pty
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, NULL);
|
||||
if (fpty_session->pid < 0) {
|
||||
uwsgi_error("forkpty()");
|
||||
return -1;
|
||||
}
|
||||
else if (fpty_session->pid == 0) {
|
||||
if (ufpty.cmd) {
|
||||
char *space = strchr(ufpty.cmd, ' ');
|
||||
if (space) {
|
||||
char *argv[4];
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = ufpty.cmd;
|
||||
argv[3] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = ufpty.cmd;
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
// never here;
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execve()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ucr->cr_table[peer->fd] = peer;
|
||||
cr_reset_hooks_and_read(peer, fpty_instance_read);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int forkptyrouter_init() {
|
||||
|
||||
ufpty.cr.session_size = sizeof(struct forkptyrouter_session);
|
||||
ufpty.cr.alloc_session = forkptyrouter_alloc_session;
|
||||
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufpty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void forkptyrouter_setup() {
|
||||
ufpty.cr.name = uwsgi_str("uWSGI forkptyrouter");
|
||||
ufpty.cr.short_name = uwsgi_str("forkptyrouter");
|
||||
}
|
||||
|
||||
struct uwsgi_plugin forkptyrouter_plugin = {
|
||||
|
||||
.name = "forkptyrouter",
|
||||
.options = forkptyrouter_options,
|
||||
.init = forkptyrouter_init,
|
||||
.on_load = forkptyrouter_setup
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='forkptyrouter'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
REQUIRES = ['corerouter']
|
||||
|
||||
GCC_LIST = ['forkptyrouter']
|
||||
@@ -123,10 +123,9 @@ static void uwsgi_gccgo_initialize() {
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
argc++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
free(argv_list);
|
||||
}
|
||||
@@ -134,12 +133,11 @@ static void uwsgi_gccgo_initialize() {
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
char *p, *ctx = NULL;
|
||||
int n = 0;
|
||||
while(p) {
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
argv[n] = p;
|
||||
n++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
runtime_args(argc, argv);
|
||||
}
|
||||
|
||||
+77
-23
@@ -19,14 +19,40 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
static struct uwsgi_option gevent_options[] = {
|
||||
{"gevent", required_argument, 0, "a shortcut enabling gevent loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_gevent, NULL, UWSGI_OPT_THREADS},
|
||||
{"gevent-monkey-patch", no_argument, 0, "call gevent.monkey.patch_all() automatically on startup", uwsgi_opt_true, &ugevent.monkey, 0},
|
||||
{"gevent-wait-for-hub", no_argument, 0, "wait for gevent hub's death instead of the control greenlet", uwsgi_opt_true, &ugevent.wait_for_hub, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Dumb greenlet used for controlling the shutdown (originally uWSGI only wait for the hub)
|
||||
*/
|
||||
PyObject *py_uwsgi_gevent_ctrl_gl(PyObject *self, PyObject *args) {
|
||||
for(;;) {
|
||||
PyObject *gevent_sleep_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(gevent_sleep_args, 0, PyInt_FromLong(60));
|
||||
PyObject *gswitch = PyEval_CallObject(ugevent.greenlet_switch, gevent_sleep_args);
|
||||
// could be NULL on exception
|
||||
if (!gswitch) {
|
||||
// just for being paranid
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(gswitch);
|
||||
Py_DECREF(gevent_sleep_args);
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) {
|
||||
|
||||
int running_cores = 0;
|
||||
int rounds = 0;
|
||||
|
||||
uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
|
||||
@@ -41,29 +67,34 @@ PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) {
|
||||
}
|
||||
uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
|
||||
int running_cores = 0;
|
||||
retry:
|
||||
running_cores = 0;
|
||||
for(i=0;i<uwsgi.async;i++) {
|
||||
if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) {
|
||||
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i,
|
||||
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
if (!rounds) {
|
||||
uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i,
|
||||
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
}
|
||||
running_cores++;
|
||||
}
|
||||
}
|
||||
|
||||
if (running_cores > 0) {
|
||||
uwsgi_log_verbose("waiting for %d running requests on worker %d (pid: %d)...\n", running_cores, uwsgi.mywid, uwsgi.mypid);
|
||||
} else {
|
||||
// no need to worry about freeing memory
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
|
||||
if (ae) {
|
||||
python_call(ae, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
PyObject *gevent_sleep_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(gevent_sleep_args, 0, PyInt_FromLong(1));
|
||||
PyObject *gswitch = python_call(ugevent.greenlet_switch, gevent_sleep_args, 0, NULL);
|
||||
Py_DECREF(gswitch);
|
||||
Py_DECREF(gevent_sleep_args);
|
||||
rounds++;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -164,14 +195,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 +206,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));
|
||||
|
||||
@@ -300,6 +331,7 @@ PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_geven
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_ctrl_gl_def[] = { {"uwsgi_gevent_ctrl_gl_handler", py_uwsgi_gevent_ctrl_gl, METH_VARARGS, ""} };
|
||||
|
||||
static void gil_gevent_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
@@ -450,8 +482,21 @@ static void gevent_loop() {
|
||||
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
PyObject *wait_for_me = ugevent.hub;
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
// spawn the control greenlet
|
||||
PyObject *uwsgi_greenlet_ctrl_gl_handler = PyCFunction_New(uwsgi_gevent_ctrl_gl_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_ctrl_gl_handler);
|
||||
PyObject *ctrl_gl_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(ctrl_gl_args, 0, uwsgi_greenlet_ctrl_gl_handler);
|
||||
ugevent.ctrl_gl = python_call(ugevent.spawn, ctrl_gl_args, 0, NULL);
|
||||
Py_INCREF(ugevent.ctrl_gl);
|
||||
wait_for_me = ugevent.ctrl_gl;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
|
||||
if (!PyObject_CallMethod(wait_for_me, "join", NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
@@ -459,6 +504,15 @@ static void gevent_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// no need to worry about freeing memory
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
|
||||
if (ae) {
|
||||
python_call(ae, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
|
||||
uwsgi_log("goodbye to the gevent Hub on worker %d (pid: %d)\n", uwsgi.mywid, uwsgi.mypid);
|
||||
if (ugevent.destroy) {
|
||||
|
||||
@@ -51,7 +51,9 @@ struct uwsgi_gevent {
|
||||
PyObject *my_signal_watcher;
|
||||
PyObject *signal_watcher;
|
||||
PyObject **watchers;
|
||||
PyObject *ctrl_gl;
|
||||
int destroy;
|
||||
int monkey;
|
||||
int wait_for_hub;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
#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, *ctx = NULL;
|
||||
uwsgi_foreach_token(servers, ";", p, ctx) {
|
||||
uwsgi_log("[glusterfs] try connect to %s for mountpoint %.*s on worker %d ...\n", p, ua->mountpoint_len, ua->mountpoint, uwsgi.mywid);
|
||||
if (uwsgi_glusterfs_try(ua, p)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
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,
|
||||
};
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
+4
-6
@@ -181,10 +181,9 @@ static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -228,10 +227,9 @@ static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <uwsgi.h>
|
||||
#include <libtcc.h>
|
||||
|
||||
uint64_t uwsgi_libtcc_counter = 0;
|
||||
|
||||
static int uwsgi_libtcc_hook(char *arg) {
|
||||
char *func_base = "uwsgi_libtcc_func";
|
||||
size_t func_len = strlen(func_base) + sizeof(UMAX64_STR);
|
||||
char *func_name = uwsgi_malloc(func_len);
|
||||
if (snprintf(func_name, func_len, "%s%llu", func_base, uwsgi_libtcc_counter) < (int) strlen(func_base)) {
|
||||
free(func_name);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_libtcc_counter++;
|
||||
size_t source_len = 64 + func_len + strlen(arg);
|
||||
char *source = uwsgi_malloc(source_len);
|
||||
if (snprintf(source, source_len, "void %s() { %s ;}", func_name, arg) < (int) ( strlen(func_base) + strlen(arg))) {
|
||||
free(func_name);
|
||||
free(source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
TCCState *s = tcc_new();
|
||||
|
||||
if (tcc_compile_string(s, source)) goto error;
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO)) goto error;
|
||||
|
||||
void (*func)() = tcc_get_symbol(s, func_name);
|
||||
if (!func) goto error;
|
||||
free(func_name);
|
||||
free(source);
|
||||
|
||||
// call the function
|
||||
func();
|
||||
|
||||
tcc_delete(s);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(func_name);
|
||||
free(source);
|
||||
tcc_delete(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_libtcc_setup() {
|
||||
uwsgi_register_hook("tcc", uwsgi_libtcc_hook);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin libtcc_plugin = {
|
||||
.name = "libtcc",
|
||||
.on_load = uwsgi_libtcc_setup,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='libtcc'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=['-ltcc']
|
||||
GCC_LIST=['libtcc']
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
@@ -18,8 +18,24 @@ ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_fd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
ul->fd = -1;
|
||||
if (ul->arg) ul->fd = atoi(ul->arg);
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
if (ul->fd >= 0) {
|
||||
return write(ul->fd, message, len);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_file_logger_register() {
|
||||
uwsgi_register_logger("file", uwsgi_file_logger);
|
||||
uwsgi_register_logger("fd", uwsgi_fd_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logfile_plugin = {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
The pipe logger
|
||||
|
||||
Author: INADA Naoki
|
||||
|
||||
every log line is sent to the stdin of an external process
|
||||
|
||||
Example:
|
||||
|
||||
req-logger = pipe:/usr/local/bin/mylogger
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_pipe_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
int pipefd[2];
|
||||
// retry later...
|
||||
if (pipe(pipefd) < 0) return -1;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) return -1;
|
||||
if (pid > 0) {
|
||||
close(pipefd[0]);
|
||||
ul->fd = pipefd[1];
|
||||
}
|
||||
else {
|
||||
// child
|
||||
setsid();
|
||||
close(pipefd[1]);
|
||||
dup2(pipefd[0], STDIN_FILENO);
|
||||
close(pipefd[0]);
|
||||
uwsgi_exec_command_with_args(ul->arg);
|
||||
exit(1); // if here something seriously failed
|
||||
}
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
int err = write(ul->fd, message, len);
|
||||
// on failed writes, re-configure the logger
|
||||
if (err <= 0) {
|
||||
close(ul->fd);
|
||||
ul->configured = 0;
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_pipe_logger_register() {
|
||||
uwsgi_register_logger("pipe", uwsgi_pipe_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logpipe_plugin = {
|
||||
.name = "logpipe",
|
||||
.on_load = uwsgi_pipe_logger_register,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logpipe'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logpipe']
|
||||
@@ -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},
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
msgpack utilities
|
||||
|
||||
*/
|
||||
|
||||
enum {
|
||||
MSGPACK_NIL = 0,
|
||||
MSGPACK_TRUE,
|
||||
MSGPACK_FALSE,
|
||||
MSGPACK_INT,
|
||||
MSGPACK_FLOAT,
|
||||
MSGPACK_STR,
|
||||
MSGPACK_BIN,
|
||||
MSGPACK_ARRAY,
|
||||
MSGPACK_MAP,
|
||||
MSGPACK_EXT,
|
||||
MSGPACK_MAGIC,
|
||||
};
|
||||
|
||||
struct uwsgi_msgpack_item {
|
||||
uint8_t type;
|
||||
char *str;
|
||||
uint32_t str_len;
|
||||
int64_t num;
|
||||
double fnum;
|
||||
int (*func)(char *);
|
||||
struct uwsgi_msgpack_item *next;
|
||||
};
|
||||
|
||||
struct uwsgi_msgpack_item *uwsgi_msgpack_item_add(struct uwsgi_msgpack_item **list, uint8_t type) {
|
||||
struct uwsgi_msgpack_item *old_umi = NULL, *umi = *list;
|
||||
while(umi) {
|
||||
old_umi = umi;
|
||||
umi = umi->next;
|
||||
}
|
||||
|
||||
umi = uwsgi_calloc(sizeof(struct uwsgi_msgpack_item));
|
||||
umi->type = type;
|
||||
if (old_umi) {
|
||||
old_umi->next = umi;
|
||||
}
|
||||
else {
|
||||
*list = umi;
|
||||
}
|
||||
return umi;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_map(struct uwsgi_buffer *ub, uint32_t len) {
|
||||
if (len <= 15) {
|
||||
return uwsgi_buffer_byte(ub, 0x80 + len);
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDE)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) len);
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_byte(ub, 0xDF)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_array(struct uwsgi_buffer *ub, uint32_t len) {
|
||||
if (len <= 15) {
|
||||
return uwsgi_buffer_byte(ub, 0x90 + len);
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDC)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) len);
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_byte(ub, 0xDD)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_str(struct uwsgi_buffer *ub, char *str, uint32_t len) {
|
||||
if (len <= 31) {
|
||||
if (uwsgi_buffer_byte(ub, 0xA0 + len)) return -1;
|
||||
}
|
||||
// this is annoying, D9 does not work for older SPEC :(
|
||||
/*
|
||||
else if (len <= 0xff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD9)) return -1;
|
||||
if (uwsgi_buffer_byte(ub, (uint8_t) len)) return -1;
|
||||
}
|
||||
*/
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDA)) return -1;
|
||||
if (uwsgi_buffer_u16be(ub, (uint16_t) len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_byte(ub, 0xDB)) return -1;
|
||||
if (uwsgi_buffer_u32be(ub, len)) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_buffer_append(ub, str, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_bin(struct uwsgi_buffer *ub, char *str, uint32_t len) {
|
||||
if (len <= 0xff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xC4)) return -1;
|
||||
if (uwsgi_buffer_byte(ub, (uint8_t) len)) return -1;
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xC5)) return -1;
|
||||
if (uwsgi_buffer_u16be(ub, (uint16_t) len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_byte(ub, 0xC6)) return -1;
|
||||
if (uwsgi_buffer_u32be(ub, len)) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_buffer_append(ub, str, len);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_msgpack_int(struct uwsgi_buffer *ub, int64_t num) {
|
||||
if (num > 0 && num <= 127) {
|
||||
return uwsgi_buffer_byte(ub, (uint8_t) num);
|
||||
}
|
||||
else if (num < 0 && num >= 31) {
|
||||
return uwsgi_buffer_byte(ub, 224 | (int8_t) num);
|
||||
}
|
||||
else if (num <= 127 && num >= -127) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD0)) return -1;
|
||||
return uwsgi_buffer_byte(ub, (int8_t) num);
|
||||
}
|
||||
else if (num <= 32767 && num >= -32767) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD1)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) num);
|
||||
}
|
||||
else if (num <= 2147483647LL && num >= -2147483648LL) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD2)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, (uint32_t) num);
|
||||
}
|
||||
if (uwsgi_buffer_byte(ub, 0xD3)) return -1;
|
||||
return uwsgi_buffer_u64be(ub, (uint64_t)num);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_float(struct uwsgi_buffer *ub, double num) {
|
||||
if (num >= -126.0 && num <= 127.0) {
|
||||
if (uwsgi_buffer_byte(ub, 0xCA)) return -1;
|
||||
return uwsgi_buffer_f32be(ub, (float) num);
|
||||
}
|
||||
if (uwsgi_buffer_byte(ub, 0xCB)) return -1;
|
||||
return uwsgi_buffer_f64be(ub, num);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_nil(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC0);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_true(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC3);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_false(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC2);
|
||||
}
|
||||
|
||||
static char *uwsgi_msgpack_log_encoder(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
if (!ule->configured) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(ule->args, "|", p, ctx) {
|
||||
char *colon = strchr(p, ':');
|
||||
if (colon) *colon = 0;
|
||||
// find the type of item
|
||||
if (!strcmp(p, "map")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAP);
|
||||
if (colon) {
|
||||
new_umi->num = strtoull(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "array")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_ARRAY);
|
||||
if (colon) {
|
||||
new_umi->num = strtoull(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "nil")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_NIL);
|
||||
}
|
||||
else if (!strcmp(p, "true")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_TRUE);
|
||||
}
|
||||
else if (!strcmp(p, "false")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_FALSE);
|
||||
}
|
||||
else if (!strcmp(p, "int")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_INT);
|
||||
if (colon) {
|
||||
new_umi->num = strtoll(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "float")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_FLOAT);
|
||||
if (colon) {
|
||||
new_umi->fnum = strtod(colon+1, NULL);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "str")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_STR);
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "bin")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_BIN);
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "msg")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
}
|
||||
else if (!strcmp(p, "msgbin")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 1;
|
||||
}
|
||||
|
||||
else if (!strcmp(p, "msgnl")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 2;
|
||||
}
|
||||
else if (!strcmp(p, "msgbinnl")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 3;
|
||||
}
|
||||
else if (!strcmp(p, "unix")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 4;
|
||||
}
|
||||
else if (!strcmp(p, "micros")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 5;
|
||||
}
|
||||
else if (!strcmp(p, "strftime")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 6;
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (colon) *colon = ':';
|
||||
}
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
struct uwsgi_msgpack_item *umi = (struct uwsgi_msgpack_item*) ule->data;
|
||||
uint32_t tmp_len = 0;
|
||||
while(umi) {
|
||||
switch(umi->type) {
|
||||
case(MSGPACK_NIL):
|
||||
if (uwsgi_buffer_msgpack_nil(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_TRUE):
|
||||
if (uwsgi_buffer_msgpack_true(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_FALSE):
|
||||
if (uwsgi_buffer_msgpack_false(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_STR):
|
||||
if (uwsgi_buffer_msgpack_str(ub, umi->str, umi->str_len)) goto end;
|
||||
break;
|
||||
case(MSGPACK_BIN):
|
||||
if (uwsgi_buffer_msgpack_bin(ub, umi->str, umi->str_len)) goto end;
|
||||
break;
|
||||
case(MSGPACK_MAP):
|
||||
if (uwsgi_buffer_msgpack_map(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_ARRAY):
|
||||
if (uwsgi_buffer_msgpack_array(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_INT):
|
||||
if (uwsgi_buffer_msgpack_int(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_FLOAT):
|
||||
if (uwsgi_buffer_msgpack_float(ub, umi->fnum)) goto end;
|
||||
break;
|
||||
case(MSGPACK_MAGIC):
|
||||
// msg
|
||||
tmp_len = len;
|
||||
if (umi->num == 0) {
|
||||
if (msg[len-1] == '\n') tmp_len--;
|
||||
if (uwsgi_buffer_msgpack_str(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgbin
|
||||
else if (umi->num == 1) {
|
||||
if (msg[len-1] == '\n') tmp_len--;
|
||||
if (uwsgi_buffer_msgpack_bin(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgnl
|
||||
if (umi->num == 2) {
|
||||
if (uwsgi_buffer_msgpack_str(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgbinnl
|
||||
else if (umi->num == 3) {
|
||||
if (uwsgi_buffer_msgpack_bin(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// unix
|
||||
else if (umi->num == 4) {
|
||||
if (uwsgi_buffer_msgpack_int(ub, (int64_t)uwsgi_now())) goto end;
|
||||
}
|
||||
// micros
|
||||
else if (umi->num == 5) {
|
||||
if (uwsgi_buffer_msgpack_int(ub, (int64_t)uwsgi_micros())) goto end;
|
||||
}
|
||||
// strftime
|
||||
else if (umi->num == 6) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
int rlen = strftime(sftime, 64, umi->str, localtime(&now));
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_buffer_msgpack_str(ub, sftime, rlen)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_msgpack_str(ub, "", 0)) goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
umi = umi->next;
|
||||
}
|
||||
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void uwsgi_msgpack_register() {
|
||||
uwsgi_register_log_encoder("msgpack", uwsgi_msgpack_log_encoder);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin msgpack_plugin = {
|
||||
.name = "msgpack",
|
||||
.on_load = uwsgi_msgpack_register,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='msgpack'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=[]
|
||||
GCC_LIST = ['msgpack']
|
||||
@@ -5,25 +5,24 @@ NAME='php'
|
||||
ld_run_path = None
|
||||
PHPPATH = 'php-config'
|
||||
|
||||
try:
|
||||
phpdir = os.environ['UWSGICONFIG_PHPDIR']
|
||||
phpdir = os.environ.get('UWSGICONFIG_PHPDIR')
|
||||
if phpdir:
|
||||
ld_run_path = "%s/lib" % phpdir
|
||||
PHPPATH = "%s/bin/php-config" % phpdir
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
|
||||
except:
|
||||
pass
|
||||
PHPPATH = os.environ.get('UWSGICONFIG_PHPPATH', PHPPATH)
|
||||
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
|
||||
|
||||
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
|
||||
|
||||
if ld_run_path:
|
||||
LDFLAGS.append('-L%s' % ld_run_path)
|
||||
os.environ['LD_RUN_PATH'] = ld_run_path
|
||||
|
||||
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
|
||||
|
||||
phplibdir = os.environ.get('UWSGICONFIG_PHPLIBDIR')
|
||||
if phplibdir:
|
||||
LIBS.append('-Wl,-rpath=%s' % phplibdir)
|
||||
|
||||
GCC_LIST = ['php_plugin']
|
||||
|
||||
+5
-1
@@ -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 *);
|
||||
|
||||
@@ -383,10 +383,9 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
AV *uperl_argv = GvAV(PL_argvgv);
|
||||
if (uperl.argv_items) {
|
||||
char *argv_list = uwsgi_str(uperl.argv_items);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
av_push(uperl_argv, newSVpv(p, 0));
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
struct uwsgi_string_list *usl = uperl.argv_item;
|
||||
@@ -483,6 +482,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 +511,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
#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", required_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
// block signals on this thread
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
#ifndef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
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,
|
||||
};
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -262,8 +320,9 @@ void init_pyargv() {
|
||||
char *tmp_ptr = uwsgi_str(up.argv);
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(tmp_ptr, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
char *ctx = NULL;
|
||||
ap = strtok_r(tmp_ptr, " ", &ctx);
|
||||
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
|
||||
#endif
|
||||
@@ -294,8 +353,9 @@ void init_pyargv() {
|
||||
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(py_argv_copy, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
char *ctx = NULL;
|
||||
ap = strtok_r(py_argv_copy, " ", &ctx);
|
||||
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
|
||||
#endif
|
||||
|
||||
@@ -394,6 +394,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(func);
|
||||
|
||||
if (uwsgi_register_rpc(name, &python_plugin, argc, func)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
|
||||
@@ -498,6 +499,8 @@ PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(handler);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, handler, 0)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to register signal");
|
||||
}
|
||||
@@ -1805,6 +1808,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 +1900,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 +3112,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 +3153,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},
|
||||
};
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -790,6 +818,18 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_apps[wsgi_req->app_id].requests++;
|
||||
|
||||
env = rb_hash_new();
|
||||
// the following vars have to always been defined (we skip REQUEST_METHOD and PATH_INFO as they should always be available)
|
||||
rb_hash_aset(env, rb_str_new2("SCRIPT_NAME"), rb_str_new2(""));
|
||||
rb_hash_aset(env, rb_str_new2("QUERY_STRING"), rb_str_new2(""));
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_NAME"), rb_str_new2(uwsgi.hostname));
|
||||
// SERVER_PORT
|
||||
char *server_port = strchr(wsgi_req->socket->name, ':');
|
||||
if (server_port) {
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_PORT"), rb_str_new(server_port+1, strlen(server_port+1)));
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_PORT"), rb_str_new2("80"));
|
||||
}
|
||||
|
||||
// fill ruby hash
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
|
||||
@@ -54,6 +54,7 @@ struct uwsgi_rack {
|
||||
|
||||
char *gemset;
|
||||
|
||||
struct uwsgi_string_list *libdir;
|
||||
};
|
||||
|
||||
void uwsgi_rack_init_api(void);
|
||||
|
||||
@@ -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()))
|
||||
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
#include <uwsgi.h>
|
||||
#include <rados/librados.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Author: Javier Guerra
|
||||
|
||||
based on the uWSGI GlusterFS plugin by Roberto De Ioris
|
||||
|
||||
--rados-mount mountpoint=/foo,pool=unbit001,config=/etc/ceph.conf
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_plugin rados_plugin;
|
||||
|
||||
struct uwsgi_rados {
|
||||
int timeout;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} urados;
|
||||
|
||||
static struct uwsgi_option uwsgi_rados_options[] = {
|
||||
{"rados-mount", required_argument, 0, "virtual mount the specified rados volume in a uri", uwsgi_opt_add_string_list, &urados.mountpoints, UWSGI_OPT_MIME},
|
||||
{"rados-timeout", required_argument, 0, "timeout for async operations", uwsgi_opt_set_int, &urados.timeout, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int uwsgi_rados_read_sync(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
while(remains > 0) {
|
||||
char buf[8192];
|
||||
int rlen = rados_read(ctx, key, buf, UMIN(remains, 8192), off);
|
||||
if (rlen <= 0) return -1;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) return -1;
|
||||
remains -= rlen;
|
||||
off += rlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
async read of a resource
|
||||
the uwsgi_rados_async_io structure is passed between threads
|
||||
the callback simply signal the main core about the availability of data
|
||||
*/
|
||||
struct uwsgi_rados_async_io {
|
||||
int fd[2];
|
||||
ssize_t rlen;
|
||||
};
|
||||
|
||||
static void uwsgi_rados_read_async_cb(rados_completion_t comp, void *data) {
|
||||
struct uwsgi_rados_async_io *aio = (struct uwsgi_rados_async_io *) data;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[rados-cb] rlen = %d\n", rlen);
|
||||
#endif
|
||||
aio->rlen = rados_aio_get_return_value(comp);
|
||||
// signal the core
|
||||
if (write(aio->fd[1], "\1", 1) <= 0) {
|
||||
uwsgi_error("uwsgi_rados_read_async_cb()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_rados_read_async(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
char buf[8192];
|
||||
struct uwsgi_rados_async_io aio;
|
||||
int ret = -1;
|
||||
if (pipe(aio.fd)) {
|
||||
uwsgi_error("uwsgi_rados_read_async()/pipe()");
|
||||
return -1;
|
||||
}
|
||||
aio.rlen = -1;
|
||||
rados_completion_t comp;
|
||||
if (rados_aio_create_completion(&aio, uwsgi_rados_read_async_cb, NULL, &comp) < 0) goto end;
|
||||
|
||||
while(remains > 0) {
|
||||
// trigger an async read
|
||||
if (rados_aio_read(ctx, key, comp, buf, 8192, off) < 0) goto end;
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(aio.fd[0], urados.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:
|
||||
rados_aio_release(&comp);
|
||||
close(aio.fd[0]);
|
||||
close(aio.fd[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
|
||||
char *rad_mountpoint = NULL;
|
||||
char *rad_config = NULL;
|
||||
char *rad_poolname = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &rad_mountpoint,
|
||||
"config", &rad_config,
|
||||
"pool", &rad_poolname,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse rados mountpoint definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!rad_mountpoint|| !rad_poolname) {
|
||||
uwsgi_log("[rados] mount requires a mountpoint, and a pool name.\n");
|
||||
exit(1);
|
||||
}
|
||||
time_t now = uwsgi_now();
|
||||
uwsgi_log("[rados] mounting %s ...\n", rad_mountpoint);
|
||||
|
||||
rados_t cluster;
|
||||
if (rados_create(&cluster, NULL) < 0) {
|
||||
uwsgi_error("Can't create Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
if (rad_config)
|
||||
uwsgi_log("Using Ceph conf:%s\n", rad_config);
|
||||
else
|
||||
uwsgi_log("Using default Ceph conf.\n");
|
||||
if (rados_conf_read_file(cluster, rad_config) < 0) {
|
||||
uwsgi_error("Can't configure Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
if (rados_connect(cluster) < 0) {
|
||||
uwsgi_error("Can't connect with Ceph cluster");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rados_ioctx_t ctx;
|
||||
uwsgi_log("Ceph pool: %s\n", rad_poolname);
|
||||
if (rados_ioctx_create(cluster, rad_poolname, &ctx) < 0) {
|
||||
uwsgi_error("Can't open rados pool")
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, rados_plugin.modifier1, rad_mountpoint, strlen(rad_mountpoint), NULL, NULL);
|
||||
if (!ua) {
|
||||
uwsgi_log("[rados] unable to mount %s\n", rad_mountpoint);
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ua->responder0 = cluster;
|
||||
ua->responder1 = ctx;
|
||||
ua->started_at = now;
|
||||
ua->startup_time = uwsgi_now() - now;
|
||||
uwsgi_log("Rados app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, rad_mountpoint, (int) ua->startup_time, ctx);
|
||||
}
|
||||
|
||||
// we translate the string list to an app representation
|
||||
// this happens before fork() if not in lazy/lazy-apps mode
|
||||
static void uwsgi_rados_setup() {
|
||||
if (!urados.timeout) {
|
||||
urados.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = urados.mountpoints;
|
||||
while(usl) {
|
||||
uwsgi_rados_add_mountpoint(usl->value, usl->len);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
char filename[PATH_MAX+1];
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty 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, rados_plugin.modifier1);
|
||||
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
||||
if (uwsgi_apps[uwsgi.default_app].modifier1 == rados_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];
|
||||
|
||||
if (wsgi_req->path_info_len > ua->mountpoint_len &&
|
||||
memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0)
|
||||
{
|
||||
memcpy(filename, wsgi_req->path_info+ua->mountpoint_len, wsgi_req->path_info_len-ua->mountpoint_len);
|
||||
} else {
|
||||
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
filename[wsgi_req->path_info_len] = 0;
|
||||
|
||||
struct {
|
||||
uint64_t size;
|
||||
time_t mtime;
|
||||
} st;
|
||||
rados_ioctx_t ctx = ua->responder1;
|
||||
|
||||
int r = rados_stat(ctx, filename, &st.size, &st.mtime);
|
||||
if (r < 0) {
|
||||
if (r == -ENOENT)
|
||||
uwsgi_404(wsgi_req);
|
||||
else
|
||||
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.mtime)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.size)) goto end;
|
||||
|
||||
// skip body on HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
size_t remains = st.size;
|
||||
if (uwsgi.async > 1) {
|
||||
if (uwsgi_rados_read_async(wsgi_req, ctx, filename, remains)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_rados_read_sync(wsgi_req, ctx, filename, remains)) goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin rados_plugin = {
|
||||
.name = "rados",
|
||||
.modifier1 = 28,
|
||||
.options = uwsgi_rados_options,
|
||||
.post_fork = uwsgi_rados_setup,
|
||||
.request = uwsgi_rados_request,
|
||||
.after_request = log_request,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
NAME='rados'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lrados']
|
||||
GCC_LIST = ['rados']
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user