Compare commits

...
37 Commits
Author SHA1 Message Date
Unbit 93116a1239 prepare for 2.0.8 2014-10-26 05:30:44 +01:00
unbit 5e4440443a Merge pull request #755 from aldur/manage_script_name_fix
manage_script_name fix for tricky resources
2014-10-24 17:19:50 +02:00
Unbit 373481b888 backported rtsp support 2014-10-24 17:12:52 +02:00
Unbit 105b9c69cf backported --hook-post-fork 2014-10-24 12:07:05 +02:00
Unbit 9012ead72c backported https fix for ssl shutdown 2014-10-24 11:49:18 +02:00
Roberto De Ioris 6c1d2625a8 backported support for chunked input management in the http/https router 2014-10-19 12:54:12 +02:00
Unbit c0733b5771 Merge remote-tracking branch 'origin/uwsgi-2.0-cache-lazy-expire' into uwsgi-2.0 2014-10-18 04:23:39 +02:00
Unbit f4759d7acd fixed php SCRIPT_NAME usage when --php-app is in place 2014-10-18 04:19:41 +02:00
Unbit 7082188a06 allow appendn hook without second argument 2014-10-17 13:15:30 +02:00
Unbit bcd9ed011d try to load trollius on python2 2014-10-17 13:04:46 +02:00
Nigel Heron 25c6d7a3a1 fix heap corruption in carbon plugin 2014-10-17 05:18:58 +02:00
Roberto De Ioris 675c02c7fa fixed #749 2014-10-16 20:53:47 +02:00
Roberto De Ioris 32896a1418 fixed #748 2014-10-16 08:26:13 +02:00
Unbit 548e736d84 fixed #746 2014-10-15 10:06:27 +02:00
Unbit 87575b1a22 disable SSLv3 by default and allow setting raw ssl options 2014-10-15 09:11:18 +02:00
Roberto De Ioris 1aa6eeca1b added sweep_on_full, clear_on_full and no_expire 2014-10-14 05:24:28 +02:00
Unbit f778e30d48 run the sweeper only if required 2014-10-13 13:00:07 +02:00
Unbit e071184d53 ignore lazy caches from the sweeper 2014-10-13 12:55:26 +02:00
Unbit 1d09cde778 implemented cache lazy expire 2014-10-13 12:40:40 +02:00
Greg Dahlman 70ee29becb added wait for fs and wait for mountpoint 2014-10-10 11:06:44 +02:00
Unbit 60e26333bf allows building external plugins as embedded 2014-10-10 11:00:28 +02:00
Unbit 865b9c199d improved offload api 2014-10-10 10:58:45 +02:00
Unbit 833193a1ba added UWSGI_HAS_OFFLOAD_UBUFS 2014-10-10 10:58:41 +02:00
Unbit 4eab050634 added 8 uwsgi_buffer and 8 custom fields to offload request 2014-10-10 10:57:03 +02:00
Aldur 688d1d3b75 fixed python3 support in spooler decorators 2014-10-10 10:55:18 +02:00
Unbit 349daee614 fixed uwsgidecorators spooler arguments 2014-10-10 10:49:18 +02:00
Unbit 0d272cf747 added Adriano Di Luzio to 2.0 CONTRIBUTORS 2014-10-10 10:47:19 +02:00
Unbit 46ac28efae fixed tcsetattr 2014-10-10 10:45:58 +02:00
Unbit 31b3bcc83d fixed kevent 2014-10-10 10:45:06 +02:00
Unbit f364d676fa automatically manage HTTP_X_FORWARDED_PROTO 2014-10-10 10:40:13 +02:00
Unbit c72fde1eed ensure PSGI response headers are in the right format [2] 2014-10-03 08:32:03 +02:00
Unbit a5cacfbba6 ensure PSGI response headers are in the right format 2014-10-03 08:31:52 +02:00
Unbit 921cfa5d79 backported daemons and proto http fixes from 2.1 2014-10-03 08:30:11 +02:00
Roberto De Ioris 9c676c62f5 destroy the whole instance on Emperor error 2014-10-03 08:26:57 +02:00
Roberto De Ioris 2917de3e76 exit on Emperor error 2014-10-03 08:26:43 +02:00
Unbit e836272c07 attempt to fix #732 2014-10-03 08:26:21 +02:00
Roberto De Ioris 7e25452242 set version to 2.0.7.1 2014-09-12 06:37:06 +02:00
34 changed files with 662 additions and 128 deletions
+1
View File
@@ -29,3 +29,4 @@ Danila Shtan <danila@shtan.ru>
Ævar Arnfjörð Bjarmason
Yu Zhao (getcwd)
Mathieu Dupuy
Adriano Di Luzio (adriano@unbit.it)
+2 -1
View File
@@ -369,7 +369,8 @@ void async_schedule_to_req_green(void) {
uwsgi.schedule_fix(wsgi_req);
}
// switch after each yield
uwsgi.schedule_to_main(wsgi_req);
if (uwsgi.schedule_to_main)
uwsgi.schedule_to_main(wsgi_req);
}
#ifdef UWSGI_ROUTING
+84 -40
View File
@@ -24,6 +24,42 @@ extern struct uwsgi_server uwsgi;
*/
static void cache_full(struct uwsgi_cache *uc) {
uint64_t i;
if (!uc->ignore_full) {
if (uc->purge_lru)
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
else
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
}
uc->full++;
if (uc->purge_lru && uc->lru_head)
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
// we do not need locking here !
if (uc->sweep_on_full) {
uint64_t now = (uint64_t) uwsgi_now();
if (uc->next_scan <= now) {
uc->next_scan = now + uc->sweep_on_full;
for (i = 1; i < uc->max_items; i++) {
struct uwsgi_cache_item *uci = cache_item(i);
if (uci->expires > 0 && uci->expires <= now) {
uwsgi_cache_del2(uc, NULL, 0, i, 0);
}
}
}
}
if (uc->clear_on_full) {
for (i = 1; i < uc->max_items; i++) {
uwsgi_cache_del2(uc, NULL, 0, i, 0);
}
}
}
static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t need) {
// how many blocks we need ?
uint64_t needed_blocks = need/uc->blocksize;
@@ -420,6 +456,17 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
}
static uint64_t check_lazy(struct uwsgi_cache *uc, struct uwsgi_cache_item *uci, uint64_t slot) {
if (!uci->expires || !uc->lazy_expire) return slot;
uint64_t now = (uint64_t) uwsgi_now();
// expired ?
if (uci->expires <= now) {
uwsgi_cache_del2(uc, NULL, 0, slot, UWSGI_CACHE_FLAG_LOCAL);
return 0;
}
return slot;
}
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
uint32_t hash = uc->hash->func(key, keylen);
@@ -445,7 +492,7 @@ static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_
if (memcmp(uci->key, key, keylen))
goto cycle;
return slot;
return check_lazy(uc, uci, slot);
cycle:
while (uci->next) {
@@ -468,8 +515,9 @@ cycle:
continue;
if (uci->keysize != keylen)
continue;
if (!memcmp(uci->key, key, keylen))
return slot;
if (!memcmp(uci->key, key, keylen)) {
return check_lazy(uc, uci, slot);
}
}
return 0;
@@ -718,15 +766,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
index = uwsgi_cache_get_index(uc, key, keylen);
if (!index) {
if (!uc->unused_blocks_stack_ptr) {
if (!uc->ignore_full) {
if (uc->purge_lru)
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
else
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
}
uc->full++;
if (uc->purge_lru && uc->lru_head)
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
cache_full(uc);
if (!uc->unused_blocks_stack_ptr)
goto end;
}
@@ -741,16 +781,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
else {
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
if (uci->first_block == 0xffffffffffffffffLLU) {
if (!uc->ignore_full) {
if (uc->purge_lru)
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
else
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
}
uc->full++;
uc->unused_blocks_stack_ptr++;
if (uc->purge_lru && uc->lru_head)
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
cache_full(uc);
goto end;
}
// mark used blocks;
@@ -851,16 +883,8 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
uint64_t old_first_block = uci->first_block;
uci->first_block = uwsgi_cache_find_free_blocks(uc, vallen);
if (uci->first_block == 0xffffffffffffffffLLU) {
if (!uc->ignore_full) {
if (uc->purge_lru)
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
else
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
}
uc->full++;
uci->first_block = old_first_block;
if (uc->purge_lru && uc->lru_head)
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
cache_full(uc);
goto end;
}
// mark used blocks;
@@ -1072,7 +1096,7 @@ static uint64_t cache_sweeper_free_items(struct uwsgi_cache *uc) {
uint64_t i;
uint64_t freed_items = 0;
if (uc->no_expire || uc->purge_lru)
if (uc->no_expire || uc->purge_lru || uc->lazy_expire)
return 0;
uwsgi_rlock(uc->lock);
@@ -1151,20 +1175,24 @@ void uwsgi_cache_start_sweepers() {
if (uwsgi.cache_no_expire)
return;
int need_to_run = 0;
while(uc) {
pthread_t cache_sweeper;
if (!uc->no_expire && !uc->purge_lru) {
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
uwsgi_error("pthread_create()");
uwsgi_log("unable to run the sweeper!!!\n");
}
else {
uwsgi_log("sweeper thread enabled\n");
}
if (!uc->no_expire && !uc->purge_lru && !uc->lazy_expire) {
need_to_run = 1;
break;
}
uc = uc->next;
}
if (!need_to_run) return;
pthread_t cache_sweeper;
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
uwsgi_error("uwsgi_cache_start_sweepers()/pthread_create()");
uwsgi_log("unable to run the cache sweeper!!!\n");
return;
}
uwsgi_log("cache sweeper thread enabled\n");
}
void uwsgi_cache_start_sync_servers() {
@@ -1241,6 +1269,10 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
char *c_math_initial = NULL;
char *c_ignore_full = NULL;
char *c_purge_lru = NULL;
char *c_lazy_expire = NULL;
char *c_sweep_on_full = NULL;
char *c_clear_on_full = NULL;
char *c_no_expire = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"name", &c_name,
@@ -1273,6 +1305,11 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
"ignore_full", &c_ignore_full,
"purge_lru", &c_purge_lru,
"lru", &c_purge_lru,
"lazy_expire", &c_lazy_expire,
"lazy", &c_lazy_expire,
"sweep_on_full", &c_sweep_on_full,
"clear_on_full", &c_clear_on_full,
"no_expire", &c_no_expire,
NULL)) {
uwsgi_log("unable to parse cache definition\n");
exit(1);
@@ -1326,6 +1363,13 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
if (c_lazy_expire) uc->lazy_expire = 1;
if (c_sweep_on_full) {
uc->sweep_on_full = uwsgi_n64(c_sweep_on_full);
}
if (c_clear_on_full) uc->clear_on_full = 1;
if (c_no_expire) uc->no_expire = 1;
uc->store_sync = uwsgi.cache_store_sync;
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
+6 -1
View File
@@ -237,7 +237,12 @@ void uwsgi_detach_daemons() {
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
int waitpid_status;
while (!kill(ud->pid, 0)) {
kill(-(ud->pid), ud->stop_signal);
if (uwsgi_instance_is_reloading && ud->reload_signal > 0) {
kill(-(ud->pid), ud->reload_signal);
}
else {
kill(-(ud->pid), ud->stop_signal);
}
sleep(1);
waitpid(ud->pid, &waitpid_status, WNOHANG);
if (uwsgi_now() >= timeout) {
+1 -1
View File
@@ -948,7 +948,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
struct timespec ts;
struct kevent ev;
if (timeout <= 0) {
if (timeout < 0) {
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
}
else {
+15 -6
View File
@@ -233,17 +233,26 @@ static int uwsgi_hook_writen(char *arg) {
static int uwsgi_hook_appendn(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
return -1;
}
*space = 0;
if (space)
*space = 0;
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
if (fd < 0) {
uwsgi_error_open(arg);
*space = ' ';
if (space)
*space = ' ';
return -1;
}
if (!space) {
// simple newline
if (write(fd, "\n", 1) != 1) {
uwsgi_error("uwsgi_hook_appendn()/write()");
close(fd);
return -1;
}
close(fd);
return 0;
}
*space = ' ';
size_t l = strlen(space+1);
char *buf = uwsgi_malloc(l + 1);
+38
View File
@@ -55,6 +55,9 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
}
return -1;
}
#ifdef UWSGI_DEBUG
uwsgi_log("[offload] created session %p\n", uor);
#endif
return 0;
}
@@ -159,6 +162,12 @@ static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsg
}
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
// call the free function asap
if (uor->free) {
uor->free(uor);
}
// close the socket and the file descriptor
if (uor->takeover && uor->s > -1) {
close(uor->s);
@@ -197,12 +206,41 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
uwsgi_buffer_destroy(uor->ubuf);
}
if (uor->ubuf1) {
uwsgi_buffer_destroy(uor->ubuf1);
}
if (uor->ubuf2) {
uwsgi_buffer_destroy(uor->ubuf2);
}
if (uor->ubuf3) {
uwsgi_buffer_destroy(uor->ubuf3);
}
if (uor->ubuf4) {
uwsgi_buffer_destroy(uor->ubuf4);
}
if (uor->ubuf5) {
uwsgi_buffer_destroy(uor->ubuf5);
}
if (uor->ubuf6) {
uwsgi_buffer_destroy(uor->ubuf6);
}
if (uor->ubuf7) {
uwsgi_buffer_destroy(uor->ubuf7);
}
if (uor->ubuf8) {
uwsgi_buffer_destroy(uor->ubuf8);
}
if (uor->pipe[0] != -1) {
close(uor->pipe[1]);
close(uor->pipe[0]);
}
free(uor);
#ifdef UWSGI_DEBUG
uwsgi_log("[offload] destroyed session %p\n", uor);
#endif
}
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
+40 -20
View File
@@ -527,6 +527,11 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_X_FORWARDED_PROTO", 22)) {
wsgi_req->scheme = buf;
wsgi_req->scheme_len = len;
}
return 0;
}
@@ -731,25 +736,40 @@ next:
}
for (i = 0; i < uwsgi_apps_cnt; i++) {
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
best_found = uwsgi_apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
char* mountpoint = uwsgi_apps[i].mountpoint;
int mountpoint_len = uwsgi_apps[i].mountpoint_len;
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
#ifdef UWSGI_DEBUG
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
#endif
}
// Ignore trailing mountpoint slashes
if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') {
mountpoint_len -= 1;
}
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
// Check if mountpoint could be a possible candidate
if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info
mountpoint_len <= best_found || // it should be better than the previous found
// should have the same prefix of path_info
uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) ||
// and should not be "misleading"
(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) {
continue;
}
best_found = mountpoint_len;
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
#ifdef UWSGI_DEBUG
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
#endif
}
}
}
@@ -1051,7 +1071,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
wsgi_req->var_cnt++;
ptr += keylen;
*ptr++ = (uint8_t) (vallen & 0xff);
*ptr++ = (uint8_t) ((vallen >> 8) & 0xff);
@@ -1118,13 +1138,13 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
*ptr ++= '/';
}
memcpy(ptr, index, index_len);
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
wsgi_req->var_cnt++;
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
wsgi_req->path_info = new_path_info;
return 0;
}
+2
View File
@@ -563,6 +563,7 @@ char *generate_socket_name(char *socket_name) {
ifa = ifap;
while (ifa) {
memset(new_addr, 0, 16);
if (!ifa->ifa_addr) goto next;
sin = (struct sockaddr_in *) ifa->ifa_addr;
if (inet_ntop(AF_INET, (void *) &sin->sin_addr.s_addr, new_addr, 16)) {
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
@@ -575,6 +576,7 @@ char *generate_socket_name(char *socket_name) {
}
next:
ifaf = ifa;
ifa = ifaf->ifa_next;
+9
View File
@@ -210,6 +210,10 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
ssloptions |= SSL_OP_NO_COMPRESSION;
#endif
if (!uwsgi.sslv3) {
ssloptions |= SSL_OP_NO_SSLv3;
}
// release/reuse buffers as soon as possibile
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
@@ -396,6 +400,11 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, uwsgi.ssl_options) {
ssloptions |= atoi(usl->value);
}
SSL_CTX_set_options(ctx, ssloptions);
+73 -1
View File
@@ -699,6 +699,22 @@ void uwsgi_as_root() {
}
}
uwsgi_foreach(usl, uwsgi.wait_for_fs) {
if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_file) {
if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_dir) {
if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
}
uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
}
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
uwsgi_foreach(usl, uwsgi.mount_as_root) {
@@ -3399,7 +3415,7 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
}
if (!uwsgi.no_default_app) {
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
if ((mountpoint_len == 0 || (mountpoint_len == 1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
uwsgi.default_app = id;
}
}
@@ -4463,3 +4479,59 @@ mode_t uwsgi_mode_t(char *value, int *error) {
return mode;
}
int uwsgi_wait_for_mountpoint(char *mountpoint) {
if (!uwsgi.wait_for_fs_timeout) {
uwsgi.wait_for_fs_timeout = 60;
}
uwsgi_log("waiting for %s (max %d seconds) ...\n", mountpoint, uwsgi.wait_for_fs_timeout);
int counter = 0;
for (;;) {
if (counter > uwsgi.wait_for_fs_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", mountpoint, counter);
return -1;
}
struct stat st0;
struct stat st1;
if (stat(mountpoint, &st0)) goto retry;
if (!S_ISDIR(st0.st_mode)) goto retry;
char *relative = uwsgi_concat2(mountpoint, "/../");
if (stat(relative, &st1)) {
free(relative);
goto retry;
}
free(relative);
// useless :P
if (!S_ISDIR(st1.st_mode)) goto retry;
if (st0.st_dev == st1.st_dev) goto retry;
uwsgi_log_verbose("%s mounted\n", mountpoint);
return 0;
retry:
sleep(1);
counter++;
}
}
// type -> 1 file, 2 dir, 0 both
int uwsgi_wait_for_fs(char *filename, int type) {
if (!uwsgi.wait_for_fs_timeout) {
uwsgi.wait_for_fs_timeout = 60;
}
uwsgi_log("waiting for %s (max %d seconds) ...\n", filename, uwsgi.wait_for_fs_timeout);
int counter = 0;
for (;;) {
if (counter > uwsgi.wait_for_fs_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
return -1;
}
struct stat st;
if (stat(filename, &st)) goto retry;
if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
uwsgi_log_verbose("%s found\n", filename);
return 0;
retry:
sleep(1);
counter++;
}
}
+19 -3
View File
@@ -393,6 +393,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
{"hook-post-fork", required_argument, 0, "run the specified hook after each fork", uwsgi_opt_add_string_list, &uwsgi.hook_post_fork, 0},
{"hook-accepting", required_argument, 0, "run the specified hook after each worker enter the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting, 0},
{"hook-accepting1", required_argument, 0, "run the specified hook after the first worker enters the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1, 0},
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
@@ -460,6 +461,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"wait-for-fs", required_argument, 0, "wait for the specified filesystem item to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
{"wait-for-file", required_argument, 0, "wait for the specified file to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
{"wait-for-dir", required_argument, 0, "wait for the specified directory to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
{"wait-for-mountpoint", required_argument, 0, "wait for the specified mountpoint to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_mountpoint, 0},
{"wait-for-fs-timeout", required_argument, 0, "set the timeout for wait-for-fs/file/dir", uwsgi_opt_set_int, &uwsgi.wait_for_fs_timeout, 0},
{"call-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
@@ -637,6 +644,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
{"sni-dir", required_argument, 0, "check for cert/key/client_ca file in the specified directory and create a sni/ssl context on demand", uwsgi_opt_set_str, &uwsgi.sni_dir, 0},
{"sni-dir-ciphers", required_argument, 0, "set ssl ciphers for sni-dir option", uwsgi_opt_set_str, &uwsgi.sni_dir_ciphers, 0},
{"ssl-enable3", no_argument, 0, "enable SSLv3 (insecure)", uwsgi_opt_true, &uwsgi.sslv3, 0},
{"ssl-option", no_argument, 0, "set a raw ssl option (numeric value)", uwsgi_opt_add_string_list, &uwsgi.ssl_options, 0},
#ifdef UWSGI_PCRE
{"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
#endif
@@ -1534,8 +1543,10 @@ static void vacuum(void) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
if (uwsgi.restore_tc) {
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
uwsgi_error("tcsetattr()");
if (getpid() == masterpid) {
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
uwsgi_error("vacuum()/tcsetattr()");
}
}
}
@@ -3282,6 +3293,8 @@ int uwsgi_run() {
}
}
uwsgi_hooks_run(uwsgi.hook_post_fork, "post-fork", 1);
if (uwsgi.worker_exec2) {
char *w_argv[2];
w_argv[0] = uwsgi.worker_exec2;
@@ -3432,7 +3445,10 @@ void uwsgi_ignition() {
if (uwsgi.has_emperor && uwsgi.mywid == 1) {
char byte = 5;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
uwsgi_error("emperor-i-am-ready-to-accept/write()");
uwsgi_log_verbose("lost communication with the Emperor, goodbye...\n");
gracefully_kill_them_all(0);
exit(1);
}
}
+12 -3
View File
@@ -312,8 +312,6 @@ static void asyncio_loop() {
uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
if (uwsgi.async < 2) {
uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
exit(1);
@@ -323,9 +321,20 @@ static void asyncio_loop() {
uwsgi_log("*** DANGER *** asyncio mode without coroutine/greenthread engine loaded !!!\n");
}
if (!uwsgi.schedule_to_req) {
uwsgi.schedule_to_req = async_schedule_to_req_green;
}
else {
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
}
#ifndef UWSGI_PYTHREE
PyObject *asyncio = PyImport_ImportModule("trollius");
#else
PyObject *asyncio = PyImport_ImportModule("asyncio");
#endif
if (!asyncio) uwsgi_pyexit;
uasyncio.mod = asyncio;
uasyncio.loop = PyObject_CallMethod(asyncio, "get_event_loop", NULL);
+1 -1
View File
@@ -196,7 +196,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
u_carbon.was_busy[i] += uwsgi_worker_is_busy(i+1);
}
needs_retry = 0;
+11 -4
View File
@@ -84,7 +84,13 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
}
// destroy a peer
void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
// first of all check if we need to run a flush procedure
if (peer->flush && !peer->is_flushing) {
peer->is_flushing = 1;
// on success, suspend the execution
if (peer->flush(peer) >= 0) return -1;
}
struct corerouter_peer *prev = peer->prev;
struct corerouter_peer *next = peer->next;
@@ -111,6 +117,7 @@ void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
uwsgi_buffer_destroy(peer->out);
}
free(peer);
return 0;
}
void uwsgi_opt_corerouter(char *opt, char *value, void *cr) {
@@ -383,7 +390,7 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
}
end:
uwsgi_cr_peer_del(peer);
if (uwsgi_cr_peer_del(peer) < 0) return;
if (peer == cs->main_peer) {
cs->main_peer = NULL;
@@ -401,7 +408,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
struct corerouter_peer *main_peer = cr_session->main_peer;
if (main_peer) {
uwsgi_cr_peer_del(main_peer);
if (uwsgi_cr_peer_del(main_peer) < 0) return;
}
// free peers
@@ -413,7 +420,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
if (ucr->subscriptions && tmp_peer->un && tmp_peer->un->len) {
tmp_peer->un->reference--;
}
uwsgi_cr_peer_del(tmp_peer);
if (uwsgi_cr_peer_del(tmp_peer) < 0) return;
}
// could be used to free additional resources
+3
View File
@@ -190,6 +190,9 @@ struct corerouter_peer {
struct corerouter_peer *next;
int current_timeout;
ssize_t (*flush)(struct corerouter_peer *);
int is_flushing;
};
struct uwsgi_corerouter {
+4
View File
@@ -46,6 +46,8 @@ struct uwsgi_http {
int connect_timeout;
int manage_source;
int enable_proxy_protocol;
int chunked_input;
int manage_rtsp;
};
struct http_session {
@@ -134,6 +136,8 @@ struct http_session {
ssize_t (*func_write)(struct corerouter_peer *);
int is_rtsp;
};
+23
View File
@@ -42,6 +42,8 @@ struct uwsgi_option http_options[] = {
{"http-raw-body", no_argument, 0, "blindly send HTTP body to backends (required for WebSockets and Icecast support in backends)", uwsgi_opt_true, &uhttp.raw_body, 0},
{"http-websockets", no_argument, 0, "automatically detect websockets connections and put the session in raw mode", uwsgi_opt_true, &uhttp.websockets, 0},
{"http-chunked-input", no_argument, 0, "automatically detect chunked input requests and put the session in raw mode", uwsgi_opt_true, &uhttp.chunked_input, 0},
{"http-use-code-string", required_argument, 0, "use code string as hostname->server mapper for the http router", uwsgi_opt_corerouter_cs, &uhttp, 0},
{"http-use-socket", optional_argument, 0, "forward request to the specified uwsgi socket", uwsgi_opt_corerouter_use_socket, &uhttp, 0},
{"http-gracetime", required_argument, 0, "retry connections to dead static nodes after the specified amount of seconds", uwsgi_opt_set_int, &uhttp.cr.static_node_gracetime, 0},
@@ -64,6 +66,7 @@ struct uwsgi_option http_options[] = {
{"http-connect-timeout", required_argument, 0, "set internal http socket timeout for backend connections", uwsgi_opt_set_int, &uhttp.connect_timeout, 0},
{"http-manage-source", no_argument, 0, "manage the SOURCE HTTP method placing the session in raw mode", uwsgi_opt_true, &uhttp.manage_source, 0},
{"http-manage-rtsp", no_argument, 0, "manage RTSP sessions", uwsgi_opt_true, &uhttp.manage_rtsp, 0},
{"http-enable-proxy-protocol", optional_argument, 0, "manage PROXY protocol requests", uwsgi_opt_true, &uhttp.enable_proxy_protocol, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -150,6 +153,11 @@ static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t
// in the future we could support chunked requests...
else if (!uwsgi_strncmp("TRANSFER_ENCODING", 17, hh, keylen)) {
hr->session.can_keepalive = 0;
if (uhttp.chunked_input) {
if (!uwsgi_strnicmp(val, vallen, "chunked", 7)) {
hr->raw_body = 1;
}
}
}
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
@@ -316,6 +324,10 @@ int http_headers_parse(struct corerouter_peer *peer) {
if (uhttp.keepalive && !uwsgi_strncmp("HTTP/1.1", 8, base, ptr-base)) {
hr->session.can_keepalive = 1;
}
if (uhttp.manage_rtsp && !uwsgi_strncmp("RTSP/1.0", 8, base, ptr-base)) {
hr->raw_body = 1;
hr->is_rtsp = 1;
}
ptr += 2;
found = 1;
break;
@@ -445,6 +457,17 @@ int http_headers_parse(struct corerouter_peer *peer) {
hv = hv->next;
}
if (hr->is_rtsp) {
if (uwsgi_starts_with("rtsp://", 7, hr->path_info, hr->path_info_len)) {
char *slash = memchr(hr->path_info + 7, '/', hr->path_info_len - 7);
if (!slash) return -1;
peer->key = hr->path_info + 7;
peer->key_len = slash - (hr->path_info + 7);
// override PATH_INFO
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, slash, hr->path_info_len - (7 + peer->key_len))) return -1;
}
}
return 0;
clear:
+42
View File
@@ -374,6 +374,47 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
return -1;
}
ssize_t hr_ssl_shutdown(struct corerouter_peer *peer) {
// ensure no hooks are set
if (uwsgi_cr_set_hooks(peer, NULL, NULL)) return -1;
struct corerouter_session *cs = peer->session;
struct http_session *hr = (struct http_session *) cs;
int ret = SSL_shutdown(hr->ssl);
if (ret < 0) return -1;
if (ret == 1) return 0;
int err = 0;
if (ERR_peek_error()) {
err = SSL_get_error(hr->ssl, ret);
}
// no error, close the connection
if (err == 0 || err == SSL_ERROR_ZERO_RETURN) return -1;
if (err == SSL_ERROR_WANT_READ) {
if (uwsgi_cr_set_hooks(peer, hr_ssl_shutdown, NULL)) return -1;
return 1;
}
else if (err == SSL_ERROR_WANT_WRITE) {
if (uwsgi_cr_set_hooks(peer, NULL, hr_ssl_shutdown)) return -1;
return 1;
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(peer, "hr_ssl_shutdown()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
ERR_print_errors_fp(stderr);
}
return -1;
}
void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
hr->ssl = SSL_new(ugs->ctx);
SSL_set_fd(hr->ssl, hr->session.main_peer->fd);
@@ -382,6 +423,7 @@ void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
SSL_set_ex_data(hr->ssl, uhttp.spdy_index, hr);
#endif
uwsgi_cr_set_hooks(hr->session.main_peer, hr_ssl_read, NULL);
hr->session.main_peer->flush = hr_ssl_shutdown;
hr->session.close = hr_session_ssl_close;
hr->func_write = hr_ssl_write;
}
+1 -1
View File
@@ -121,7 +121,7 @@ int uwsgi_buffer_msgpack_int(struct uwsgi_buffer *ub, int64_t num) {
if (num > 0 && num <= 127) {
return uwsgi_buffer_byte(ub, (uint8_t) num);
}
else if (num < 0 && num >= 31) {
else if (num < 0 && num >= -31) {
return uwsgi_buffer_byte(ub, 224 | (int8_t) num);
}
else if (num <= 127 && num >= -127) {
+13 -5
View File
@@ -659,6 +659,7 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
size_t real_filename_len = 0;
struct stat php_stat;
char *filename = NULL;
int force_empty_script_name = 0;
zend_file_handle file_handle;
@@ -727,6 +728,7 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
appready:
wsgi_req->path_info = "";
wsgi_req->path_info_len = 0;
force_empty_script_name = 1;
goto secure2;
}
@@ -856,13 +858,19 @@ secure2:
}
secure3:
wsgi_req->script_name = orig_path_info;
if (path_info) {
wsgi_req->script_name_len = path_info - orig_path_info;
if (force_empty_script_name) {
wsgi_req->script_name = "";
wsgi_req->script_name_len = 0;
}
else {
wsgi_req->script_name_len = orig_path_info_len;
}
wsgi_req->script_name = orig_path_info;
if (path_info) {
wsgi_req->script_name_len = path_info - orig_path_info;
}
else {
wsgi_req->script_name_len = orig_path_info_len;
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("php filename = %s script_name = %.*s (%d) document_root = %.*s (%d)\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->script_name_len,
+1 -1
View File
@@ -68,7 +68,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
hitem = av_fetch(response, 1, 0);
if (!hitem) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
if (!hitem || !SvRV(*hitem) || SvTYPE(SvRV(*hitem)) != SVt_PVAV) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
headers = (AV *) SvRV(*hitem);
if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
+30 -23
View File
@@ -397,6 +397,7 @@ void uwsgi_python_post_fork() {
PyErr_Clear();
if (uwsgi.mywid > 0) {
uwsgi_python_set_thread_name(0);
if (up.auto_reload) {
// spawn the reloader thread
pthread_t par_tid;
@@ -1270,11 +1271,39 @@ void uwsgi_python_enable_threads() {
up.reset_ts = threaded_reset_ts;
}
uwsgi_log("python threads support enabled\n");
}
void uwsgi_python_set_thread_name(int core_id) {
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
PyObject *threading_module = PyImport_ImportModule("threading");
if (threading_module) {
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
if (threading_module_dict) {
#ifdef PYTHREE
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
#else
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
#endif
if (threading_current) {
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
if (!current_thread) {
// ignore the error
PyErr_Clear();
}
else {
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
Py_INCREF(current_thread);
}
}
}
}
}
void uwsgi_python_init_thread(int core_id) {
// set a new ThreadState for each thread
@@ -1286,29 +1315,7 @@ void uwsgi_python_init_thread(int core_id) {
uwsgi_log("python ThreadState %d = %p\n", core_id, pts);
#endif
UWSGI_GET_GIL;
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
PyObject *threading_module = PyImport_ImportModule("threading");
if (threading_module) {
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
if (threading_module_dict) {
#ifdef PYTHREE
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
#else
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
#endif
if (threading_current) {
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
if (!current_thread) {
// ignore the error
PyErr_Clear();
}
else {
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
Py_INCREF(current_thread);
}
}
}
}
uwsgi_python_set_thread_name(core_id);
UWSGI_RELEASE_GIL;
+61
View File
@@ -27,7 +27,18 @@ char *uwsgi_python_get_thread_name(PyObject *thread_id) {
if (PyInt_AsLong(thread_ident) == PyInt_AsLong(thread_id)) {
PyObject *thread_name = PyObject_GetAttrString(threads_list_next, "name");
if (!thread_name) goto clear2;
#ifdef PYTHREE
PyObject *thread_name_utf8 = PyUnicode_AsUTF8String(thread_name);
if (!thread_name_utf8) goto clear2;
char *name = NULL;
char *tmp_name = PyString_AsString(thread_name_utf8);
if (tmp_name) {
name = uwsgi_str(tmp_name);
Py_DECREF(thread_name_utf8);
}
#else
char *name = PyString_AsString(thread_name);
#endif
Py_DECREF(threads_list_next);
Py_DECREF(threads_list_iter);
Py_DECREF(threads_list);
@@ -133,6 +144,9 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
PyObject *st_items = PyIter_Next(stacktrace_iter);
// we have the first traceback item
while(st_items) {
#ifdef PYTHREE
int thread_name_need_free = 0;
#endif
PyObject *st_filename = PyTuple_GetItem(st_items, 0);
if (!st_filename) { Py_DECREF(st_items); goto next; }
PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
@@ -149,12 +163,26 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
if (!iov[1].iov_base) {
iov[1].iov_base = "<UnnamedPythonThread>";
}
#ifdef PYTHREE
else {
thread_name_need_free = 1;
}
#endif
iov[1].iov_len = strlen(iov[1].iov_base);
iov[2].iov_base = " filename = ";
iov[2].iov_len = 12;
#ifdef PYTHREE
PyObject *st_filename_utf8 = PyUnicode_AsUTF8String(st_filename);
if (!st_filename_utf8) {
if (thread_name_need_free) free(iov[1].iov_base);
goto next;
}
iov[3].iov_base = PyString_AsString(st_filename_utf8);
#else
iov[3].iov_base = PyString_AsString(st_filename);
#endif
iov[3].iov_len = strlen(iov[3].iov_base);
iov[4].iov_base = " lineno = ";
@@ -166,7 +194,17 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
iov[6].iov_base = " function = ";
iov[6].iov_len = 12 ;
#ifdef PYTHREE
PyObject *st_name_utf8 = PyUnicode_AsUTF8String(st_name);
if (!st_name_utf8) {
if (thread_name_need_free) free(iov[1].iov_base);
Py_DECREF(st_filename_utf8);
goto next;
}
iov[7].iov_base = PyString_AsString(st_name_utf8);
#else
iov[7].iov_base = PyString_AsString(st_name);
#endif
iov[7].iov_len = strlen(iov[7].iov_base);
iov[8].iov_base = "";
@@ -178,10 +216,24 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
iov[10].iov_base = "\n";
iov[10].iov_len = 1;
#ifdef PYTHREE
PyObject *st_line_utf8 = NULL;
#endif
if (st_line) {
iov[8].iov_base = " line = ";
iov[8].iov_len = 8;
#ifdef PYTHREE
PyObject *st_line_utf8 = PyUnicode_AsUTF8String(st_line);
if (!st_line_utf8) {
if (thread_name_need_free) free(iov[1].iov_base);
Py_DECREF(st_filename_utf8);
Py_DECREF(st_name_utf8);
goto next;
}
iov[9].iov_base = PyString_AsString(st_line_utf8);
#else
iov[9].iov_base = PyString_AsString(st_line);
#endif
iov[9].iov_len = strlen(iov[9].iov_base);
}
@@ -192,6 +244,15 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
// free the line_no
free(iov[5].iov_base);
Py_DECREF(st_items);
#ifdef PYTHREE
Py_DECREF(st_filename_utf8);
Py_DECREF(st_name_utf8);
if (st_line_utf8) {
Py_DECREF(st_line_utf8);
}
if (thread_name_need_free)
free(iov[1].iov_base);
#endif
st_items = PyIter_Next(stacktrace_iter);
}
if (write(client_fd, "\n", 1) < 0) {
+2
View File
@@ -299,6 +299,8 @@ int uwsgi_python_send_body(struct wsgi_request *, PyObject *);
int uwsgi_request_python_raw(struct wsgi_request *);
void uwsgi_python_set_thread_name(int);
#define py_current_wsgi_req() current_wsgi_req();\
if (!wsgi_req) {\
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
+2 -2
View File
@@ -147,7 +147,7 @@ static int uwsgi_rados_put(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, cha
char *body = uwsgi_request_body_read(wsgi_req, UMIN(remains, 32768) , &body_len);
if (!body || body == uwsgi.empty) goto error;
if (uwsgi.async <= 1) {
if (rados_write(ctx, key, body, body_len, off) < 0) {
if (rados_write_full(ctx, key, body, body_len) < 0) {
return -1;
}
}
@@ -169,7 +169,7 @@ static int uwsgi_rados_put(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, cha
free(urcb);
goto error;
}
if (rados_aio_write(ctx, key, comp, body, body_len, off) < 0) {
if (rados_aio_write_full(ctx, key, comp, body, body_len) < 0) {
free(urcb);
rados_aio_release(comp);
goto error;
+1 -1
View File
@@ -49,7 +49,7 @@ static uint16_t http_add_uwsgi_header(struct wsgi_request *wsgi_req, char *hh, s
if (buffer + keylen + hvlen + 2 + 2 >= watermark) {
if (has_prefix) {
uwsgi_log("[WARNING] unable to add HTTP_%.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen, hh, hvlen, hv);
uwsgi_log("[WARNING] unable to add HTTP_%.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen-5, hh, hvlen, hv);
}
else {
uwsgi_log("[WARNING] unable to add %.*s=%.*s to uwsgi packet, consider increasing buffer size\n", keylen, hh, hvlen, hv);
@@ -0,0 +1,13 @@
[uwsgi]
http-socket = :8080
master = 1
; Three apps on three mountpoints
wsgi-file = %d/useless_app.py
mount = /foo=%d/useless_app.py
mount = /foobis/=%d/useless_app.py
mount = /footris/=%d/useless_app.py
manage-script-name = 1
@@ -0,0 +1,59 @@
#! /usr/bin/env python3
# coding = utf-8
# author = Adriano Di Luzio
# I require requests!
"""
First run:
$ ./uwsgi t/python/manage_script_name/manage_script_name_test.ini
Then run me!
"""
import unittest
import requests
HOST = "http://127.0.0.1:8080"
class ManageScriptNameTest(unittest.TestCase):
def test_classic_mountpoints(self):
mps = {
"/foo",
"/foobis/",
"/footris/"
}
for mp in mps:
# Requests to /foo should kick-in the managed script name.
r = requests.get(HOST + mp)
self.assertEqual(r.text, mp)
ends = mp.endswith("/")
# And equally requests to /foo/
r = requests.get(
HOST + mp + "/") if not ends else requests.get(HOST + mp[:-1])
self.assertEqual(r.text, mp)
# Or correct requests (/foo/resource)
r = requests.get(
HOST + mp + "/" + "resource") if not ends else requests.get(HOST + mp + "resource")
self.assertEqual(r.text, mp)
def test_intriguing_mountpoints(self):
mps = {
"/fooanything",
"/foobisis/",
"/foofighters",
}
for mp in mps:
r = requests.get(HOST + mp)
self.assertEqual(r.text, "")
if __name__ == '__main__':
unittest.main(verbosity=2)
@@ -0,0 +1,3 @@
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return env['SCRIPT_NAME']
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2014-09-05'
s.date = '2014-10-26'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+43
View File
@@ -8,6 +8,8 @@ extern "C" {
#define UWSGI_PLUGIN_API 1
#define UWSGI_HAS_OFFLOAD_UBUFS 1
#define UMAX16 65536
#define UMAX8 256
@@ -836,6 +838,9 @@ struct uwsgi_cache {
uint64_t lru_tail;
int store_delete;
int lazy_expire;
uint64_t sweep_on_full;
int clear_on_full;
};
struct uwsgi_option {
@@ -2736,6 +2741,18 @@ struct uwsgi_server {
// uWSGI 2.0.7
int vassal_sos;
// uWSGI 2.0.8
struct uwsgi_string_list *wait_for_fs;
struct uwsgi_string_list *wait_for_dir;
struct uwsgi_string_list *wait_for_file;
int wait_for_fs_timeout;
struct uwsgi_string_list *wait_for_mountpoint;
#ifdef UWSGI_SSL
int sslv3;
struct uwsgi_string_list *ssl_options;
#endif
struct uwsgi_string_list *hook_post_fork;
};
struct uwsgi_rpc {
@@ -3071,6 +3088,7 @@ struct wsgi_request *find_first_accepting_wsgi_req(void);
struct wsgi_request *find_wsgi_req_by_fd(int);
struct wsgi_request *find_wsgi_req_by_id(int);
void async_schedule_to_req_green(void);
void async_schedule_to_req(void);
int async_add_fd_write(struct wsgi_request *, int, int);
int async_add_fd_read(struct wsgi_request *, int, int);
@@ -4244,6 +4262,28 @@ struct uwsgi_offload_request {
struct uwsgi_offload_request *prev;
struct uwsgi_offload_request *next;
// added in 2.1
struct uwsgi_buffer *ubuf1;
struct uwsgi_buffer *ubuf2;
struct uwsgi_buffer *ubuf3;
struct uwsgi_buffer *ubuf4;
struct uwsgi_buffer *ubuf5;
struct uwsgi_buffer *ubuf6;
struct uwsgi_buffer *ubuf7;
struct uwsgi_buffer *ubuf8;
int64_t custom1;
int64_t custom2;
int64_t custom3;
int64_t custom4;
int64_t custom5;
int64_t custom6;
int64_t custom7;
int64_t custom8;
void *data;
void (*free)(struct uwsgi_offload_request *);
};
struct uwsgi_offload_engine {
@@ -4802,6 +4842,9 @@ int uwsgi_notify_socket_manage(int);
int uwsgi_notify_msg(char *, char *, size_t);
void vassal_sos();
int uwsgi_wait_for_fs(char *, int);
int uwsgi_wait_for_mountpoint(char *);
#ifdef __cplusplus
}
#endif
+18 -10
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '2.0.7'
uwsgi_version = '2.0.8'
import os
import re
@@ -403,18 +403,26 @@ def build_uwsgi(uc, print_only=False, gcll=None):
path = path.rstrip('/')
if not os.path.isdir(path):
up = {}
if os.path.isfile(path):
bname = os.path.basename(path)
# override path
path = os.path.dirname(path)
up['GCC_LIST'] = [bname]
up['NAME'] = bname.split('.')[0]
if not path: path = '.'
elif os.path.isdir(path):
try:
execfile('%s/uwsgiplugin.py' % path, up)
except:
f = open('%s/uwsgiplugin.py' % path)
exec(f.read(), up)
f.close()
else:
print("Error: plugin '%s' not found" % p)
sys.exit(1)
up = {}
try:
execfile('%s/uwsgiplugin.py' % path, up)
except:
f = open('%s/uwsgiplugin.py' % path)
exec(f.read(), up)
f.close()
p_cflags = cflags[:]
try:
p_cflags += up['CFLAGS']
+28 -3
View File
@@ -18,6 +18,29 @@ mule_functions = {}
postfork_chain = []
# Python3 compatibility
def _encode1(val):
if sys.version_info >= (3, 0) and isinstance(val, str):
return val.encode('utf-8')
else:
return val
def _decode1(val):
if sys.version_info >= (3, 0) and isinstance(val, bytes):
return val.decode('utf-8')
else:
return val
def _encode_to_spooler(vars):
return dict((_encode1(K), _encode1(V)) for (K, V) in vars.items())
def _decode_from_spooler(vars):
return dict((_decode1(K), _decode1(V)) for (K, V) in vars.items())
def get_free_signal():
for signum in range(0, 256):
if not uwsgi.signal_registered(signum):
@@ -27,6 +50,7 @@ def get_free_signal():
def manage_spool_request(vars):
vars = _decode_from_spooler(vars)
f = spooler_functions[vars['ud_spool_func']]
if 'args' in vars:
args = pickle.loads(vars.pop('args'))
@@ -67,7 +91,7 @@ class postfork(object):
class _spoolraw(object):
def __call__(self, *args, **kwargs):
arguments = self.base_dict
arguments = self.base_dict.copy()
if not self.pass_arguments:
if len(args) > 0:
arguments.update(args[0])
@@ -79,8 +103,9 @@ class _spoolraw(object):
if key in kwargs:
spooler_args.update({key: kwargs.pop(key)})
arguments.update(spooler_args)
arguments.update({'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
return uwsgi.spool(arguments)
arguments.update(
{'args': pickle.dumps(args), 'kwargs': pickle.dumps(kwargs)})
return uwsgi.spool(_encode_to_spooler(arguments))
# For backward compatibility (uWSGI < 1.9.13)
def spool(self, *args, **kwargs):