Compare commits

..
32 Commits
Author SHA1 Message Date
Unbit 37bc47cb82 uWSGI 2.0.11.1 2015-07-19 08:17:07 +02:00
Unbit 35701f6ac6 fixed #963 2015-07-19 08:11:06 +02:00
Roberto De Ioris fb23d4a8ae Merge branch 'uwsgi-2.0' of https://github.com/unbit/uwsgi into uwsgi-2.0 2015-07-13 13:25:23 +02:00
Unbit 30c667d34f added unix signal registration hook 2015-07-06 16:11:53 +02:00
Unbit d09fd561b6 uWSGI 2.0.11 2015-07-01 08:53:41 +02:00
Roberto De Ioris ff05c16577 Merge branch 'uwsgi-2.0' of https://github.com/unbit/uwsgi into uwsgi-2.0 2015-07-01 08:51:04 +02:00
Unbit eefaa98cf3 backported pypy fixes from 2.1 2015-07-01 08:37:40 +02:00
Fabrizio Gennari 9c4d563c72 Check whether *value is indeed an SvRV before casting it 2015-07-01 06:12:54 +02:00
James Oakley ceda8a41e3 Fix version detection for gcc 5 2015-06-30 08:05:41 +02:00
Unbit 3021ba3f85 ensure the mem_collector does not receive signals 2015-06-16 18:30:19 +02:00
Roberto De Ioris 3be7312aa8 added fixpathinfo routing action 2015-06-07 19:37:48 +02:00
Roberto De Ioris 83d782051c fixed shared sockets for gateways 2015-06-03 07:23:16 +02:00
protoCall7 70996049cc Changed abs to labs because offset is declared as a long 2015-06-02 09:03:30 +02:00
Jay Oster e219e209a0 Add null terminator to uwsgi_get_dot_h() and uwsgi_config_py()
- Fixes #933
2015-06-02 09:00:01 +02:00
Unbit eb728cfe23 added sor and micros routing vars 2015-05-28 12:24:03 +02:00
unbit 7569544329 Merge pull request #929 from hulu/wait-init-thread-last
Wait for initial thread last.
2015-05-23 05:19:56 +02:00
Roberto De Ioris ee86bf593d fixed #649 2015-05-23 05:16:24 +02:00
Roberto De Ioris 27ea120325 added memory collector 2015-05-17 05:50:35 +02:00
Unbit dd21877dcb attempt to fix a bug spotted by funkybob on irc 2015-05-15 06:41:31 +02:00
Roberto De Ioris 36ca76a231 backported coverity fixes by riccardo #908 2015-05-14 06:28:52 +02:00
Unbit 0e339cf968 added bigranges sharedarea tests 2015-05-13 15:45:26 +02:00
Unbit 762200fdd6 fixed #922 2015-05-13 15:09:18 +02:00
Roberto De Ioris 688a464451 fixed #914 2015-05-12 06:28:06 +02:00
Roberto De Ioris 0dafe8aa5e backported gzip fix 2015-05-08 06:59:52 +02:00
Roberto De Ioris 5410cb4fe7 backported ssl ca management fix 2015-05-06 07:25:18 +02:00
Charlie Root 86f55a69cf fixed OpenBSD build on 2.0 2015-05-02 13:00:31 +02:00
Roberto De Ioris 6bd59ffe1c backported #848 2015-05-01 13:35:25 +02:00
Roberto De Ioris 95a139f73d backported wait-for-socket and wait_for hooks 2015-05-01 13:32:50 +02:00
Roberto De Ioris 2e71d62704 added Curtis Maloney to CONTRIBUTORS 2015-04-13 06:53:35 +02:00
Roberto De Ioris 8942e832e9 backported build fix from 2.1 2015-04-13 06:53:19 +02:00
Unbit 14b0a512e4 fixed #883 2015-04-10 15:53:42 +02:00
Unbit 0c062bbc1a fixed typo 2015-03-25 09:41:07 +01:00
33 changed files with 408 additions and 64 deletions
+2
View File
@@ -30,3 +30,5 @@ Danila Shtan <danila@shtan.ru>
Yu Zhao (getcwd)
Mathieu Dupuy
Adriano Di Luzio (adriano@unbit.it)
Curtis Maloney
Vladimir Didenko
+3
View File
@@ -2295,6 +2295,9 @@ void uwsgi_check_emperor() {
}
free(env_emperor_fd_config);
}
if (fds)
free(fds);
close(proxy_fd);
break;
}
next:
+1 -1
View File
@@ -72,7 +72,7 @@ void gateway_respawn(int id) {
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
uwsgi_close_all_sockets();
uwsgi_close_all_unshared_sockets();
if (uwsgi.master_as_root)
uwsgi_as_root();
#ifdef __linux__
+42
View File
@@ -407,6 +407,24 @@ static int uwsgi_hook_hostname(char *arg) {
#endif
}
static int uwsgi_hook_unix_signal(char *arg) {
char *space = strchr(arg, ' ');
if (!space) {
uwsgi_log("invalid unix_signal syntax, must be <signum> <func>\n");
return -1;
}
*space = 0;
int signum = atoi(arg);
*space = ' ';
void (*func)(int) = dlsym(RTLD_DEFAULT, space+1);
if (!func) {
uwsgi_log("unable to find function \"%s\"\n", space+1);
return -1;
}
uwsgi_unix_signal(signum, func);
return 0;
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
@@ -557,6 +575,22 @@ static int uwsgi_hook_retryrpc(char *arg) {
return 0;
}
static int uwsgi_hook_wait_for_fs(char *arg) {
return uwsgi_wait_for_fs(arg, 0);
}
static int uwsgi_hook_wait_for_file(char *arg) {
return uwsgi_wait_for_fs(arg, 1);
}
static int uwsgi_hook_wait_for_dir(char *arg) {
return uwsgi_wait_for_fs(arg, 2);
}
static int uwsgi_hook_wait_for_socket(char *arg) {
return uwsgi_wait_for_socket(arg);
}
void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("chdir", uwsgi_hook_chdir);
@@ -598,6 +632,14 @@ void uwsgi_register_base_hooks() {
uwsgi_register_hook("rpc", uwsgi_hook_rpc);
uwsgi_register_hook("retryrpc", uwsgi_hook_retryrpc);
uwsgi_register_hook("wait_for_fs", uwsgi_hook_wait_for_fs);
uwsgi_register_hook("wait_for_file", uwsgi_hook_wait_for_file);
uwsgi_register_hook("wait_for_dir", uwsgi_hook_wait_for_dir);
uwsgi_register_hook("wait_for_socket", uwsgi_hook_wait_for_socket);
uwsgi_register_hook("unix_signal", uwsgi_hook_unix_signal);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
+4
View File
@@ -471,6 +471,10 @@ void sanitize_args() {
exit(1);
}
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
if (!uwsgi.mem_collector_freq) uwsgi.mem_collector_freq = 3;
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
+6 -8
View File
@@ -277,14 +277,12 @@ static void legions_check_nodes_step2() {
memcpy(best_uuid, node->uuid, 36);
}
// go on if i am not an arbiter
else if (ul->valor > 0) {
// no potential Lord is available, i will propose myself
// but only if i am not suspended...
if (uwsgi_now() > ul->suspended_til) {
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
// no potential Lord is available, i will propose myself
// but only if i am not suspended...
else if (ul->valor > 0 && uwsgi_now() > ul->suspended_til) {
best_valor = ul->valor;
memcpy(best_uuid, ul->uuid, 36);
i_am_the_best = 1;
}
else {
// empty lord
+1 -4
View File
@@ -3,6 +3,7 @@
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <sys/user.h>
#include <sys/sysctl.h>
#include <kvm.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
@@ -13,10 +14,6 @@
#define _FILE_OFFSET_BITS 64
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif
#ifdef __DragonFly__
#include <uwsgi.h>
#endif
+7 -1
View File
@@ -39,6 +39,8 @@ int uwsgi_master_check_reload(char **argv) {
// check for chain reload
void uwsgi_master_check_chain() {
static time_t last_check = 0;
if (!uwsgi.status.chain_reloading) return;
// we need to ensure the previous worker (if alive) is accepting new requests
@@ -49,7 +51,11 @@ void uwsgi_master_check_chain() {
if (previous_worker->pid > 0 && !previous_worker->cheaped) {
// the worker has been respawned but it is still not ready
if (previous_worker->accepting == 0) {
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
time_t now = uwsgi_now();
if (now != last_check) {
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
last_check = now;
}
return;
}
}
+30
View File
@@ -1215,6 +1215,27 @@ static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
return 0;
}
// fixpathinfo route
static int uwsgi_router_fixpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
if (wsgi_req->script_name_len == 0)
return UWSGI_ROUTE_NEXT;
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info+wsgi_req->script_name_len, wsgi_req->path_info_len - wsgi_req->script_name_len);
if (!ptr) {
return UWSGI_ROUTE_BREAK;
}
wsgi_req->path_info = wsgi_req->path_info+wsgi_req->script_name_len;
wsgi_req->path_info_len = wsgi_req->path_info_len - wsgi_req->script_name_len;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_router_fixpathinfo(struct uwsgi_route *ur, char *arg) {
ur->func = uwsgi_router_fixpathinfo_func;
ur->data = arg;
ur->data_len = strlen(arg);
return 0;
}
// setscheme route
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
@@ -1778,6 +1799,10 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
ret = uwsgi_64bit2str(wsgi_req->response_size);
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "sor", 3)) {
ret = uwsgi_64bit2str(wsgi_req->start_of_request);
*vallen = strlen(ret);
}
return ret;
}
@@ -1814,6 +1839,10 @@ static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint
ret = uwsgi_num2str(uwsgi_now());
*vallen = strlen(ret);
}
else if (!uwsgi_strncmp(key, keylen, "micros", 6)) {
ret = uwsgi_64bit2str(uwsgi_micros());
*vallen = strlen(ret);
}
return ret;
}
@@ -1871,6 +1900,7 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_router("seturi", uwsgi_router_seturi);
uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr);
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
uwsgi_register_router("fixpathinfo", uwsgi_router_fixpathinfo);
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
+9 -9
View File
@@ -280,8 +280,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t of
}
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = fd;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
@@ -292,12 +292,12 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t of
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
int id = uwsgi_sharedarea_new_id();
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
uwsgi.sharedareas[id] = uwsgi_calloc_shared((size_t)uwsgi.page_size * (size_t)(pages + 1));
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + (size_t) uwsgi.page_size;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = pages;
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
uwsgi.sharedareas[id]->max_pos = ((size_t)uwsgi.page_size * (size_t)pages) -1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
free(id_str);
@@ -310,8 +310,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
uwsgi.sharedareas[id]->area = area;
uwsgi.sharedareas[id]->id = id;
uwsgi.sharedareas[id]->fd = -1;
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
uwsgi.sharedareas[id]->max_pos = len-1;
char *id_str = uwsgi_num2str(id);
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
@@ -348,8 +348,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
else {
len = uwsgi_n64(s_size);
}
pages = len / uwsgi.page_size;
if (len % uwsgi.page_size != 0) pages++;
pages = len / (size_t) uwsgi.page_size;
if (len % (size_t) uwsgi.page_size != 0) pages++;
}
if (s_offset) {
+11 -1
View File
@@ -1249,10 +1249,20 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
}
void uwsgi_close_all_sockets() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound)
close(uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
}
void uwsgi_close_all_unshared_sockets() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->bound)
if (uwsgi_sock->bound && !uwsgi_sock->shared)
close(uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
+12 -1
View File
@@ -30,7 +30,18 @@ void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
}
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
return 1;
if (!ok && uwsgi.ssl_verbose) {
char buf[256];
X509 *err_cert;
int depth;
int err;
depth = X509_STORE_CTX_get_error_depth(x509_store);
err_cert = X509_STORE_CTX_get_current_cert(x509_store);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
err = X509_STORE_CTX_get_error(x509_store);
uwsgi_log("[uwsgi-ssl] client certificate verify error: num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf);
}
return ok;
}
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
+28 -1
View File
@@ -3514,7 +3514,7 @@ int uwsgi_tmpfd() {
tmpdir = "/tmp";
}
#ifdef O_TMPFILE
fd = open(tmpdir, O_TMPFILE | O_RDWR);
fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
if (fd >= 0) {
return fd;
}
@@ -4446,6 +4446,7 @@ void uwsgi_setns(char *path) {
}
}
free(fds);
close(ns_fd);
break;
}
if (fds)
@@ -4510,6 +4511,7 @@ retry:
sleep(1);
counter++;
}
return -1;
}
// type -> 1 file, 2 dir, 0 both
@@ -4534,4 +4536,29 @@ retry:
sleep(1);
counter++;
}
return -1;
}
int uwsgi_wait_for_socket(char *socket_name) {
if (!uwsgi.wait_for_socket_timeout) {
uwsgi.wait_for_socket_timeout = 60;
}
uwsgi_log("waiting for %s (max %d seconds) ...\n", socket_name, uwsgi.wait_for_socket_timeout);
int counter = 0;
for (;;) {
if (counter > uwsgi.wait_for_socket_timeout) {
uwsgi_log("%s unavailable after %d seconds\n", socket_name, counter);
return -1;
}
// wait for 1 second to respect uwsgi.wait_for_fs_timeout
int fd = uwsgi_connect(socket_name, 1, 0);
if (fd < 0) goto retry;
close(fd);
uwsgi_log_verbose("%s ready\n", socket_name);
return 0;
retry:
sleep(1);
counter++;
}
return -1;
}
+59 -4
View File
@@ -469,6 +469,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"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},
{"wait-for-socket", required_argument, 0, "wait for the specified socket to be ready before loading apps", uwsgi_opt_add_string_list, &uwsgi.wait_for_socket, 0},
{"wait-for-socket-timeout", required_argument, 0, "set the timeout for wait-for-socket", uwsgi_opt_set_int, &uwsgi.wait_for_socket_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},
@@ -518,6 +521,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"reload-on-rss", required_argument, 0, "reload if rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_rss, UWSGI_OPT_MEMORY},
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
{"mem-collector-freq", required_argument, 0, "set the memory collector frequency when evil reloads are in place", uwsgi_opt_set_int, &uwsgi.mem_collector_freq, 0},
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
@@ -1176,7 +1180,7 @@ void wait_for_threads() {
int sudden_death = 0;
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
for (i = 0; i < uwsgi.threads; i++) {
for (i = 1; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[i].thread_id)) {
uwsgi_error("pthread_cancel()\n");
@@ -1189,7 +1193,7 @@ void wait_for_threads() {
goto end;
// wait for thread termination
for (i = 0; i < uwsgi.threads; i++) {
for (i = 1; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, NULL);
if (ret) {
@@ -1198,6 +1202,22 @@ void wait_for_threads() {
}
}
// cancel inital thread last since after pthread_cancel() and
// pthread_join() is called on it, the whole process will appear to be
// a zombie. although it won't eliminate process zombie time, but it
// should minimize it.
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, pthread_self())) {
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[0].thread_id)) {
uwsgi_error("pthread_cancel() on initial thread\n");
goto end;
}
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, NULL);
if (ret) {
uwsgi_log("pthread_join() = %d on initial thread\n", ret);
}
}
end:
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
@@ -2544,6 +2564,11 @@ int uwsgi_start(void *v_argv) {
uwsgi_as_root();
}
// wait for socket
uwsgi_foreach(usl, uwsgi.wait_for_socket) {
if (uwsgi_wait_for_socket(usl->value)) exit(1);
}
if (uwsgi.logto2) {
if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
logto(uwsgi.logto2);
@@ -3212,6 +3237,24 @@ next2:
}
// this lives in a worker thread and periodically scans for memory usage
// when evil reloaders are in place
void *mem_collector(void *foobar) {
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
uwsgi_log_verbose("mem-collector thread started for worker %d\n", uwsgi.mywid);
for(;;) {
sleep(uwsgi.mem_collector_freq);
uint64_t rss, vsz;
get_memusage(&rss, &vsz);
uwsgi.workers[uwsgi.mywid].rss_size = rss;
uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
}
return NULL;
}
int uwsgi_run() {
// !!! from now on, we could be in the master or in a worker !!!
@@ -3238,6 +3281,11 @@ int uwsgi_run() {
}
#endif
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
pthread_t t;
pthread_create(&t, NULL, mem_collector, NULL);
}
// eventually maps (or disable) sockets for the worker
uwsgi_map_sockets();
@@ -4415,6 +4463,7 @@ int uwsgi_zerg_attach(char *value) {
if (zerg == NULL) {
uwsgi_log("--- invalid data received from zerg-server ---\n");
close(zerg_fd);
return -1;
}
@@ -4710,7 +4759,7 @@ extern char *uwsgi_dot_h;
char *uwsgi_get_dot_h() {
char *src = uwsgi_dot_h;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
@@ -4731,6 +4780,9 @@ char *uwsgi_get_dot_h() {
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#else
// add final null byte
*ptr = '\0';
#endif
return base;
}
@@ -4743,7 +4795,7 @@ extern char *uwsgi_config_py;
char *uwsgi_get_config_py() {
char *src = uwsgi_config_py;
size_t len = strlen(src);
char *ptr = uwsgi_malloc(len / 2);
char *ptr = uwsgi_malloc((len / 2) + 1);
char *base = ptr;
size_t i;
unsigned int u;
@@ -4764,6 +4816,9 @@ char *uwsgi_get_config_py() {
base = ub->buf;
ub->buf = NULL;
uwsgi_buffer_destroy(ub);
#else
// add final null byte
*ptr = '\0';
#endif
return base;
}
+1 -1
View File
@@ -533,9 +533,9 @@ static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
memcpy(full_path, tmp_path, full_path_len+1);
if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) {
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
if (need_free)
free(docroot);
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
return -1;
}
+1 -1
View File
@@ -95,7 +95,7 @@ int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
if (peer->flush && !peer->is_flushing) {
peer->is_flushing = 1;
// on success, suspend the execution
if (peer->flush(peer) >= 0) return -1;
if (peer->flush(peer) > 0) return -1;
}
struct corerouter_peer *prev = peer->prev;
struct corerouter_peer *next = peer->next;
+6 -3
View File
@@ -320,7 +320,8 @@ ssize_t hr_ssl_write(struct corerouter_peer *main_peer) {
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(main_peer, "hr_ssl_write()");
if (errno != 0)
uwsgi_cr_error(main_peer, "hr_ssl_write()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
@@ -380,7 +381,8 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(main_peer, "hr_ssl_read()");
if (errno != 0)
uwsgi_cr_error(main_peer, "hr_ssl_read()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
@@ -420,7 +422,8 @@ ssize_t hr_ssl_shutdown(struct corerouter_peer *peer) {
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(peer, "hr_ssl_shutdown()");
if (errno != 0)
uwsgi_cr_error(peer, "hr_ssl_shutdown()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
+2 -2
View File
@@ -144,7 +144,7 @@ XS(XS_input_read) {
else {
long orig_offset = 0;
// first of all get the new orig_len;
offset = abs(offset);
offset = labs(offset);
if (offset > (long) orig_len) {
new_size = offset;
orig_offset = offset - orig_len;
@@ -285,7 +285,7 @@ nonworker:
uwsgi_log("[perl] WARNING !!! unable to build uwsgi::opt hash !!!\n");
goto end;
}
if (SvTYPE(SvRV(*value)) == SVt_PVAV) {
if (SvROK(*value) && SvTYPE(SvRV(*value)) == SVt_PVAV) {
if (uwsgi.exported_opts[i]->value == NULL) {
av_push((AV *)SvRV(*value), newSViv(1));
}
+12 -12
View File
@@ -393,7 +393,7 @@ class WSGIinput(object):
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
return ffi.buffer(chunk, rlen[0])[:]
if rlen[0] < 0:
raise IOError("error reading wsgi.input")
raise IOError("error waiting for wsgi.input")
@@ -402,7 +402,7 @@ class WSGIinput(object):
rlen = ffi.new('ssize_t*')
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
if chunk != ffi.NULL:
return ffi.string(chunk, rlen[0])
return ffi.buffer(chunk, rlen[0])[:]
if rlen[0] < 0:
raise IOError("error reading line from wsgi.input")
raise IOError("error waiting for line on wsgi.input")
@@ -521,7 +521,7 @@ class uwsgi_pypy_RPC(object):
def __call__(self, argc, argv, argvs, buf):
pargs = []
for i in range(0, argc):
pargs.append(ffi.string(argv[i], argvs[i]))
pargs.append(ffi.buffer(argv[i], argvs[i])[:])
response = self.func(*pargs)
if len(response) > 0:
buf[0] = lib.uwsgi_malloc(len(response))
@@ -560,7 +560,7 @@ def uwsgi_pypy_rpc(node, func, *args):
response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize)
if response:
ret = ffi.string(response, rsize[0])
ret = ffi.buffer(response, rsize[0])[:]
lib.free(response)
return ret
return None
@@ -587,7 +587,7 @@ def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache)
if value == ffi.NULL:
return None
ret = ffi.string(value, vallen[0])
ret = ffi.buffer(value, vallen[0])[:]
libc.free(value)
return ret
uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get
@@ -617,8 +617,9 @@ def uwsgi_pypy_uwsgi_cache_keys(cache=ffi.NULL):
uci = ffi.new('struct uwsgi_cache_item **')
while True:
uci[0] = lib.uwsgi_cache_keys(uc, pos, uci)
if uci[0] == ffi.NULL: break
l.append(ffi.string(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize))
if uci[0] == ffi.NULL:
break
l.append(ffi.buffer(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize)[:])
lib.uwsgi_cache_rwunlock(uc)
return l
uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys
@@ -849,7 +850,7 @@ def uwsgi_pypy_websocket_recv():
ub = lib.uwsgi_websocket_recv(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
ret = ffi.buffer(ub.buf, ub.pos)[:]
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
@@ -862,7 +863,7 @@ def uwsgi_pypy_websocket_recv_nb():
ub = lib.uwsgi_websocket_recv_nb(wsgi_req);
if ub == ffi.NULL:
raise IOError("unable to receive websocket message")
ret = ffi.string(ub.buf, ub.pos)
ret = ffi.buffer(ub.buf, ub.pos)[:]
lib.uwsgi_buffer_destroy(ub)
return ret
uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
@@ -897,7 +898,7 @@ def uwsgi_pypy_chunked_read(timeout=0):
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
if chunk == ffi.NULL:
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
return ffi.buffer(chunk, rlen[0])[:]
uwsgi.chunked_read = uwsgi_pypy_chunked_read
"""
@@ -911,8 +912,7 @@ def uwsgi_pypy_chunked_read_nb():
if lib.uwsgi_is_again() > 0:
return None
raise IOError("unable to receive chunked part")
return ffi.string(chunk, rlen[0])
return ffi.buffer(chunk, rlen[0])[:]
uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
"""
+3 -1
View File
@@ -88,7 +88,7 @@ struct uwsgi_option uwsgi_python_options[] = {
{"module", required_argument,'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
{"wsgi", required_argument, 'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
{"callable", required_argument, 0, "set default WSGI callable name", uwsgi_opt_set_str, &up.callable, 0},
{"test", required_argument, 'J', "test a mdule import", uwsgi_opt_set_str, &up.test_module, 0},
{"test", required_argument, 'J', "test a module import", uwsgi_opt_set_str, &up.test_module, 0},
{"home", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
@@ -1670,6 +1670,8 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
PyDict_SetItemString(spool_dict, "body", value);
Py_DECREF(value);
}
// PyTuple_SetItem steals a reference !!!
Py_INCREF(spool_dict);
PyTuple_SetItem(pyargs, 0, spool_dict);
ret = python_call(spool_func, pyargs, 0, NULL);
+69
View File
@@ -1448,6 +1448,72 @@ PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
}
PyObject *py_uwsgi_sharedarea_inc32(PyObject * self, PyObject * args) {
int id;
uint64_t pos = 0;
int32_t value = 1;
if (!PyArg_ParseTuple(args, "iL|i:sharedarea_inc32", &id, &pos, &value)) {
return NULL;
}
UWSGI_RELEASE_GIL
int ret = uwsgi_sharedarea_inc32(id, pos, value);
UWSGI_GET_GIL
if (ret) {
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_inc32()");
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_sharedarea_dec64(PyObject * self, PyObject * args) {
int id;
uint64_t pos = 0;
int64_t value = 1;
if (!PyArg_ParseTuple(args, "iL|l:sharedarea_dec64", &id, &pos, &value)) {
return NULL;
}
UWSGI_RELEASE_GIL
int ret = uwsgi_sharedarea_dec64(id, pos, value);
UWSGI_GET_GIL
if (ret) {
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec64()");
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_sharedarea_dec32(PyObject * self, PyObject * args) {
int id;
uint64_t pos = 0;
int32_t value = 1;
if (!PyArg_ParseTuple(args, "iL|i:sharedarea_dec32", &id, &pos, &value)) {
return NULL;
}
UWSGI_RELEASE_GIL
int ret = uwsgi_sharedarea_dec32(id, pos, value);
UWSGI_GET_GIL
if (ret) {
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec32()");
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_sharedarea_write32(PyObject * self, PyObject * args) {
int id;
uint64_t pos = 0;
@@ -2569,6 +2635,9 @@ static PyMethodDef uwsgi_sa_methods[] = {
{"sharedarea_write16", py_uwsgi_sharedarea_write16, METH_VARARGS, ""},
{"sharedarea_inclong", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
{"sharedarea_inc64", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
{"sharedarea_inc32", py_uwsgi_sharedarea_inc32, METH_VARARGS, ""},
{"sharedarea_dec64", py_uwsgi_sharedarea_dec64, METH_VARARGS, ""},
{"sharedarea_dec32", py_uwsgi_sharedarea_dec32, METH_VARARGS, ""},
{"sharedarea_rlock", py_uwsgi_sharedarea_rlock, METH_VARARGS, ""},
{"sharedarea_wlock", py_uwsgi_sharedarea_wlock, METH_VARARGS, ""},
{"sharedarea_unlock", py_uwsgi_sharedarea_unlock, METH_VARARGS, ""},
+4 -2
View File
@@ -250,7 +250,8 @@ static ssize_t sr_write(struct corerouter_peer *main_peer) {
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(main_peer, "sr_write()");
if (errno != 0)
uwsgi_cr_error(main_peer, "sr_write()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
@@ -332,7 +333,8 @@ static ssize_t sr_read(struct corerouter_peer *main_peer) {
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_cr_error(main_peer, "sr_ssl_read()");
if (errno != 0)
uwsgi_cr_error(main_peer, "sr_ssl_read()");
}
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
+8 -3
View File
@@ -24,7 +24,7 @@ static int transform_gzip(struct wsgi_request *wsgi_req, struct uwsgi_transforma
struct uwsgi_buffer *ub = ut->chunk;
if (ut->is_final) {
if (uwsgi_gzip_fix(&utgz->z, utgz->crc32, ub, utgz->len)) {
if (utgz->len > 0 && uwsgi_gzip_fix(&utgz->z, utgz->crc32, ub, utgz->len)) {
free(utgz);
return -1;
}
@@ -32,6 +32,11 @@ static int transform_gzip(struct wsgi_request *wsgi_req, struct uwsgi_transforma
return 0;
}
if (ub->pos == 0) {
// Don't try to compress empty responses.
return 0;
}
size_t dlen = 0;
char *gzipped = uwsgi_gzip_chunk(&utgz->z, &utgz->crc32, ub->buf, ub->pos, &dlen);
if (!gzipped) return -1;
@@ -39,7 +44,7 @@ static int transform_gzip(struct wsgi_request *wsgi_req, struct uwsgi_transforma
uwsgi_buffer_map(ub, gzipped, dlen);
if (!utgz->header) {
// do not check for errors !!!
uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4);
uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4);
utgz->header = 1;
if (uwsgi_buffer_insert(ub, 0, gzheader, 10)) {
return -1;
@@ -59,7 +64,7 @@ static int uwsgi_routing_func_gzip(struct wsgi_request *wsgi_req, struct uwsgi_r
ut->can_stream = 1;
// this is the trasformation clearing the memory
ut = uwsgi_add_transformation(wsgi_req, transform_gzip, utgz);
ut->is_final = 1;
ut->is_final = 1;
return UWSGI_ROUTE_NEXT;
}
+4 -2
View File
@@ -287,7 +287,8 @@ retry:
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_ssl_write()/SSL_write()");
if (errno != 0)
uwsgi_error("uwsgi_proto_ssl_write()/SSL_write()");
}
return -1;
@@ -383,7 +384,8 @@ retry:
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_ssl_read_body()/SSL_read()");
if (errno != 0)
uwsgi_error("uwsgi_proto_ssl_read_body()/SSL_read()");
}
return -1;
+2 -1
View File
@@ -760,7 +760,8 @@ retry:
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_https_parser()/SSL_read()");
if (errno != 0)
uwsgi_error("uwsgi_proto_https_parser()/SSL_read()");
}
return -1;
empty:
+2 -1
View File
@@ -83,7 +83,8 @@ retry:
}
else if (err == SSL_ERROR_SYSCALL) {
uwsgi_error("uwsgi_proto_suwsgi_parser()/SSL_read()");
if (errno != 0)
uwsgi_error("uwsgi_proto_suwsgi_parser()/SSL_read()");
}
return -1;
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
socket = /tmp/foo
sharedarea = size=4300000000
pyrun = t/sharedarea/%n.py
+16
View File
@@ -0,0 +1,16 @@
import uwsgi
import unittest
class SharedareaTest(unittest.TestCase):
def test_32(self):
pos = 2L * (1024L ** 3)
uwsgi.sharedarea_write32(0, pos, 17)
self.assertEqual(uwsgi.sharedarea_read32(0, pos), 17)
def test_64(self):
pos = 2L * (1024L ** 3)
uwsgi.sharedarea_write64(0, pos, 30)
self.assertEqual(uwsgi.sharedarea_read64(0, pos), 30)
unittest.main()
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
socket = /tmp/foo
sharedarea = size=64
pyrun = t/sharedarea/%n.py
+34
View File
@@ -0,0 +1,34 @@
import uwsgi
import unittest
class SharedareaTest(unittest.TestCase):
def setUp(self):
uwsgi.sharedarea_write(0, 0, '\0' * 64)
def test_32(self):
uwsgi.sharedarea_write32(0, 0, 17)
self.assertEqual(uwsgi.sharedarea_read32(0, 0), 17)
def test_inc32(self):
uwsgi.sharedarea_write32(0, 4, 30)
uwsgi.sharedarea_inc32(0, 4, 3)
self.assertEqual(uwsgi.sharedarea_read32(0, 4), 33)
def test_dec32(self):
uwsgi.sharedarea_write32(0, 5, 30)
uwsgi.sharedarea_dec32(0, 5, 4)
self.assertEqual(uwsgi.sharedarea_read32(0, 5), 26)
def test_inc64(self):
uwsgi.sharedarea_write64(0, 8, 17 * (1024 ** 5))
uwsgi.sharedarea_inc64(0, 8, 1)
self.assertEqual(uwsgi.sharedarea_read64(0, 8), 17 * (1024 ** 5) + 1)
def test_dec64(self):
uwsgi.sharedarea_write64(0, 8, 30 * (1024 ** 5))
uwsgi.sharedarea_dec64(0, 8, 30 * (1024 ** 5) - 1)
self.assertEqual(uwsgi.sharedarea_read64(0, 8), 1)
unittest.main()
+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 = '2015-03-17'
s.date = '2015-07-19'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+7
View File
@@ -2760,6 +2760,11 @@ struct uwsgi_server {
// uWSGI 2.0.10
struct uwsgi_string_list *emperor_wrapper_override;
struct uwsgi_string_list *emperor_wrapper_fallback;
// uWSGI 2.0.11
struct uwsgi_string_list *wait_for_socket;
int wait_for_socket_timeout;
int mem_collector_freq;
};
struct uwsgi_rpc {
@@ -3469,6 +3474,7 @@ struct uwsgi_socket *uwsgi_new_shared_socket(char *);
struct uwsgi_socket *uwsgi_del_socket(struct uwsgi_socket *);
void uwsgi_close_all_sockets(void);
void uwsgi_close_all_unshared_sockets(void);
struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **, char *);
#ifdef UWSGI_PCRE
@@ -4852,6 +4858,7 @@ void vassal_sos();
int uwsgi_wait_for_fs(char *, int);
int uwsgi_wait_for_mountpoint(char *);
int uwsgi_wait_for_socket(char *);
#ifdef __cplusplus
}
+9 -4
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '2.0.10'
uwsgi_version = '2.0.11.1'
import os
import re
@@ -689,8 +689,13 @@ class uConf(object):
print("detected include path: %s" % self.include_path)
try:
gcc_major = int(gcc_version.split('.')[0])
gcc_minor = int(gcc_version.split('.')[1])
gcc_version_components = gcc_version.split('.')
gcc_major = int(gcc_version_components[0])
if len(gcc_version_components) > 1:
gcc_minor = int(gcc_version_components[1])
else:
# gcc 5.0 is represented as simply "5"
gcc_minor = 0
except:
raise Exception("you need a C compiler to build uWSGI")
if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and gcc_minor < 3):
@@ -768,7 +773,7 @@ class uConf(object):
if 'UWSGI_PROFILE_OVERRIDE' in os.environ:
for item in os.environ['UWSGI_PROFILE_OVERRIDE'].split(';'):
k,v = item.split('=', 2)
k,v = item.split('=', 1)
self.set(k, v)
if 'UWSGI_AS_LIB' in os.environ: