mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-05 08:28:28 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46d7d4bf1d | ||
|
|
02d76f12e0 | ||
|
|
719860a349 | ||
|
|
5cce0935fd | ||
|
|
24ef2a838f | ||
|
|
8aa739b4b2 | ||
|
|
9221e1953e | ||
|
|
18592fb2bd | ||
|
|
fc80eeb581 | ||
|
|
bc19b58681 | ||
|
|
8f2202eab5 | ||
|
|
aa2ecf14df | ||
|
|
43f5792826 | ||
|
|
36ff37e12c | ||
|
|
6dd6f961e8 | ||
|
|
5dd5d92ffb | ||
|
|
64f1b844bd | ||
|
|
e562c4691d | ||
|
|
1cbab74f0e | ||
|
|
3053fdb25a | ||
|
|
f11f542242 | ||
|
|
32ddf10cfa | ||
|
|
1b54be396c | ||
|
|
f81a4f9736 | ||
|
|
048b339593 | ||
|
|
081a6b90bf | ||
|
|
97f1b6d649 |
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
|
||||
apxs2 -i -c mod_proxy_uwsgi.c
|
||||
|
||||
*/
|
||||
#define APR_WANT_MEMFUNC
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_strings.h"
|
||||
@@ -101,6 +106,14 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
|
||||
ap_add_common_vars(r);
|
||||
ap_add_cgi_vars(r);
|
||||
|
||||
// this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
|
||||
// and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
|
||||
// files you have higher problems...
|
||||
const char *auth = apr_table_get(r->headers_in, "Authorization");
|
||||
if (auth) {
|
||||
apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
|
||||
}
|
||||
|
||||
const char *script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
|
||||
const char *path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
|
||||
|
||||
@@ -336,8 +349,6 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
// ADD PATH_INFO
|
||||
size_t w_len = strlen(worker->name);
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"URL %s: %s %s %s", url, worker->name, r->filename, u_path_info);
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
delta = 1;
|
||||
|
||||
+11
-9
@@ -99,23 +99,23 @@ struct wsgi_request *find_first_available_wsgi_req() {
|
||||
void async_expire_timeouts() {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
time_t current_time = uwsgi_now();
|
||||
uint64_t current_time = (uint64_t) uwsgi_now();
|
||||
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for (;;) {
|
||||
|
||||
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
|
||||
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
|
||||
|
||||
if (urbt == NULL)
|
||||
return;
|
||||
|
||||
if (urbt->key <= current_time) {
|
||||
if (urbt->value <= current_time) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
|
||||
free(wsgi_req->async_timeout);
|
||||
wsgi_req->async_timeout = NULL;
|
||||
uaf = wsgi_req->waiting_fds;
|
||||
@@ -258,12 +258,12 @@ void async_loop() {
|
||||
timeout = 0;
|
||||
}
|
||||
else {
|
||||
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
|
||||
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
timeout = 0;
|
||||
}
|
||||
if (min_timeout) {
|
||||
timeout = min_timeout->key - uwsgi_now();
|
||||
timeout = min_timeout->value - uwsgi_now();
|
||||
if (timeout <= 0) {
|
||||
async_expire_timeouts();
|
||||
timeout = 0;
|
||||
@@ -354,13 +354,14 @@ void async_loop() {
|
||||
if (uwsgi.wsgi_req) {
|
||||
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
|
||||
// reset timeout
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
// put request in the runqueue
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
continue;
|
||||
@@ -395,7 +396,7 @@ void async_loop() {
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
@@ -405,6 +406,7 @@ void async_loop() {
|
||||
|
||||
// put the request in the runqueue again
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,7 +434,7 @@ void async_loop() {
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
+4
-3
@@ -105,7 +105,7 @@ static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = djb33x_hash(key, keylen);
|
||||
|
||||
int hash_key = hash % 0xffff;
|
||||
uint32_t hash_key = hash % 0xffff;
|
||||
|
||||
uint64_t slot = uwsgi.cache_hashtable[hash_key];
|
||||
|
||||
@@ -117,8 +117,9 @@ static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
uci = &uwsgi.cache_items[slot];
|
||||
|
||||
// first round
|
||||
if (hash_key != uci->djbhash % 0xffff) return 0;
|
||||
if (uci->djbhash != hash)
|
||||
return 0;
|
||||
goto cycle;
|
||||
if (uci->keysize != keylen)
|
||||
goto cycle;
|
||||
if (memcmp(uci->key, key, keylen))
|
||||
@@ -144,7 +145,7 @@ cycle:
|
||||
}
|
||||
}
|
||||
if (uci->djbhash != hash)
|
||||
return 0;
|
||||
continue;
|
||||
if (uci->keysize != keylen)
|
||||
continue;
|
||||
if (!memcmp(uci->key, key, keylen))
|
||||
|
||||
+10
-2
@@ -1023,7 +1023,7 @@ void emperor_loop() {
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
emperor_add(NULL, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
@@ -1324,13 +1324,21 @@ end:
|
||||
void uwsgi_emperor_start() {
|
||||
|
||||
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
|
||||
if (uwsgi.emperor_procname) {
|
||||
uwsgi_set_processname(uwsgi.emperor_procname);
|
||||
}
|
||||
uwsgi_notify_ready();
|
||||
emperor_loop();
|
||||
// never here
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
|
||||
if (uwsgi.emperor_procname) {
|
||||
uwsgi.emperor_pid = uwsgi_fork(uwsgi.emperor_procname);
|
||||
}
|
||||
else {
|
||||
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
|
||||
}
|
||||
if (uwsgi.emperor_pid < 0) {
|
||||
uwsgi_error("pid()");
|
||||
exit(1);
|
||||
|
||||
@@ -45,6 +45,10 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
|
||||
|
||||
#ifdef UWSGI_LOCK_USE_MUTEX
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#undef EOWNERDEAD
|
||||
#endif
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
|
||||
int uwsgi_pthread_robust_mutexes_enabled = 1;
|
||||
|
||||
+74
-1
@@ -815,6 +815,7 @@ struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
|
||||
void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
|
||||
ssize_t rlen = 0;
|
||||
const char *empty_var = "-";
|
||||
while (logchunk) {
|
||||
int pos = logchunk->vec;
|
||||
// raw string
|
||||
@@ -851,6 +852,11 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
|
||||
}
|
||||
logchunk = logchunk->next;
|
||||
}
|
||||
|
||||
@@ -862,7 +868,9 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
while (logchunk) {
|
||||
if (logchunk->free) {
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_len > 0) {
|
||||
free(uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base);
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base != empty_var) {
|
||||
free(uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
logchunk = logchunk->next;
|
||||
@@ -928,6 +936,27 @@ ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_lf_hsize(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_lf_size(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_lf_cl(struct wsgi_request *wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->post_cl);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(uwsgi_now());
|
||||
return strlen(*buf);
|
||||
@@ -948,6 +977,17 @@ ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_malloc(64);
|
||||
time_t now = wsgi_req->start_of_request / 1000000;
|
||||
size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
|
||||
if (ret == 0) {
|
||||
*buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
@@ -1018,11 +1058,39 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, protocol);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, user_agent);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
|
||||
logchunk->pos = offsetof(struct wsgi_request, referer);
|
||||
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_status;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_hsize;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_size;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_cl;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_micros;
|
||||
@@ -1038,6 +1106,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->func = uwsgi_lf_time;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ltime;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ctime;
|
||||
|
||||
+16
-10
@@ -231,28 +231,28 @@ int uwsgi_master_check_mercy() {
|
||||
}
|
||||
|
||||
|
||||
void expire_rb_timeouts(struct rb_root *root) {
|
||||
void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
|
||||
|
||||
time_t current = uwsgi_now();
|
||||
uint64_t current = (uint64_t) uwsgi_now();
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
struct uwsgi_signal_rb_timer *usrbt;
|
||||
|
||||
for (;;) {
|
||||
|
||||
urbt = uwsgi_min_rb_timer(root);
|
||||
urbt = uwsgi_min_rb_timer(tree, NULL);
|
||||
|
||||
if (urbt == NULL)
|
||||
return;
|
||||
|
||||
if (urbt->key <= current) {
|
||||
if (urbt->value <= current) {
|
||||
// remove the timeout and add another
|
||||
usrbt = (struct uwsgi_signal_rb_timer *) urbt->data;
|
||||
rb_erase(&usrbt->uwsgi_rb_timer->rbt, root);
|
||||
free(usrbt->uwsgi_rb_timer);
|
||||
uwsgi_del_rb_timer(tree, urbt);
|
||||
free(urbt);
|
||||
usrbt->iterations_done++;
|
||||
uwsgi_route_signal(usrbt->sig);
|
||||
if (!usrbt->iterations || usrbt->iterations_done < usrbt->iterations) {
|
||||
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(root, uwsgi_now() + usrbt->value, usrbt);
|
||||
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(tree, uwsgi_now() + usrbt->value, usrbt);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -622,7 +622,7 @@ int master_loop(char **argv, char **environ) {
|
||||
int check_interval = 1;
|
||||
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct rb_root *rb_timers = uwsgi_init_rb_timer();
|
||||
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
@@ -975,12 +975,12 @@ int master_loop(char **argv, char **environ) {
|
||||
int interesting_fd = -1;
|
||||
|
||||
if (ushared->rb_timers_cnt > 0) {
|
||||
min_timeout = uwsgi_min_rb_timer(rb_timers);
|
||||
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
}
|
||||
else {
|
||||
check_interval = min_timeout->key - uwsgi_now();
|
||||
check_interval = min_timeout->value - uwsgi_now();
|
||||
if (check_interval <= 0) {
|
||||
expire_rb_timeouts(rb_timers);
|
||||
check_interval = 0;
|
||||
@@ -1461,6 +1461,12 @@ health_cycle:
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (uwsgi.emperor_pid >= 0) {
|
||||
uwsgi_log_verbose("!!! Emperor died !!!\n");
|
||||
uwsgi_emperor_start();
|
||||
continue;
|
||||
}
|
||||
|
||||
pid_found = 0;
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
|
||||
@@ -555,6 +555,11 @@ int uwsgi_respawn_worker(int wid) {
|
||||
// reset the apps count with a copy from the master
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
|
||||
// reset wsgi_request structures
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
|
||||
}
|
||||
|
||||
uwsgi_fixup_fds(wid, 0, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
+12
-1
@@ -41,6 +41,17 @@ void uwsgi_mule(int id) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.muleid = id;
|
||||
// avoid race conditions
|
||||
uwsgi.mules[id - 1].id = id;
|
||||
@@ -71,7 +82,7 @@ void uwsgi_mule(int id) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
|
||||
// never here
|
||||
break;
|
||||
end_me(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -883,6 +883,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->authorization = ptrbuf;
|
||||
wsgi_req->authorization_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("HTTP_USER_AGENT", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->user_agent = ptrbuf;
|
||||
wsgi_req->user_agent_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("HTTP_REFERER", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->referer = ptrbuf;
|
||||
wsgi_req->referer_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("DOCUMENT_ROOT", 13, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->document_root = ptrbuf;
|
||||
wsgi_req->document_root_len = strsize;
|
||||
|
||||
+334
-32
@@ -1,65 +1,367 @@
|
||||
/*
|
||||
|
||||
uWSGI timers implementation
|
||||
uWSGI rbtree implementation based on nginx
|
||||
|
||||
based on Linux hrtimers and nginx timeout management.
|
||||
|
||||
rbtree with allowed duplicate keys is used
|
||||
Copyright (C) Igor Sysoev
|
||||
Copyright (C) Nginx, Inc.
|
||||
Copyright (C) Unbit S.a.s.
|
||||
|
||||
The red-black tree code is based on the algorithm described in
|
||||
the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
|
||||
*/
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct rb_root *uwsgi_init_rb_timer() {
|
||||
#define uwsgi_rbt_red(node) ((node)->color = 1)
|
||||
#define uwsgi_rbt_black(node) ((node)->color = 0)
|
||||
#define uwsgi_rbt_is_red(node) ((node)->color)
|
||||
#define uwsgi_rbt_is_black(node) (!uwsgi_rbt_is_red(node))
|
||||
#define uwsgi_rbt_copy_color(n1, n2) (n1->color = n2->color)
|
||||
|
||||
struct rb_root *u_rb_root = uwsgi_malloc(sizeof(struct rb_root));
|
||||
|
||||
u_rb_root->rb_node = NULL;
|
||||
struct uwsgi_rbtree *uwsgi_init_rb_timer() {
|
||||
|
||||
return u_rb_root;
|
||||
struct uwsgi_rbtree *tree = uwsgi_calloc(sizeof(struct uwsgi_rbtree));
|
||||
struct uwsgi_rb_timer *sentinel = uwsgi_calloc(sizeof(struct uwsgi_rb_timer));
|
||||
// no need to set it black, calloc already did it
|
||||
//uwsgi_rbt_black(sentinel);
|
||||
tree->root = sentinel;
|
||||
tree->sentinel = sentinel;
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct rb_root *root) {
|
||||
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
|
||||
|
||||
struct rb_node *node = root->rb_node;
|
||||
if (!node)
|
||||
node = tree->root;
|
||||
struct uwsgi_rb_timer *sentinel = tree->sentinel;
|
||||
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
if (tree->root == sentinel) return NULL;
|
||||
|
||||
while (node->rb_left != NULL) {
|
||||
node = node->rb_left;
|
||||
while (node->left != sentinel) {
|
||||
node = node->left;
|
||||
}
|
||||
|
||||
return ((struct uwsgi_rb_timer *) node);
|
||||
return node;
|
||||
}
|
||||
|
||||
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *root, time_t key, void *data) {
|
||||
static void uwsgi_rbtree_lr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
|
||||
|
||||
struct uwsgi_rb_timer *urbt = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
|
||||
struct rb_node **p = &root->rb_node, *parent = NULL;
|
||||
struct uwsgi_rb_timer *current_rb_timer;
|
||||
struct uwsgi_rb_timer *temp;
|
||||
|
||||
memset(urbt, 0, sizeof(struct uwsgi_rb_timer));
|
||||
temp = node->right;
|
||||
node->right = temp->left;
|
||||
|
||||
urbt->key = key;
|
||||
urbt->data = data;
|
||||
if (temp->left != sentinel) {
|
||||
temp->left->parent = node;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
parent = *p;
|
||||
temp->parent = node->parent;
|
||||
|
||||
current_rb_timer = (struct uwsgi_rb_timer *) parent;
|
||||
if (node == *root) {
|
||||
*root = temp;
|
||||
|
||||
}
|
||||
else if (node == node->parent->left) {
|
||||
node->parent->left = temp;
|
||||
|
||||
}
|
||||
else {
|
||||
node->parent->right = temp;
|
||||
}
|
||||
|
||||
temp->left = node;
|
||||
node->parent = temp;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_rbtree_rr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
|
||||
|
||||
struct uwsgi_rb_timer *temp;
|
||||
|
||||
temp = node->left;
|
||||
node->left = temp->right;
|
||||
|
||||
if (temp->right != sentinel) {
|
||||
temp->right->parent = node;
|
||||
}
|
||||
|
||||
temp->parent = node->parent;
|
||||
|
||||
if (node == *root) {
|
||||
*root = temp;
|
||||
|
||||
}
|
||||
else if (node == node->parent->right) {
|
||||
node->parent->right = temp;
|
||||
|
||||
}
|
||||
else {
|
||||
node->parent->left = temp;
|
||||
}
|
||||
|
||||
temp->right = node;
|
||||
node->parent = temp;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_rbt_add(struct uwsgi_rb_timer *temp, struct uwsgi_rb_timer *node, struct uwsgi_rb_timer *sentinel) {
|
||||
struct uwsgi_rb_timer **p;
|
||||
|
||||
for (;;) {
|
||||
|
||||
p = (node->value < temp->value) ? &temp->left : &temp->right;
|
||||
if (*p == sentinel)
|
||||
break;
|
||||
temp = *p;
|
||||
}
|
||||
|
||||
*p = node;
|
||||
node->parent = temp;
|
||||
node->left = sentinel;
|
||||
node->right = sentinel;
|
||||
uwsgi_rbt_red(node);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *tree, uint64_t value, void *data) {
|
||||
|
||||
struct uwsgi_rb_timer *node = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
|
||||
struct uwsgi_rb_timer *new_node = node;
|
||||
node->value = value;
|
||||
node->data = data;
|
||||
|
||||
struct uwsgi_rb_timer *temp = NULL;
|
||||
|
||||
/* a binary tree insert */
|
||||
|
||||
struct uwsgi_rb_timer **root = &tree->root;
|
||||
struct uwsgi_rb_timer *sentinel = tree->sentinel;
|
||||
|
||||
if (*root == sentinel) {
|
||||
node->parent = NULL;
|
||||
node->left = sentinel;
|
||||
node->right = sentinel;
|
||||
uwsgi_rbt_black(node);
|
||||
*root = node;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
uwsgi_rbt_add(*root, node, sentinel);
|
||||
|
||||
/* re-balance tree */
|
||||
|
||||
while (node != *root && uwsgi_rbt_is_red(node->parent)) {
|
||||
|
||||
if (node->parent == node->parent->parent->left) {
|
||||
temp = node->parent->parent->right;
|
||||
|
||||
if (uwsgi_rbt_is_red(temp)) {
|
||||
uwsgi_rbt_black(node->parent);
|
||||
uwsgi_rbt_black(temp);
|
||||
uwsgi_rbt_red(node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
|
||||
}
|
||||
else {
|
||||
if (node == node->parent->right) {
|
||||
node = node->parent;
|
||||
uwsgi_rbtree_lr(root, sentinel, node);
|
||||
}
|
||||
|
||||
uwsgi_rbt_black(node->parent);
|
||||
uwsgi_rbt_red(node->parent->parent);
|
||||
uwsgi_rbtree_rr(root, sentinel, node->parent->parent);
|
||||
}
|
||||
|
||||
if (key <= current_rb_timer->key) {
|
||||
p = &(*p)->rb_left;
|
||||
}
|
||||
else {
|
||||
p = &(*p)->rb_right;
|
||||
temp = node->parent->parent->left;
|
||||
|
||||
if (uwsgi_rbt_is_red(temp)) {
|
||||
uwsgi_rbt_black(node->parent);
|
||||
uwsgi_rbt_black(temp);
|
||||
uwsgi_rbt_red(node->parent->parent);
|
||||
node = node->parent->parent;
|
||||
|
||||
}
|
||||
else {
|
||||
if (node == node->parent->left) {
|
||||
node = node->parent;
|
||||
uwsgi_rbtree_rr(root, sentinel, node);
|
||||
}
|
||||
|
||||
uwsgi_rbt_black(node->parent);
|
||||
uwsgi_rbt_red(node->parent->parent);
|
||||
uwsgi_rbtree_lr(root, sentinel, node->parent->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb_link_node((struct rb_node *) urbt, parent, p);
|
||||
uwsgi_rbt_black(*root);
|
||||
|
||||
rb_insert_color((struct rb_node *) urbt, root);
|
||||
return new_node;
|
||||
}
|
||||
|
||||
return urbt;
|
||||
void uwsgi_del_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
|
||||
uint8_t red;
|
||||
struct uwsgi_rb_timer **root, *sentinel, *subst, *temp, *w;
|
||||
|
||||
/* a binary tree delete */
|
||||
|
||||
root = &tree->root;
|
||||
sentinel = tree->sentinel;
|
||||
|
||||
if (node->left == sentinel) {
|
||||
temp = node->right;
|
||||
subst = node;
|
||||
|
||||
}
|
||||
else if (node->right == sentinel) {
|
||||
temp = node->left;
|
||||
subst = node;
|
||||
|
||||
}
|
||||
else {
|
||||
subst = uwsgi_min_rb_timer(tree, node->right);
|
||||
|
||||
if (subst->left != sentinel) {
|
||||
temp = subst->left;
|
||||
}
|
||||
else {
|
||||
temp = subst->right;
|
||||
}
|
||||
}
|
||||
|
||||
if (subst == *root) {
|
||||
*root = temp;
|
||||
uwsgi_rbt_black(temp);
|
||||
return;
|
||||
}
|
||||
|
||||
red = uwsgi_rbt_is_red(subst);
|
||||
|
||||
if (subst == subst->parent->left) {
|
||||
subst->parent->left = temp;
|
||||
|
||||
}
|
||||
else {
|
||||
subst->parent->right = temp;
|
||||
}
|
||||
|
||||
if (subst == node) {
|
||||
|
||||
temp->parent = subst->parent;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (subst->parent == node) {
|
||||
temp->parent = subst;
|
||||
|
||||
}
|
||||
else {
|
||||
temp->parent = subst->parent;
|
||||
}
|
||||
|
||||
subst->left = node->left;
|
||||
subst->right = node->right;
|
||||
subst->parent = node->parent;
|
||||
uwsgi_rbt_copy_color(subst, node);
|
||||
|
||||
if (node == *root) {
|
||||
*root = subst;
|
||||
|
||||
}
|
||||
else {
|
||||
if (node == node->parent->left) {
|
||||
node->parent->left = subst;
|
||||
}
|
||||
else {
|
||||
node->parent->right = subst;
|
||||
}
|
||||
}
|
||||
|
||||
if (subst->left != sentinel) {
|
||||
subst->left->parent = subst;
|
||||
}
|
||||
|
||||
if (subst->right != sentinel) {
|
||||
subst->right->parent = subst;
|
||||
}
|
||||
}
|
||||
|
||||
if (red) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* a delete fixup */
|
||||
|
||||
while (temp != *root && uwsgi_rbt_is_black(temp)) {
|
||||
|
||||
if (temp == temp->parent->left) {
|
||||
w = temp->parent->right;
|
||||
|
||||
if (uwsgi_rbt_is_red(w)) {
|
||||
uwsgi_rbt_black(w);
|
||||
uwsgi_rbt_red(temp->parent);
|
||||
uwsgi_rbtree_lr(root, sentinel, temp->parent);
|
||||
w = temp->parent->right;
|
||||
}
|
||||
|
||||
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
|
||||
uwsgi_rbt_red(w);
|
||||
temp = temp->parent;
|
||||
|
||||
}
|
||||
else {
|
||||
if (uwsgi_rbt_is_black(w->right)) {
|
||||
uwsgi_rbt_black(w->left);
|
||||
uwsgi_rbt_red(w);
|
||||
uwsgi_rbtree_rr(root, sentinel, w);
|
||||
w = temp->parent->right;
|
||||
}
|
||||
|
||||
uwsgi_rbt_copy_color(w, temp->parent);
|
||||
uwsgi_rbt_black(temp->parent);
|
||||
uwsgi_rbt_black(w->right);
|
||||
uwsgi_rbtree_lr(root, sentinel, temp->parent);
|
||||
temp = *root;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
w = temp->parent->left;
|
||||
|
||||
if (uwsgi_rbt_is_red(w)) {
|
||||
uwsgi_rbt_black(w);
|
||||
uwsgi_rbt_red(temp->parent);
|
||||
uwsgi_rbtree_rr(root, sentinel, temp->parent);
|
||||
w = temp->parent->left;
|
||||
}
|
||||
|
||||
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
|
||||
uwsgi_rbt_red(w);
|
||||
temp = temp->parent;
|
||||
|
||||
}
|
||||
else {
|
||||
if (uwsgi_rbt_is_black(w->left)) {
|
||||
uwsgi_rbt_black(w->right);
|
||||
uwsgi_rbt_red(w);
|
||||
uwsgi_rbtree_lr(root, sentinel, w);
|
||||
w = temp->parent->left;
|
||||
}
|
||||
|
||||
uwsgi_rbt_copy_color(w, temp->parent);
|
||||
uwsgi_rbt_black(temp->parent);
|
||||
uwsgi_rbt_black(w->left);
|
||||
uwsgi_rbtree_rr(root, sentinel, temp->parent);
|
||||
temp = *root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_rbt_black(temp);
|
||||
}
|
||||
|
||||
@@ -97,8 +97,18 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
|
||||
exit(1);
|
||||
}
|
||||
else if (pid == 0) {
|
||||
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
// USR1 will be used to wake up the spooler
|
||||
uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGSTOP, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
uwsgi.mywid = -1;
|
||||
uwsgi.mypid = getpid();
|
||||
uspool->pid = uwsgi.mypid;
|
||||
|
||||
+44
-22
@@ -4109,31 +4109,53 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
|
||||
|
||||
char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
|
||||
|
||||
struct uwsgi_string_list *touch = touch_list;
|
||||
while (touch) {
|
||||
struct stat tr_st;
|
||||
if (stat(touch->value, &tr_st)) {
|
||||
uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
|
||||
touch->custom = 0;
|
||||
}
|
||||
else {
|
||||
if (!touch->custom)
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
if ((uint64_t) tr_st.st_mtime > touch->custom) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
return touch->value;
|
||||
}
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
}
|
||||
touch = touch->next;
|
||||
}
|
||||
// touch->value - file path
|
||||
// touch->custom - file timestamp
|
||||
// touch->custom2 - 0 if file exists, 1 if it does not exists
|
||||
|
||||
return NULL;
|
||||
struct uwsgi_string_list *touch = touch_list;
|
||||
while (touch) {
|
||||
struct stat tr_st;
|
||||
if (stat(touch->value, &tr_st)) {
|
||||
if (touch->custom && !touch->custom2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] File %s was removed\n", touch->value);
|
||||
#endif
|
||||
touch->custom2 = 1;
|
||||
return touch->value;
|
||||
}
|
||||
else if (!touch->custom && !touch->custom2) {
|
||||
uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
|
||||
touch->custom2 = 1;
|
||||
}
|
||||
touch->custom = 0;
|
||||
}
|
||||
else {
|
||||
if (!touch->custom && touch->custom2) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] File was created: %s\n", touch->value);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
touch->custom2 = 0;
|
||||
return touch->value;
|
||||
}
|
||||
else if (touch->custom && (uint64_t) tr_st.st_mtime > touch->custom) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
return touch->value;
|
||||
}
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
}
|
||||
touch = touch->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *uwsgi_chomp(char *str) {
|
||||
size_t i;
|
||||
for (i = 0; i < strlen(str); i++) {
|
||||
|
||||
+20
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI ***
|
||||
|
||||
Copyright (C) 2009-2012 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright (C) 2009-2013 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -105,7 +105,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"suspend", required_argument, 0, "suspend an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
|
||||
{"resume", required_argument, 0, "resume an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"connect-and-read", required_argument, 0, "connect to a scoekt and wait for data from it", uwsgi_opt_connect_and_read, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"connect-and-read", required_argument, 0, "connect to a socket and wait for data from it", uwsgi_opt_connect_and_read, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"extract", required_argument, 0, "fetch/dump any supported address to stdout", uwsgi_opt_extract, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"listen", required_argument, 'l', "set the socket listen queue size", uwsgi_opt_set_int, &uwsgi.listen_queue, 0},
|
||||
{"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL, 0},
|
||||
@@ -139,6 +140,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
@@ -2888,7 +2890,7 @@ wait_for_call_of_duty:
|
||||
uwsgi_ignition();
|
||||
}
|
||||
// never here
|
||||
pthread_exit(NULL);
|
||||
end_me(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3903,3 +3905,18 @@ void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
|
||||
uwsgi_log("%.*s", (int) len, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
|
||||
|
||||
int len = 0;
|
||||
char *buf;
|
||||
|
||||
buf = uwsgi_open_and_read(address, &len, 0, NULL);
|
||||
if (len > 0) {
|
||||
if (write(1, buf, len) != len) {
|
||||
uwsgi_error("write()");
|
||||
exit(1);
|
||||
};
|
||||
};
|
||||
exit(0);
|
||||
}
|
||||
|
||||
-309
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
|
||||
*** uWSGI, stripped down version of Linux rbtree ***
|
||||
|
||||
|
||||
Red Black Trees
|
||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
||||
(C) 2002 David Woodhouse <dwmw2@infradead.org>
|
||||
|
||||
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../uwsgi.h"
|
||||
|
||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
|
||||
}
|
||||
static inline void rb_set_color(struct rb_node *rb, int color)
|
||||
{
|
||||
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
||||
}
|
||||
|
||||
|
||||
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
||||
{
|
||||
struct rb_node *right = node->rb_right;
|
||||
struct rb_node *parent = rb_parent(node);
|
||||
|
||||
if ((node->rb_right = right->rb_left))
|
||||
rb_set_parent(right->rb_left, node);
|
||||
right->rb_left = node;
|
||||
|
||||
rb_set_parent(right, parent);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (node == parent->rb_left)
|
||||
parent->rb_left = right;
|
||||
else
|
||||
parent->rb_right = right;
|
||||
}
|
||||
else
|
||||
root->rb_node = right;
|
||||
rb_set_parent(node, right);
|
||||
}
|
||||
|
||||
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
|
||||
{
|
||||
struct rb_node *left = node->rb_left;
|
||||
struct rb_node *parent = rb_parent(node);
|
||||
|
||||
if ((node->rb_left = left->rb_right))
|
||||
rb_set_parent(left->rb_right, node);
|
||||
left->rb_right = node;
|
||||
|
||||
rb_set_parent(left, parent);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (node == parent->rb_right)
|
||||
parent->rb_right = left;
|
||||
else
|
||||
parent->rb_left = left;
|
||||
}
|
||||
else
|
||||
root->rb_node = left;
|
||||
rb_set_parent(node, left);
|
||||
}
|
||||
|
||||
void rb_insert_color(struct rb_node *node, struct rb_root *root)
|
||||
{
|
||||
struct rb_node *parent, *gparent;
|
||||
|
||||
while ((parent = rb_parent(node)) && rb_is_red(parent))
|
||||
{
|
||||
gparent = rb_parent(parent);
|
||||
|
||||
if (parent == gparent->rb_left)
|
||||
{
|
||||
{
|
||||
register struct rb_node *uncle = gparent->rb_right;
|
||||
if (uncle && rb_is_red(uncle))
|
||||
{
|
||||
rb_set_black(uncle);
|
||||
rb_set_black(parent);
|
||||
rb_set_red(gparent);
|
||||
node = gparent;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent->rb_right == node)
|
||||
{
|
||||
register struct rb_node *tmp;
|
||||
__rb_rotate_left(parent, root);
|
||||
tmp = parent;
|
||||
parent = node;
|
||||
node = tmp;
|
||||
}
|
||||
|
||||
rb_set_black(parent);
|
||||
rb_set_red(gparent);
|
||||
__rb_rotate_right(gparent, root);
|
||||
} else {
|
||||
{
|
||||
register struct rb_node *uncle = gparent->rb_left;
|
||||
if (uncle && rb_is_red(uncle))
|
||||
{
|
||||
rb_set_black(uncle);
|
||||
rb_set_black(parent);
|
||||
rb_set_red(gparent);
|
||||
node = gparent;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent->rb_left == node)
|
||||
{
|
||||
register struct rb_node *tmp;
|
||||
__rb_rotate_right(parent, root);
|
||||
tmp = parent;
|
||||
parent = node;
|
||||
node = tmp;
|
||||
}
|
||||
|
||||
rb_set_black(parent);
|
||||
rb_set_red(gparent);
|
||||
__rb_rotate_left(gparent, root);
|
||||
}
|
||||
}
|
||||
|
||||
rb_set_black(root->rb_node);
|
||||
}
|
||||
|
||||
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
|
||||
struct rb_root *root)
|
||||
{
|
||||
struct rb_node *other;
|
||||
|
||||
while ((!node || rb_is_black(node)) && node != root->rb_node)
|
||||
{
|
||||
if (parent->rb_left == node)
|
||||
{
|
||||
other = parent->rb_right;
|
||||
if (rb_is_red(other))
|
||||
{
|
||||
rb_set_black(other);
|
||||
rb_set_red(parent);
|
||||
__rb_rotate_left(parent, root);
|
||||
other = parent->rb_right;
|
||||
}
|
||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
||||
{
|
||||
rb_set_red(other);
|
||||
node = parent;
|
||||
parent = rb_parent(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!other->rb_right || rb_is_black(other->rb_right))
|
||||
{
|
||||
rb_set_black(other->rb_left);
|
||||
rb_set_red(other);
|
||||
__rb_rotate_right(other, root);
|
||||
other = parent->rb_right;
|
||||
}
|
||||
rb_set_color(other, rb_color(parent));
|
||||
rb_set_black(parent);
|
||||
rb_set_black(other->rb_right);
|
||||
__rb_rotate_left(parent, root);
|
||||
node = root->rb_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
other = parent->rb_left;
|
||||
if (rb_is_red(other))
|
||||
{
|
||||
rb_set_black(other);
|
||||
rb_set_red(parent);
|
||||
__rb_rotate_right(parent, root);
|
||||
other = parent->rb_left;
|
||||
}
|
||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
||||
{
|
||||
rb_set_red(other);
|
||||
node = parent;
|
||||
parent = rb_parent(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!other->rb_left || rb_is_black(other->rb_left))
|
||||
{
|
||||
rb_set_black(other->rb_right);
|
||||
rb_set_red(other);
|
||||
__rb_rotate_left(other, root);
|
||||
other = parent->rb_left;
|
||||
}
|
||||
rb_set_color(other, rb_color(parent));
|
||||
rb_set_black(parent);
|
||||
rb_set_black(other->rb_left);
|
||||
__rb_rotate_right(parent, root);
|
||||
node = root->rb_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node)
|
||||
rb_set_black(node);
|
||||
}
|
||||
|
||||
void rb_erase(struct rb_node *node, struct rb_root *root)
|
||||
{
|
||||
struct rb_node *child, *parent;
|
||||
int color;
|
||||
|
||||
if (!node->rb_left)
|
||||
child = node->rb_right;
|
||||
else if (!node->rb_right)
|
||||
child = node->rb_left;
|
||||
else
|
||||
{
|
||||
struct rb_node *old = node, *left;
|
||||
|
||||
node = node->rb_right;
|
||||
while ((left = node->rb_left) != NULL)
|
||||
node = left;
|
||||
|
||||
if (rb_parent(old)) {
|
||||
if (rb_parent(old)->rb_left == old)
|
||||
rb_parent(old)->rb_left = node;
|
||||
else
|
||||
rb_parent(old)->rb_right = node;
|
||||
} else
|
||||
root->rb_node = node;
|
||||
|
||||
child = node->rb_right;
|
||||
parent = rb_parent(node);
|
||||
color = rb_color(node);
|
||||
|
||||
if (parent == old) {
|
||||
parent = node;
|
||||
} else {
|
||||
if (child)
|
||||
rb_set_parent(child, parent);
|
||||
parent->rb_left = child;
|
||||
|
||||
node->rb_right = old->rb_right;
|
||||
rb_set_parent(old->rb_right, node);
|
||||
}
|
||||
|
||||
node->rb_parent_color = old->rb_parent_color;
|
||||
node->rb_left = old->rb_left;
|
||||
rb_set_parent(old->rb_left, node);
|
||||
|
||||
goto color;
|
||||
}
|
||||
|
||||
parent = rb_parent(node);
|
||||
color = rb_color(node);
|
||||
|
||||
if (child)
|
||||
rb_set_parent(child, parent);
|
||||
if (parent)
|
||||
{
|
||||
if (parent->rb_left == node)
|
||||
parent->rb_left = child;
|
||||
else
|
||||
parent->rb_right = child;
|
||||
}
|
||||
else
|
||||
root->rb_node = child;
|
||||
|
||||
color:
|
||||
if (color == RB_BLACK)
|
||||
__rb_erase_color(child, parent, root);
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
#else
|
||||
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
#endif
|
||||
{
|
||||
node->rb_parent_color = (unsigned long )parent;
|
||||
node->rb_left = node->rb_right = NULL;
|
||||
|
||||
*rb_link = node;
|
||||
}
|
||||
|
||||
@@ -327,16 +327,16 @@ static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *
|
||||
|
||||
static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
time_t current = uwsgi_now();
|
||||
uint64_t current = (uint64_t) uwsgi_now();
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
struct corerouter_session *cr_session;
|
||||
|
||||
for (;;) {
|
||||
urbt = uwsgi_min_rb_timer(ucr->timeouts);
|
||||
urbt = uwsgi_min_rb_timer(ucr->timeouts, NULL);
|
||||
if (urbt == NULL)
|
||||
return;
|
||||
|
||||
if (urbt->key <= current) {
|
||||
if (urbt->value <= current) {
|
||||
cr_session = (struct corerouter_session *) urbt->data;
|
||||
cr_session->timed_out = 1;
|
||||
if (cr_session->connecting) {
|
||||
@@ -708,12 +708,12 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
for (;;) {
|
||||
|
||||
// set timeouts and harakiri
|
||||
min_timeout = uwsgi_min_rb_timer(ucr->timeouts);
|
||||
min_timeout = uwsgi_min_rb_timer(ucr->timeouts, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
delta = -1;
|
||||
}
|
||||
else {
|
||||
delta = min_timeout->key - uwsgi_now();
|
||||
delta = min_timeout->value - uwsgi_now();
|
||||
if (delta <= 0) {
|
||||
corerouter_expire_timeouts(ucr);
|
||||
delta = 0;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+u->socket_timeout, x)
|
||||
#define cr_add_fake_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+1, x)
|
||||
#define cr_add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
|
||||
#define cr_del_check_timeout(x) rb_erase(&x->rbt, timeouts);
|
||||
#define cr_del_timeout(u, x) rb_erase(&x->timeout->rbt, u->timeouts); free(x->timeout);
|
||||
#define cr_del_check_timeout(x) uwsgi_del_rb_timer(timeouts, x);
|
||||
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
|
||||
|
||||
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
|
||||
errno = EINPROGRESS;\
|
||||
@@ -33,7 +33,7 @@ struct uwsgi_corerouter {
|
||||
int processes;
|
||||
int quiet;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
struct uwsgi_rbtree *timeouts;
|
||||
|
||||
int use_cache;
|
||||
int nevents;
|
||||
|
||||
@@ -265,6 +265,11 @@ ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_bu
|
||||
stop_the_watchers
|
||||
}
|
||||
|
||||
Py_DECREF(current);
|
||||
Py_DECREF(current_greenlet);
|
||||
Py_DECREF(watcher);
|
||||
Py_DECREF(timer);
|
||||
|
||||
return *tmp_pos;
|
||||
|
||||
}
|
||||
|
||||
@@ -291,6 +291,57 @@ static int uwsgi_api_req_fd(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uwsgi_api_lock(lua_State *L) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
lua_pushstring(L, "The spooler cannot lock/unlock resources");
|
||||
lua_error(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lua_gettop(L) > 0) {
|
||||
lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
lua_pushstring(L, "Invalid lock number");
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_api_unlock(lua_State *L) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
lua_pushstring(L, "The spooler cannot lock/unlock resources");
|
||||
lua_error(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lua_gettop(L) > 0) {
|
||||
lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
lua_pushstring(L, "Invalid lock number");
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_reg uwsgi_api[] = {
|
||||
{"log", uwsgi_api_log},
|
||||
{"cl", uwsgi_api_cl},
|
||||
@@ -300,6 +351,8 @@ static const luaL_reg uwsgi_api[] = {
|
||||
{"cache_set", uwsgi_api_cache_set},
|
||||
{"register_signal", uwsgi_api_register_signal},
|
||||
{"register_rpc", uwsgi_api_register_rpc},
|
||||
{"lock", uwsgi_api_lock},
|
||||
{"unlock", uwsgi_api_unlock},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ struct uwsgi_php {
|
||||
char *docroot;
|
||||
char *app;
|
||||
char *app_qs;
|
||||
char *fallback;
|
||||
size_t ini_size;
|
||||
int dump_config;
|
||||
char *server_software;
|
||||
@@ -53,6 +54,7 @@ struct uwsgi_option uwsgi_php_options[] = {
|
||||
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
|
||||
{"php-var", required_argument, 0, "add/overwrite a CGI variable at each request", uwsgi_opt_add_string_list, &uphp.vars, 0},
|
||||
{"php-app-qs", required_argument, 0, "when in app mode force QUERY_STRING to the specified value + PATH_INFO", uwsgi_opt_set_str, &uphp.app_qs, 0},
|
||||
{"php-fallback", required_argument, 0, "run the specified php script when the request one does not exist", uwsgi_opt_set_str, &uphp.fallback, 0},
|
||||
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
@@ -717,7 +719,6 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
*(dst+part_size-1) = 0;
|
||||
|
||||
if (stat(full_path, &st)) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -727,7 +728,6 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
|
||||
if (i < (wsgi_req->path_info_len)-1) {
|
||||
*path_info = ptr + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -823,9 +823,16 @@ appready:
|
||||
|
||||
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
|
||||
free(filename);
|
||||
return -1;
|
||||
if (uphp.fallback) {
|
||||
filename = uwsgi_str(uphp.fallback);
|
||||
}
|
||||
else {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
uint16_t orig_path_info_len = wsgi_req->path_info_len;
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ struct uwsgi_perl {
|
||||
|
||||
CV **tmp_psgix_logger;
|
||||
CV **tmp_stream_responder;
|
||||
|
||||
SV *postfork;
|
||||
SV *atexit;
|
||||
};
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
@@ -52,3 +55,4 @@ int uwsgi_perl_obj_isa(SV *, char *);
|
||||
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 *);
|
||||
|
||||
@@ -16,6 +16,9 @@ struct uwsgi_option uwsgi_perl_options[] = {
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
|
||||
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
|
||||
#ifdef PERL_VERSION_STRING
|
||||
{"perl-version", no_argument, 0, "print perl version", uwsgi_opt_print, PERL_VERSION_STRING, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -554,6 +557,10 @@ void uwsgi_perl_post_fork() {
|
||||
sv_setiv(GvSV(tmpgv), (IV)getpid());
|
||||
SvREADONLY_on(GvSV(tmpgv));
|
||||
}
|
||||
|
||||
if (uperl.postfork) {
|
||||
uwsgi_perl_run_hook(uperl.postfork);
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_perl_mount_app(char *mountpoint, char *app) {
|
||||
@@ -621,6 +628,51 @@ int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_perl_run_hook(SV *hook) {
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs( hook );
|
||||
PUTBACK;
|
||||
|
||||
call_sv( SvRV(hook), G_DISCARD);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
|
||||
return;
|
||||
}
|
||||
|
||||
SPAGAIN;
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
if (uwsgi.mywid == -1) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
return;
|
||||
|
||||
// if busy do not run atexit hooks
|
||||
if (uwsgi.workers[uwsgi.mywid].busy)
|
||||
return;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
// managing atexit in async mode is a real pain...skip it for now
|
||||
if (uwsgi.async > 1)
|
||||
return;
|
||||
#endif
|
||||
|
||||
realstuff:
|
||||
|
||||
if (uperl.atexit) {
|
||||
uwsgi_perl_run_hook(uperl.atexit);
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
.name = "psgi",
|
||||
@@ -641,5 +693,7 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
|
||||
.atexit = uwsgi_perl_atexit,
|
||||
|
||||
.magic = uwsgi_perl_magic,
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_plugin psgi_plugin;
|
||||
extern struct uwsgi_perl uperl;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
|
||||
@@ -171,6 +172,28 @@ XS(XS_register_signal) {
|
||||
|
||||
}
|
||||
|
||||
XS(XS_postfork) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
uperl.postfork = newRV_inc(ST(0));
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_atexit) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
uperl.atexit = newRV_inc(ST(0));
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
XS(XS_log) {
|
||||
|
||||
dXSARGS;
|
||||
@@ -282,5 +305,7 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(signal);
|
||||
psgi_xs(register_signal);
|
||||
psgi_xs(signal_wait);
|
||||
psgi_xs(postfork);
|
||||
psgi_xs(atexit);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,23 @@ void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
|
||||
up.pyrun = value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
|
||||
#ifndef UWSGI_PYPY
|
||||
const char *version = Py_GetVersion();
|
||||
#else
|
||||
const char *version = PYPY_VERSION;
|
||||
#endif
|
||||
const char *space = strchr(version, ' ');
|
||||
if (space) {
|
||||
fprintf(stdout, "%.*s\n", (int) (space-version), version);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "%s\n", version);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -142,6 +159,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-env-behavior", required_argument, 0, "set the strategy for allocating/deallocating the WSGI env", uwsgi_opt_set_str, &up.wsgi_env_behaviour, 0},
|
||||
{"start_response-nodelay", no_argument, 0, "send WSGI http headers as soon as possible (PEP violation)", uwsgi_opt_true, &up.start_response_nodelay, 0},
|
||||
|
||||
{"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -1754,9 +1773,7 @@ int uwsgi_python_mule(char *opt) {
|
||||
|
||||
if (uwsgi_endswith(opt, ".py")) {
|
||||
UWSGI_GET_GIL;
|
||||
if (uwsgi_pyimport_by_filename("__main__", opt) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
uwsgi_pyimport_by_filename("__main__", opt);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2763,7 +2763,6 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
|
||||
|
||||
PyDict_SetItemString(worker_dict, "apps", apps_tuple);
|
||||
Py_DECREF(apps_tuple);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -270,7 +270,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
char post_buf[8192];
|
||||
char *post_tail = NULL;
|
||||
|
||||
// first round ? this memory area will be freed by async_loop
|
||||
// first round ?
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(uwsgi.buffer_size);
|
||||
}
|
||||
@@ -281,12 +281,15 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
remains = UMIN(remains, 8192);
|
||||
len = read(wsgi_req->poll.fd, post_buf, remains);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fwrite(post_buf, len, 1, wsgi_req->async_post)) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
uwsgi_error("fwrite()");
|
||||
return -1;
|
||||
}
|
||||
@@ -296,6 +299,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
}
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
rewind(wsgi_req->async_post);
|
||||
wsgi_req->body_as_file = 1;
|
||||
return UWSGI_OK;
|
||||
@@ -339,6 +343,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->async_post = tmpfile();
|
||||
if (!wsgi_req->async_post) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
if (post_tail) free(post_tail);
|
||||
uwsgi_error("tmpfile()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,14 @@ my $three = sub {
|
||||
print "three\n";
|
||||
};
|
||||
|
||||
uwsgi::postfork(sub {
|
||||
print "forked !!!\n";
|
||||
});
|
||||
|
||||
uwsgi::atexit(sub {
|
||||
print "exited\n";
|
||||
});
|
||||
|
||||
my $app = sub {
|
||||
my $env = shift;
|
||||
uwsgi::signal(17);
|
||||
|
||||
@@ -3,7 +3,7 @@ import uwsgi
|
||||
sleepvalue = 5
|
||||
|
||||
def application(env, start_response):
|
||||
start_response('200 Ok', [('Content-type', 'text/html')])
|
||||
start_response('200 Ok', [('Content-type', 'text/html')])
|
||||
yield uwsgi.async_sleep(sleepvalue)
|
||||
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
|
||||
yield "<h1>Hello World after %d seconds</h1>" % sleepvalue
|
||||
|
||||
@@ -395,6 +395,25 @@ struct uwsgi_regexp_list {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct uwsgi_rbtree {
|
||||
struct uwsgi_rb_timer *root;
|
||||
struct uwsgi_rb_timer *sentinel;
|
||||
};
|
||||
|
||||
struct uwsgi_rb_timer {
|
||||
uint8_t color;
|
||||
struct uwsgi_rb_timer *parent;
|
||||
struct uwsgi_rb_timer *left;
|
||||
struct uwsgi_rb_timer *right;
|
||||
uint64_t value;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct uwsgi_rbtree *uwsgi_init_rb_timer(void);
|
||||
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *);
|
||||
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *, uint64_t, void *);
|
||||
void uwsgi_del_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *);
|
||||
|
||||
|
||||
union uwsgi_sockaddr {
|
||||
struct sockaddr sa;
|
||||
@@ -995,6 +1014,12 @@ struct wsgi_request {
|
||||
char *authorization;
|
||||
uint16_t authorization_len;
|
||||
|
||||
char *user_agent;
|
||||
uint16_t user_agent_len;
|
||||
|
||||
char *referer;
|
||||
uint16_t referer_len;
|
||||
|
||||
char *script;
|
||||
uint16_t script_len;
|
||||
char *module;
|
||||
@@ -1293,6 +1318,7 @@ struct uwsgi_server {
|
||||
|
||||
// true if run under the emperor
|
||||
int has_emperor;
|
||||
char *emperor_procname;
|
||||
int emperor_fd;
|
||||
int emperor_queue;
|
||||
int emperor_tyrant;
|
||||
@@ -1550,7 +1576,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_async_request *async_runqueue_last;
|
||||
int async_runqueue_cnt;
|
||||
|
||||
struct rb_root *rb_async_timeouts;
|
||||
struct uwsgi_rbtree *rb_async_timeouts;
|
||||
|
||||
int async_queue_unused_ptr;
|
||||
struct wsgi_request **async_queue_unused;
|
||||
@@ -2591,74 +2617,6 @@ struct uwsgi_subscribe_req {
|
||||
uint16_t base_len;
|
||||
};
|
||||
|
||||
#ifndef _NO_UWSGI_RB
|
||||
|
||||
/*
|
||||
|
||||
*** uWSGI, stripped down version of Linux rbtree ***
|
||||
|
||||
|
||||
Red Black Trees
|
||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
||||
|
||||
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
struct rb_node
|
||||
{
|
||||
unsigned long rb_parent_color;
|
||||
#define RB_RED 0
|
||||
#define RB_BLACK 1
|
||||
struct rb_node *rb_right;
|
||||
struct rb_node *rb_left;
|
||||
} __attribute__((aligned(sizeof(long))));
|
||||
/* The alignment might seem pointless, but allegedly CRIS needs it */
|
||||
|
||||
struct rb_root
|
||||
{
|
||||
struct rb_node *rb_node;
|
||||
};
|
||||
|
||||
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
|
||||
#define rb_color(r) ((r)->rb_parent_color & 1)
|
||||
#define rb_is_red(r) (!rb_color(r))
|
||||
#define rb_is_black(r) rb_color(r)
|
||||
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
|
||||
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
|
||||
|
||||
void rb_insert_color(struct rb_node *, struct rb_root *);
|
||||
void rb_erase(struct rb_node *, struct rb_root *);
|
||||
|
||||
void rb_link_node(struct rb_node *, struct rb_node *,
|
||||
struct rb_node **);
|
||||
|
||||
struct uwsgi_rb_timer {
|
||||
|
||||
struct rb_node rbt;
|
||||
|
||||
time_t key;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct rb_root *uwsgi_init_rb_timer(void);
|
||||
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *, time_t, void *);
|
||||
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct rb_root *);
|
||||
|
||||
#endif
|
||||
|
||||
void uwsgi_nuclear_blast();
|
||||
|
||||
void uwsgi_unix_signal(int, void (*)(int));
|
||||
@@ -3221,6 +3179,7 @@ void manage_cluster_message(char *, int);
|
||||
void uwsgi_opt_add_custom_option(char *, char *, void *);
|
||||
void uwsgi_opt_cflags(char *, char *, void *);
|
||||
void uwsgi_opt_connect_and_read(char *, char *, void *);
|
||||
void uwsgi_opt_extract(char *, char *, void *);
|
||||
|
||||
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.4.4'
|
||||
uwsgi_version = '1.4.5'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -457,7 +457,7 @@ class uConf(object):
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/cluster',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'lib/rbtree', 'core/rb_timers', 'core/uwsgi']
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
self.gcc_list.append('proto/uwsgi')
|
||||
|
||||
Reference in New Issue
Block a user