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