mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c53f26cbd | ||
|
|
a5c74293d8 | ||
|
|
e5da0fc28c | ||
|
|
8e9bcc4758 | ||
|
|
bcf1f46d33 | ||
|
|
8cd13f2ad9 | ||
|
|
13df278cc4 | ||
|
|
56fedbd80c | ||
|
|
c4b563f260 | ||
|
|
39706c5899 | ||
|
|
e45f710694 | ||
|
|
0c86212aa2 | ||
|
|
3cfa743cb5 | ||
|
|
7fbc4013ca | ||
|
|
0324e5965c | ||
|
|
2050d38f96 | ||
|
|
fadce6cfe5 | ||
|
|
0ac4f8f1e4 | ||
|
|
51e81eff31 | ||
|
|
4818a5d386 | ||
|
|
4457fbefd6 | ||
|
|
9780e5fc5e | ||
|
|
9c18e0e12a | ||
|
|
c4c146dca4 | ||
|
|
08e1cf211c | ||
|
|
a52a6fc1e1 | ||
|
|
6e1c468eed | ||
|
|
1c186db72a | ||
|
|
92a8d6f2c5 | ||
|
|
144ffbaa25 | ||
|
|
3e910aaca2 | ||
|
|
5b2a3c28d0 | ||
|
|
01a5611159 | ||
|
|
bf692c4d18 | ||
|
|
a09ee5153d | ||
|
|
bc9f5d6f88 | ||
|
|
ec25be94ba | ||
|
|
7e8e113921 | ||
|
|
0575859f2d | ||
|
|
e9c0bf91ad | ||
|
|
53fb764830 | ||
|
|
76393e36be | ||
|
|
94a39e1755 | ||
|
|
e675b49ef8 | ||
|
|
78b330dd96 | ||
|
|
293ee92791 | ||
|
|
dac7457927 | ||
|
|
e1b3d8fd1a | ||
|
|
b1669d1887 | ||
|
|
095bd60f77 | ||
|
|
c3d33c90a0 | ||
|
|
4905b64f2e | ||
|
|
cfe1e9de7b | ||
|
|
82dcfd338d | ||
|
|
c696065d3c | ||
|
|
8746141afa | ||
|
|
e2b2a16b8c | ||
|
|
406daeb3ae | ||
|
|
acbc073c81 | ||
|
|
2ad23e95dd | ||
|
|
807259f25b | ||
|
|
4b06b2391c | ||
|
|
8c0adef6e7 | ||
|
|
52ea289283 | ||
|
|
bfb6e21e2a | ||
|
|
84d6f54ddd | ||
|
|
775afe1e86 | ||
|
|
cabb5f3e8e | ||
|
|
aae6413cb1 | ||
|
|
6666848ac3 | ||
|
|
c6f1911686 | ||
|
|
ef4ee87fed | ||
|
|
2a2f1a9928 | ||
|
|
f1caa39f51 | ||
|
|
536ffdcc79 | ||
|
|
d3313a39b7 | ||
|
|
89da4a97a6 | ||
|
|
3e41d5927a | ||
|
|
6a32f5d49d | ||
|
|
bf67984049 |
+2
-1
@@ -1,7 +1,7 @@
|
||||
- this is a incomplete list of all the contributors of the project -
|
||||
|
||||
Roberto De Ioris, Unbit, <roberto@unbit.it>
|
||||
Riccardo Magliocchetti, Unbit, <riccardo@unbit.it>
|
||||
Riccardo Magliocchetti
|
||||
Yann Malet, Lincoln Loop
|
||||
Simon Litchfield
|
||||
Masahiro Honma, <hiratara@cpan.org>
|
||||
@@ -28,3 +28,4 @@ Ryan Petrello
|
||||
Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
|
||||
+70
-10
@@ -67,14 +67,19 @@ static int uwsgi_canon(request_rec *r, char *url)
|
||||
}
|
||||
url += sizeof(UWSGI_SCHEME); /* Keep slashes */
|
||||
|
||||
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
|
||||
if (err) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
// is it a unix socket ?
|
||||
if (strlen(url) == 2) {
|
||||
*sport = 0;
|
||||
}
|
||||
else {
|
||||
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
|
||||
if (err) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"error parsing URL %s: %s", url, err);
|
||||
return HTTP_BAD_REQUEST;
|
||||
return HTTP_BAD_REQUEST;
|
||||
}
|
||||
apr_snprintf(sport, sizeof(sport), ":%u", port);
|
||||
}
|
||||
|
||||
apr_snprintf(sport, sizeof(sport), ":%u", port);
|
||||
|
||||
if (ap_strchr(host, ':')) { /* if literal IPv6 address */
|
||||
host = apr_pstrcat(r->pool, "[", host, "]", NULL);
|
||||
@@ -253,6 +258,43 @@ static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
static apr_status_t ap_proxy_buckets_lifetime_transform(request_rec *r,
|
||||
apr_bucket_brigade *from, apr_bucket_brigade *to)
|
||||
{
|
||||
apr_bucket *e;
|
||||
apr_bucket *new;
|
||||
const char *data;
|
||||
apr_size_t bytes;
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
|
||||
apr_brigade_cleanup(to);
|
||||
for (e = APR_BRIGADE_FIRST(from);
|
||||
e != APR_BRIGADE_SENTINEL(from);
|
||||
e = APR_BUCKET_NEXT(e)) {
|
||||
if (!APR_BUCKET_IS_METADATA(e)) {
|
||||
apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ);
|
||||
new = apr_bucket_transient_create(data, bytes, r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else if (APR_BUCKET_IS_FLUSH(e)) {
|
||||
new = apr_bucket_flush_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else if (APR_BUCKET_IS_EOS(e)) {
|
||||
new = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(to, new);
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00964)
|
||||
"Unhandled bucket type of type %s in"
|
||||
" proxy_buckets_lifetime_transform", e->type->name);
|
||||
apr_bucket_delete(e);
|
||||
rv = APR_EGENERAL;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -263,6 +305,7 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
const char *buf;
|
||||
char *value, *end;
|
||||
int len;
|
||||
int backend_broke = 1;
|
||||
apr_status_t rc;
|
||||
conn_rec *c = r->connection;
|
||||
apr_off_t readbytes;
|
||||
@@ -274,6 +317,7 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
rp->proxyreq = PROXYREQ_RESPONSE;
|
||||
|
||||
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
apr_bucket_brigade *pass_bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||
|
||||
len = ap_getline(buffer, sizeof(buffer), rp, 1);
|
||||
|
||||
@@ -325,8 +369,8 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
rv = ap_get_brigade(rp->input_filters, bb,
|
||||
AP_MODE_READBYTES, mode,
|
||||
conf->io_buffer_size);
|
||||
if (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {
|
||||
if (mode == APR_NONBLOCK_READ && (APR_STATUS_IS_EAGAIN(rv)
|
||||
|| (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
|
||||
e = apr_bucket_flush_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
if (ap_pass_brigade(r->output_filters, bb) || c->aborted) {
|
||||
@@ -342,21 +386,37 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
else if (rv != APR_SUCCESS) {
|
||||
ap_proxy_backend_broke(r, bb);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
backend_broke = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
mode = APR_NONBLOCK_READ;
|
||||
apr_brigade_length(bb, 0, &readbytes);
|
||||
backend->worker->s->read += readbytes;
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
if (APR_BRIGADE_EMPTY(bb)) {
|
||||
apr_brigade_cleanup(bb);
|
||||
break;
|
||||
}
|
||||
|
||||
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
|
||||
|
||||
ap_pass_brigade(r->output_filters, pass_bb);
|
||||
apr_brigade_cleanup(bb);
|
||||
apr_brigade_cleanup(pass_bb);
|
||||
}
|
||||
|
||||
e = apr_bucket_eos_create(c->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, e);
|
||||
ap_pass_brigade(r->output_filters, bb);
|
||||
|
||||
apr_brigade_cleanup(bb);
|
||||
|
||||
return OK;
|
||||
if (c->aborted || backend_broke) {
|
||||
return DONE;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
|
||||
Binary file not shown.
+10
-1
@@ -128,7 +128,16 @@ int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
// need to escape \ and "
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (buf[i] == '"') {
|
||||
if (buf[i] == '\t') {
|
||||
if (uwsgi_buffer_append(ub, "\\t", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\n') {
|
||||
if (uwsgi_buffer_append(ub, "\\n", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\r') {
|
||||
if (uwsgi_buffer_append(ub, "\\r", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '"') {
|
||||
if (uwsgi_buffer_append(ub, "\\\"", 2)) return -1;
|
||||
}
|
||||
else if (buf[i] == '\\') {
|
||||
|
||||
+31
-6
@@ -331,6 +331,14 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
int cache_fd;
|
||||
struct stat cst;
|
||||
|
||||
if (uc->store_delete && !stat(uc->store, &cst) && ((size_t) cst.st_size != uc->filesize || !S_ISREG(cst.st_mode))) {
|
||||
uwsgi_log("Removing invalid cache store file: %s\n", uc->store);
|
||||
if (unlink(uc->store) != 0) {
|
||||
uwsgi_log("Cannot remove invalid cache store file: %s\n", uc->store);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (stat(uc->store, &cst)) {
|
||||
uwsgi_log("creating a new cache store file: %s\n", uc->store);
|
||||
cache_fd = open(uc->store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
@@ -733,16 +741,22 @@ 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)
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
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);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + needed_blocks > uc->blocks) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
@@ -837,16 +851,22 @@ 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)
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
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);
|
||||
goto end;
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + needed_blocks > uc->blocks) {
|
||||
if (uci->first_block + needed_blocks >= uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
else {
|
||||
@@ -1212,6 +1232,7 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
char *c_keysize = NULL;
|
||||
char *c_store = NULL;
|
||||
char *c_store_sync = NULL;
|
||||
char *c_store_delete = NULL;
|
||||
char *c_nodes = NULL;
|
||||
char *c_sync = NULL;
|
||||
char *c_udp_servers = NULL;
|
||||
@@ -1236,6 +1257,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"store", &c_store,
|
||||
"store_sync", &c_store_sync,
|
||||
"storesync", &c_store_sync,
|
||||
"store_delete", &c_store_delete,
|
||||
"storedelete", &c_store_delete,
|
||||
"node", &c_nodes,
|
||||
"nodes", &c_nodes,
|
||||
"sync", &c_sync,
|
||||
@@ -1299,6 +1322,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
if (c_use_last_modified) uc->use_last_modified = 1;
|
||||
if (c_ignore_full) uc->ignore_full = 1;
|
||||
|
||||
if (c_store_delete) uc->store_delete = 1;
|
||||
|
||||
if (c_math_initial) uc->math_initial = strtol(c_math_initial, NULL, 10);
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
|
||||
@@ -294,6 +294,26 @@ int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_hostname(char *key, char *value) {
|
||||
|
||||
if (!strcmp(uwsgi.hostname, uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_hostname(char *key, char *value) {
|
||||
|
||||
if (strcmp(uwsgi.hostname, uwsgi.logic_opt_data)) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_count_options(struct uwsgi_option *uopt) {
|
||||
|
||||
struct uwsgi_option *aopt;
|
||||
|
||||
+12
-1
@@ -292,11 +292,18 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
uwsgi_close_all_sockets();
|
||||
uwsgi_close_all_fds();
|
||||
|
||||
if (ud->chdir) {
|
||||
if (chdir(ud->chdir)) {
|
||||
uwsgi_error("uwsgi_spawn_daemon()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && defined(CLONE_NEWPID)
|
||||
if (ud->ns_pid) {
|
||||
// we need to create a new session
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("setsid()");
|
||||
uwsgi_error("uwsgi_spawn_daemon()/setsid()");
|
||||
exit(1);
|
||||
}
|
||||
// avoid the need to set stop_signal in attach-daemon2
|
||||
@@ -497,6 +504,7 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
char *d_uid = NULL;
|
||||
char *d_gid = NULL;
|
||||
char *d_ns_pid = NULL;
|
||||
char *d_chdir = NULL;
|
||||
|
||||
char *arg = uwsgi_str(value);
|
||||
|
||||
@@ -518,6 +526,7 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
"uid", &d_uid,
|
||||
"gid", &d_gid,
|
||||
"ns_pid", &d_ns_pid,
|
||||
"chdir", &d_chdir,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid --%s keyval syntax\n", opt);
|
||||
exit(1);
|
||||
@@ -565,6 +574,8 @@ void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {
|
||||
#endif
|
||||
uwsgi_ud->ns_pid = d_ns_pid ? 1 : 0;
|
||||
|
||||
uwsgi_ud->chdir = d_chdir;
|
||||
|
||||
if (d_touch) {
|
||||
size_t i,rlen = 0;
|
||||
char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
|
||||
|
||||
+47
-3
@@ -1015,14 +1015,14 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
|
||||
uwsgi_log("mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
uwsgi_log("unable to mount %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
uwsgi_log("unable to umount %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
|
||||
@@ -1093,7 +1093,20 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
int i;
|
||||
|
||||
// run plugin hooks for the vassal
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->vassal) {
|
||||
uwsgi.p[i]->vassal(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->vassal) {
|
||||
uwsgi.gp[i]->vassal(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
@@ -1350,7 +1363,6 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
int i;
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
if (uwsgi_fd_is_safe(i))
|
||||
continue;
|
||||
@@ -1429,10 +1441,24 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
func(n_ui->name, n_ui->uid, n_ui->gid);
|
||||
}
|
||||
|
||||
// ->vassal_before_exec
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->vassal_before_exec) {
|
||||
uwsgi.p[i]->vassal_before_exec(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->vassal) {
|
||||
uwsgi.gp[i]->vassal_before_exec(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("[emperor] binary path: %s\n", vassal_argv[0]);
|
||||
uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
|
||||
// never here
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
@@ -1738,6 +1764,8 @@ void emperor_loop() {
|
||||
if (ui_current) {
|
||||
char byte;
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
// retry if needed
|
||||
if (rlen < 0 && uwsgi_is_again()) continue;
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
|
||||
@@ -2322,7 +2350,17 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
// place the socket in non-blocking mode
|
||||
uwsgi_socket_nb(uwsgi.emperor_fd);
|
||||
#endif
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
// and place back in blocking mode
|
||||
uwsgi_socket_b(uwsgi.emperor_fd);
|
||||
#endif
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
@@ -2342,6 +2380,12 @@ void uwsgi_master_manage_emperor() {
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
// special cose for port event system
|
||||
else if (rlen < 0 && uwsgi_is_again()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_error("uwsgi_master_manage_emperor()/read()");
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
|
||||
@@ -45,6 +45,14 @@ void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
void uwsgi_405(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "405 Method Not Allowed", 22)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Method Not Allowed", 18);
|
||||
}
|
||||
|
||||
void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *redirect = NULL;
|
||||
|
||||
+6
-5
@@ -414,11 +414,11 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != ETIME) {
|
||||
uwsgi_error("port_getn()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
uwsgi_error("port_getn()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint_t i;
|
||||
@@ -452,6 +452,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
else {
|
||||
ret = port_get(eq, &pe, NULL);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == ETIME) return 0;
|
||||
if (errno != EINTR) {
|
||||
|
||||
@@ -80,6 +80,7 @@ void uwsgi_master_fifo_prepare() {
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['B'] = vassal_sos;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['E'] = emperor_rescan;
|
||||
@@ -131,6 +132,7 @@ int uwsgi_master_fifo_manage(int fd) {
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
event_queue_del_fd(uwsgi.master_queue, uwsgi.master_fifo_fd, event_queue_read());
|
||||
close(fd);
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.stats_pusher_default_freq = 3;
|
||||
|
||||
uwsgi.original_log_fd = -1;
|
||||
uwsgi.original_log_fd = 2;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
|
||||
@@ -392,6 +392,26 @@ static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_callint(char *url, size_t *size, int add_zero) {
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, url);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *s = uwsgi_num2str(func());
|
||||
*size = strlen(s);
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, s, strlen(s));
|
||||
free(s);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
|
||||
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
|
||||
@@ -1249,6 +1269,7 @@ void uwsgi_setup_schemes() {
|
||||
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
|
||||
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
|
||||
uwsgi_register_scheme("call", uwsgi_scheme_call);
|
||||
uwsgi_register_scheme("callint", uwsgi_scheme_callint);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
|
||||
|
||||
+96
-82
@@ -301,19 +301,27 @@ void logto(char *logfile) {
|
||||
}
|
||||
|
||||
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
// if the log-master is already active, just re-set the original_log_fd
|
||||
if (uwsgi.shared->worker_log_pipe[0] == -1) {
|
||||
/* stdout */
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
uwsgi.original_log_fd = 2;
|
||||
}
|
||||
else {
|
||||
uwsgi.original_log_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,51 +354,51 @@ void uwsgi_setup_log() {
|
||||
|
||||
static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
char *name = usl->value;
|
||||
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space - name, "", 0);
|
||||
name = space + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
// make a copy of the logger
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
if (colon) {
|
||||
choosen_logger->arg = colon + 1;
|
||||
// check for empty string
|
||||
if (*choosen_logger->arg == 0) {
|
||||
choosen_logger->arg = NULL;
|
||||
}
|
||||
*colon = ':';
|
||||
}
|
||||
return choosen_logger;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_master(void) {
|
||||
@@ -511,40 +519,46 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
void uwsgi_log_do_rotate(char *logfile, char *rotatedfile, off_t logsize, int log_fd) {
|
||||
int need_free = 0;
|
||||
char *rot_name = rotatedfile;
|
||||
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
// this will be rawly written to the logfile
|
||||
uwsgi_logfile_write("logsize: %llu, triggering rotation to %s...\n", (unsigned long long) logsize, rot_name);
|
||||
if (rename(logfile, rot_name) == 0) {
|
||||
// reopen logfile and dup'it, on dup2 error, exit(1)
|
||||
int fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
// this will be written to the original file
|
||||
uwsgi_error_open(logfile);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, log_fd) < 0) {
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_do_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
// this could be lost :(
|
||||
uwsgi_error("uwsgi_log_rotate()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
if (!uwsgi.logfile)
|
||||
return;
|
||||
uwsgi_log_do_rotate(uwsgi.logfile, uwsgi.log_backupname, uwsgi.shared->logsize, uwsgi.original_log_fd);
|
||||
}
|
||||
|
||||
void uwsgi_log_reopen() {
|
||||
|
||||
+23
-7
@@ -7,6 +7,7 @@ void uwsgi_update_load_counters() {
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
static time_t last_sos = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
@@ -21,6 +22,15 @@ void uwsgi_update_load_counters() {
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
|
||||
if (uwsgi.vassal_sos) {
|
||||
if (uwsgi.current_time - last_sos > uwsgi.vassal_sos) {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (overload: %llu)...\n", (unsigned long long) ushared->overloaded);
|
||||
vassal_sos();
|
||||
last_sos = uwsgi.current_time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
@@ -273,17 +283,23 @@ static void master_check_listen_queue() {
|
||||
if (uwsgi.vassal_sos_backlog > 0 && uwsgi.has_emperor) {
|
||||
if (uwsgi.shared->backlog >= (uint64_t) uwsgi.vassal_sos_backlog) {
|
||||
// ask emperor for help
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
}
|
||||
uwsgi_log_verbose("asking Emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->backlog);
|
||||
vassal_sos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vassal_sos() {
|
||||
if (!uwsgi.has_emperor) {
|
||||
uwsgi_log("[broodlord] instance not governed by an Emperor !!!\n");
|
||||
return;
|
||||
}
|
||||
char byte = 30;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("vassal_sos()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
int master_loop(char **argv, char **environ) {
|
||||
|
||||
struct timeval last_respawn;
|
||||
|
||||
+36
-18
@@ -40,26 +40,44 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
int i;
|
||||
int needed_procs = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
|
||||
needed_procs++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.status.chain_reloading > needed_procs) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
}
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
// do not curse a worker until the old one is ready
|
||||
if (uwsgi.workers[i].accepting == 0) break;
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
break;
|
||||
|
||||
// we need to ensure the previous worker (if alive) is accepting new requests
|
||||
// before going on
|
||||
if (uwsgi.status.chain_reloading > 1) {
|
||||
struct uwsgi_worker *previous_worker = &uwsgi.workers[uwsgi.status.chain_reloading-1];
|
||||
// is the previous worker alive ?
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if all the processes are recycled, the chain is over
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
int i;
|
||||
for(i=uwsgi.status.chain_reloading;i<=uwsgi.numproc;i++) {
|
||||
struct uwsgi_worker *uw = &uwsgi.workers[i];
|
||||
if (uw->pid > 0 && !uw->cheaped && uw->accepting) {
|
||||
// the worker could have been already cursed
|
||||
if (uw->cursed_at == 0) {
|
||||
uwsgi_log_verbose("chain next victim is worker %d\n", i);
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi.status.chain_reloading++;
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
|
||||
@@ -1719,6 +1719,7 @@ void uwsgi_setns_preopen() {
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
@@ -1777,6 +1778,7 @@ void uwsgi_master_manage_setns(int fd) {
|
||||
}
|
||||
while ((de = readdir(ns)) != NULL) {
|
||||
if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "user")) continue;
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
|
||||
// allocate more memory if needed
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
|
||||
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
memmove(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
|
||||
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
|
||||
wsgi_req->post_readline_pos = 0;
|
||||
// still something to use ?
|
||||
|
||||
@@ -1753,6 +1753,10 @@ static char *uwsgi_route_var_uwsgi(struct wsgi_request *wsgi_req, char *key, uin
|
||||
ret = uwsgi_num2str(uwsgi.shared->backlog);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "rsize", 5)) {
|
||||
ret = uwsgi_64bit2str(wsgi_req->response_size);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+2
-1
@@ -193,12 +193,13 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
goto error;
|
||||
goto error2;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
error:
|
||||
close(fd);
|
||||
error2:
|
||||
free(buffer);
|
||||
return NULL;
|
||||
|
||||
|
||||
+10
-1
@@ -20,9 +20,18 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
#elif defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#elif defined(__sun__)
|
||||
off_t off = pos;
|
||||
ssize_t wlen = sendfile(sockfd, filefd, &off, len);
|
||||
if (wlen < 0 && uwsgi_is_again()) {
|
||||
if (off - pos > 0) {
|
||||
return off-pos;
|
||||
}
|
||||
}
|
||||
return wlen;
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
|
||||
+6
-8
@@ -200,11 +200,13 @@ static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, ui
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CHANGED in 2.0.7: wsgi_req is useless !
|
||||
*/
|
||||
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {
|
||||
|
||||
struct timeval tv;
|
||||
static uint64_t internal_counter = 0;
|
||||
int core_id = 0;
|
||||
int fd = -1;
|
||||
struct spooler_req sr;
|
||||
|
||||
@@ -232,10 +234,6 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req) {
|
||||
core_id = wsgi_req->async_id;
|
||||
}
|
||||
|
||||
// this lock is for threads, the pid value in filename will avoid multiprocess races
|
||||
uwsgi_lock(uspool->lock);
|
||||
|
||||
@@ -260,7 +258,7 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
// no need to check for errors...
|
||||
(void) mkdir(filename, 0777);
|
||||
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, rand(),
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >=(int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
@@ -272,8 +270,8 @@ char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len,
|
||||
else {
|
||||
filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
|
||||
filename = uwsgi_malloc(filename_len);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, core_id,
|
||||
(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter,
|
||||
rand(), (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
|
||||
if (ret <= 0 || ret >= (int) filename_len) {
|
||||
uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
|
||||
free(filename);
|
||||
|
||||
@@ -1072,6 +1072,12 @@ end:
|
||||
free(s2_sign);
|
||||
if (s2_check)
|
||||
free(s2_check);
|
||||
if (s2_sni_crt)
|
||||
free(s2_sni_crt);
|
||||
if (s2_sni_key)
|
||||
free(s2_sni_key);
|
||||
if (s2_sni_ca)
|
||||
free(s2_sni_ca);
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
+8
-2
@@ -1019,8 +1019,14 @@ void uwsgi_destroy_request(struct wsgi_request *wsgi_req) {
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &foo);
|
||||
}
|
||||
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
// reset for avoiding following requests to fail on non-uwsgi protocols
|
||||
// thanks Marko Tiikkaja for catching it
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
|
||||
// some plugins expected async_id to be defined before setup
|
||||
int tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
wsgi_req->async_id = tmp_id;
|
||||
}
|
||||
|
||||
// finalize/close/free a request
|
||||
@@ -1166,8 +1172,8 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
tmp_id = wsgi_req->async_id;
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
// some plugins expected async_id to be defined before setup
|
||||
wsgi_req->async_id = tmp_id;
|
||||
|
||||
// yes, this is pretty useless but we cannot ensure all of the plugin have the same behaviour
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
|
||||
|
||||
+32
-19
@@ -39,8 +39,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0},
|
||||
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"suwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"ssl-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"suwsgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"ssl-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
#endif
|
||||
|
||||
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0},
|
||||
@@ -71,8 +71,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"undeferred-shared-socket", required_argument, 0, "create a shared socket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
|
||||
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possible)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
|
||||
@@ -120,6 +120,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_hostname, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-hostname", required_argument, 0, "(opt logic) check for hostname", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_hostname, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -238,6 +241,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"vassals-include-before", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes_before, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos", required_argument, 0, "ask emperor for reinforcement when overloaded", uwsgi_opt_set_int, &uwsgi.vassal_sos, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
{"vassals-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
{"vassal-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
@@ -699,13 +703,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarm-msg-size", required_argument, 0, "set the max size of an alarm message (default 8192)", uwsgi_opt_set_64bit, &uwsgi.alarm_msg_size, 0},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_MASTER|UWSGI_OPT_LOG_MASTER},
|
||||
{"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
|
||||
|
||||
{"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
|
||||
@@ -1580,6 +1584,17 @@ static void vacuum(void) {
|
||||
next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
if (uwsgi.stats) {
|
||||
// is a unix socket ?
|
||||
if (!strchr(uwsgi.stats, ':') && uwsgi.stats[0] != '@') {
|
||||
if (unlink(uwsgi.stats)) {
|
||||
uwsgi_error("unlink()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("VACUUM: unix socket %s (stats) removed.\n", uwsgi.stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2231,7 +2246,7 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock_wait2, NULL);
|
||||
|
||||
// setup master logging
|
||||
if (uwsgi.log_master && !uwsgi.daemonize2 && uwsgi.logfile)
|
||||
if (uwsgi.log_master)
|
||||
uwsgi_setup_log_master();
|
||||
|
||||
// setup offload engines
|
||||
@@ -2513,11 +2528,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (uwsgi.logto2) {
|
||||
if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
|
||||
int setup_log = 0;
|
||||
if (!uwsgi.logfile) setup_log = 1; // logto() will replace uwsgi.logfile and we need to check it later
|
||||
logto(uwsgi.logto2);
|
||||
if (setup_log)
|
||||
uwsgi_setup_log_master();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3787,7 +3798,8 @@ void uwsgi_opt_false(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
gid_t gid = atoi(value);
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (gid == 0) {
|
||||
struct group *ugroup = getgrnam(value);
|
||||
if (ugroup)
|
||||
@@ -3816,7 +3828,8 @@ void uwsgi_opt_set_immediate_gid(char *opt, char *value, void *none) {
|
||||
|
||||
|
||||
void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) {
|
||||
uid_t uid = atoi(value);
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (uid == 0) {
|
||||
struct passwd *upasswd = getpwnam(value);
|
||||
if (upasswd)
|
||||
@@ -3863,7 +3876,8 @@ void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_uid(char *opt, char *value, void *key) {
|
||||
uid_t uid = atoi(value);
|
||||
uid_t uid = 0;
|
||||
if (is_a_number(value)) uid = atoi(value);
|
||||
if (!uid) {
|
||||
struct passwd *p = getpwnam(value);
|
||||
if (p) {
|
||||
@@ -3881,7 +3895,8 @@ void uwsgi_opt_uid(char *opt, char *value, void *key) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_gid(char *opt, char *value, void *key) {
|
||||
gid_t gid = atoi(value);
|
||||
gid_t gid = 0;
|
||||
if (is_a_number(value)) gid = atoi(value);
|
||||
if (!gid) {
|
||||
struct group *g = getgrnam(value);
|
||||
if (g) {
|
||||
@@ -4182,15 +4197,13 @@ void uwsgi_opt_print(char *opt, char *value, void *str) {
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_uid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.uid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.uid = atoi(value);
|
||||
if (!uwsgi.uid)
|
||||
uwsgi.uidname = value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
|
||||
|
||||
uwsgi.gid = atoi(value);
|
||||
if (is_a_number(value)) uwsgi.gid = atoi(value);
|
||||
if (!uwsgi.gid)
|
||||
uwsgi.gidname = value;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,6 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
|
||||
}
|
||||
|
||||
if (peer->failed) {
|
||||
|
||||
if (peer->soopt) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("[uwsgi-%s] unable to connect() to node \"%.*s\" (%d retries): %s\n", ucr->short_name, (int) peer->instance_address_len, peer->instance_address, peer->retries, strerror(peer->soopt));
|
||||
|
||||
@@ -271,7 +271,7 @@ struct uwsgi_corerouter {
|
||||
char *resubscribe_bind;
|
||||
|
||||
size_t buffer_size;
|
||||
|
||||
int fallback_on_no_key;
|
||||
};
|
||||
|
||||
// a session is started when a client connect to the router
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
NAME='emperor_zeromq'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['emperor_zeromq']
|
||||
|
||||
@@ -55,6 +55,7 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-resubscribe-bind", required_argument, 0, "bind to the specified address when re-subscribing", uwsgi_opt_set_str, &ufr.cr.resubscribe_bind, 0},
|
||||
|
||||
{"fastrouter-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &ufr.cr.buffer_size, 0},
|
||||
{"fastrouter-fallback-on-no-key", no_argument, 0, "move to fallback node even if a subscription key is not found", uwsgi_opt_true, &ufr.cr.fallback_on_no_key, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -226,8 +227,15 @@ static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
return -1;
|
||||
|
||||
// check instance
|
||||
if (new_peer->instance_address_len == 0)
|
||||
if (new_peer->instance_address_len == 0) {
|
||||
if (ufr.cr.fallback_on_no_key) {
|
||||
new_peer->failed = 1;
|
||||
new_peer->can_retry = 1;
|
||||
corerouter_close_peer(&ufr.cr, new_peer);
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
|
||||
@@ -1,10 +1,49 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
struct logfile_data {
|
||||
char *logfile;
|
||||
char *backupname;
|
||||
uint64_t maxsize;
|
||||
};
|
||||
|
||||
static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
ul->fd = open(ul->arg, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
int is_keyval = 0;
|
||||
char *backupname = NULL;
|
||||
char *maxsize = NULL;
|
||||
char *logfile = NULL;
|
||||
|
||||
if (strchr(ul->arg, '=')) {
|
||||
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
|
||||
"logfile", &logfile, "backupname", &backupname, "maxsize", &maxsize, NULL)) {
|
||||
uwsgi_log("[uwsgi-logfile] invalid keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
is_keyval = 1;
|
||||
}
|
||||
if (is_keyval) {
|
||||
if (!logfile) {
|
||||
uwsgi_log("[uwsgi-logfile] missing logfile key\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxsize) {
|
||||
struct logfile_data *data = uwsgi_malloc(sizeof(struct logfile_data));
|
||||
data->logfile = logfile;
|
||||
data->backupname = backupname;
|
||||
data->maxsize = (uint64_t)strtoull(maxsize, NULL, 10);
|
||||
ul->data = data;
|
||||
|
||||
free(maxsize);
|
||||
maxsize = NULL;
|
||||
}
|
||||
} else {
|
||||
logfile = ul->arg;
|
||||
}
|
||||
|
||||
ul->fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (ul->fd >= 0) {
|
||||
ul->configured = 1;
|
||||
}
|
||||
@@ -12,10 +51,21 @@ static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t
|
||||
}
|
||||
|
||||
if (ul->fd >= 0) {
|
||||
return write(ul->fd, message, len);
|
||||
}
|
||||
return 0;
|
||||
ssize_t written = write(ul->fd, message, len);
|
||||
|
||||
if (ul->data) {
|
||||
struct logfile_data *data = ul->data;
|
||||
off_t logsize = lseek(ul->fd, 0, SEEK_CUR);
|
||||
|
||||
if (data->maxsize > 0 && (uint64_t) logsize > data->maxsize) {
|
||||
uwsgi_log_do_rotate(data->logfile, data->backupname, logsize, ul->fd);
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_fd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
@@ -6,6 +6,9 @@ LDFLAGS = []
|
||||
LIBS = os.popen('pkg-config --libs mono-2').read().rstrip().split()
|
||||
GCC_LIST = ['mono_plugin']
|
||||
|
||||
if os.uname()[0] == 'Darwin':
|
||||
LIBS.append('-framework Foundation')
|
||||
|
||||
def post_build(config):
|
||||
if os.system("sn -k plugins/mono/uwsgi.key") != 0:
|
||||
os._exit(1)
|
||||
|
||||
+30
-25
@@ -26,6 +26,8 @@ struct uwsgi_php {
|
||||
|
||||
struct uwsgi_string_list *exec_before;
|
||||
struct uwsgi_string_list *exec_after;
|
||||
|
||||
char *sapi_name;
|
||||
} uphp;
|
||||
|
||||
void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
|
||||
@@ -58,6 +60,7 @@ struct uwsgi_option uwsgi_php_options[] = {
|
||||
{"php-exec-begin", required_argument, 0, "run specified php code before the requested script", uwsgi_opt_add_string_list, &uphp.exec_before, 0},
|
||||
{"php-exec-after", required_argument, 0, "run specified php code after the requested script", uwsgi_opt_add_string_list, &uphp.exec_after, 0},
|
||||
{"php-exec-end", required_argument, 0, "run specified php code after the requested script", uwsgi_opt_add_string_list, &uphp.exec_after, 0},
|
||||
{"php-sapi-name", required_argument, 0, "hack the sapi name (required for enabling zend opcode cache)", uwsgi_opt_set_str, &uphp.sapi_name, 0},
|
||||
UWSGI_END_OF_OPTIONS
|
||||
};
|
||||
|
||||
@@ -176,11 +179,11 @@ static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
php_register_variable_safe("DOCUMENT_ROOT", wsgi_req->document_root, wsgi_req->document_root_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
if (wsgi_req->path_info_len) {
|
||||
char *path_translated = ecalloc(1, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len + 1);
|
||||
char *path_translated = ecalloc(1, wsgi_req->file_len + wsgi_req->path_info_len + 1);
|
||||
|
||||
memcpy(path_translated, wsgi_req->file, (wsgi_req->file_len - wsgi_req->script_name_len));
|
||||
memcpy(path_translated + (wsgi_req->file_len - wsgi_req->script_name_len), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
php_register_variable_safe("PATH_TRANSLATED", path_translated, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
|
||||
memcpy(path_translated, wsgi_req->file, wsgi_req->file_len);
|
||||
memcpy(path_translated + wsgi_req->file_len, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
php_register_variable_safe("PATH_TRANSLATED", path_translated, wsgi_req->file_len + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
|
||||
}
|
||||
else {
|
||||
php_register_variable_safe("PATH_TRANSLATED", "", 0, track_vars_array TSRMLS_CC);
|
||||
@@ -251,8 +254,9 @@ PHP_FUNCTION(uwsgi_cache_exists) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -266,8 +270,9 @@ PHP_FUNCTION(uwsgi_cache_exists) {
|
||||
PHP_FUNCTION(uwsgi_cache_clear) {
|
||||
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -284,8 +289,9 @@ PHP_FUNCTION(uwsgi_cache_del) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -301,12 +307,13 @@ PHP_FUNCTION(uwsgi_cache_get) {
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
uint64_t valsize;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key, &keylen, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -326,11 +333,12 @@ PHP_FUNCTION(uwsgi_cache_set) {
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -348,11 +356,12 @@ PHP_FUNCTION(uwsgi_cache_update) {
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
char *cache = NULL;
|
||||
int cachelen = 0;
|
||||
|
||||
if (!uwsgi.caches)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &key, &keylen, &value, &vallen, &expires, &cache, &cachelen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
@@ -578,8 +587,10 @@ int uwsgi_php_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uphp.sapi_name) {
|
||||
uwsgi_sapi_module.name = uphp.sapi_name;
|
||||
}
|
||||
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
|
||||
|
||||
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
|
||||
|
||||
return 0;
|
||||
@@ -657,6 +668,9 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
uint16_t orig_path_info_len = wsgi_req->path_info_len;
|
||||
|
||||
if (uphp.docroot) {
|
||||
wsgi_req->document_root = uphp.docroot;
|
||||
}
|
||||
@@ -733,10 +747,6 @@ oldstyle:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
uint16_t orig_path_info_len = wsgi_req->path_info_len;
|
||||
|
||||
if (path_info) {
|
||||
wsgi_req->path_info = path_info;
|
||||
wsgi_req->path_info_len = orig_path_info_len - (path_info - orig_path_info);
|
||||
@@ -846,24 +856,19 @@ secure2:
|
||||
}
|
||||
|
||||
secure3:
|
||||
|
||||
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
|
||||
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 = real_filename + wsgi_req->document_root_len;
|
||||
}
|
||||
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
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,
|
||||
wsgi_req->document_root_len, wsgi_req->document_root, wsgi_req->document_root_len);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// now check for allowed paths and extensions
|
||||
|
||||
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
|
||||
|
||||
@@ -946,7 +946,7 @@ XS(XS_spool) {
|
||||
}
|
||||
}
|
||||
|
||||
char *filename = uwsgi_spool_request(current_wsgi_req(), ub->buf, ub->pos, body, body_len);
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (filename) {
|
||||
ST(0) = newSVpv(filename, strlen(filename));
|
||||
|
||||
@@ -325,12 +325,19 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
if (uwsgi.threads > 1 && id) {
|
||||
// if we have multiple threads we need to initialize a PyThreadState for each one
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
//uwsgi_log("%p\n", uwsgi.core[i]->ts[id]);
|
||||
uwsgi.workers[uwsgi.mywid].cores[i].ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
|
||||
//uwsgi_log("%p\n", uwsgi.workers[uwsgi.mywid].cores[i].ts[id]);
|
||||
if (!uwsgi.workers[uwsgi.mywid].cores[i].ts[id]) {
|
||||
uwsgi_log("unable to allocate new PyThreadState structure for app %s", wi->mountpoint);
|
||||
goto doh;
|
||||
}
|
||||
// cow ?
|
||||
if (uwsgi.mywid == 0) {
|
||||
int j;
|
||||
for(j=1;j<=uwsgi.numproc;j++) {
|
||||
uwsgi.workers[j].cores[i].ts[id] = uwsgi.workers[0].cores[i].ts[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) );
|
||||
}
|
||||
|
||||
@@ -920,12 +920,16 @@ int uwsgi_python_mount_app(char *mountpoint, char *app) {
|
||||
if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) {
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
// lazy ?
|
||||
if (uwsgi.mywid > 0) UWSGI_GET_GIL
|
||||
if (uwsgi.single_interpreter) {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
else {
|
||||
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
|
||||
}
|
||||
// lazy ?
|
||||
if (uwsgi.mywid > 0) UWSGI_RELEASE_GIL
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
|
||||
@@ -382,6 +382,11 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
if (PyString_Check(py_node)) {
|
||||
node = PyString_AsString(py_node);
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
else if (PyUnicode_Check(py_node)) {
|
||||
node = PyBytes_AsString(PyUnicode_AsLatin1String(py_node));
|
||||
}
|
||||
#endif
|
||||
|
||||
py_func = PyTuple_GetItem(args, 1);
|
||||
|
||||
@@ -1855,7 +1860,6 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
PyObject *spool_dict, *spool_vars;
|
||||
PyObject *zero, *key, *val;
|
||||
uint16_t keysize, valsize;
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
@@ -1956,7 +1960,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
// current_wsgi_req can be NULL, in such a case a non-thread-safe counter will be used
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
@@ -2240,7 +2245,8 @@ PyObject *py_uwsgi_stop(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_request_id(PyObject * self, PyObject * args) {
|
||||
return PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].requests);
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
return PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_worker_id(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -969,7 +969,6 @@ static int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
|
||||
static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
@@ -991,7 +990,7 @@ static VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) ub);
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, ub->buf, ub->pos, body, body_len);
|
||||
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
|
||||
+492
-93
@@ -6,27 +6,55 @@ extern struct uwsgi_server uwsgi;
|
||||
/*
|
||||
|
||||
Author: Javier Guerra
|
||||
Author: Marcin Deranek
|
||||
Author: Roberto De Ioris
|
||||
|
||||
based on the uWSGI GlusterFS plugin by Roberto De Ioris
|
||||
|
||||
--rados-mount mountpoint=/foo,pool=unbit001,config=/etc/ceph.conf
|
||||
--rados-mount mountpoint=/foo,pool=unbit001,config=/etc/ceph.conf,timeout=30,allow_put=1,allow_delete=1
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_plugin rados_plugin;
|
||||
|
||||
struct uwsgi_rados {
|
||||
// this structure is preallocated (only the pipe part is per-request)
|
||||
struct uwsgi_rados_io {
|
||||
int fds[2];
|
||||
// this is increased at every usage (in locked context)
|
||||
uint64_t rid;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
// this structure is allocated for each async transaction
|
||||
struct uwsgi_rados_cb {
|
||||
// this is copied from the current uwsgi_rados_io->rid
|
||||
uint64_t rid;
|
||||
struct uwsgi_rados_io *urio;
|
||||
};
|
||||
|
||||
static struct uwsgi_rados {
|
||||
int timeout;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
struct uwsgi_rados_io *urio;
|
||||
} urados;
|
||||
|
||||
struct uwsgi_rados_mountpoint {
|
||||
rados_t cluster;
|
||||
char *mountpoint;
|
||||
char *config;
|
||||
char *pool;
|
||||
char *str_timeout;
|
||||
int timeout;
|
||||
char *allow_put;
|
||||
char *allow_delete;
|
||||
char *allow_mkcol;
|
||||
};
|
||||
|
||||
static struct uwsgi_option uwsgi_rados_options[] = {
|
||||
{"rados-mount", required_argument, 0, "virtual mount the specified rados volume in a uri", uwsgi_opt_add_string_list, &urados.mountpoints, UWSGI_OPT_MIME},
|
||||
{"rados-timeout", required_argument, 0, "timeout for async operations", uwsgi_opt_set_int, &urados.timeout, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int uwsgi_rados_read_sync(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
static int uwsgi_rados_read_sync(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
while(remains > 0) {
|
||||
char buf[8192];
|
||||
@@ -39,119 +67,354 @@ static int uwsgi_rados_read_sync(struct wsgi_request *wsgi_req, rados_ioctx_t *c
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
async read of a resource
|
||||
the uwsgi_rados_async_io structure is passed between threads
|
||||
the callback simply signal the main core about the availability of data
|
||||
*/
|
||||
struct uwsgi_rados_async_io {
|
||||
int fd[2];
|
||||
ssize_t rlen;
|
||||
};
|
||||
|
||||
// callback used to asynchronously signal the completion
|
||||
static void uwsgi_rados_read_async_cb(rados_completion_t comp, void *data) {
|
||||
struct uwsgi_rados_async_io *aio = (struct uwsgi_rados_async_io *) data;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[rados-cb] rlen = %d\n", rlen);
|
||||
#endif
|
||||
aio->rlen = rados_aio_get_return_value(comp);
|
||||
// signal the core
|
||||
if (write(aio->fd[1], "\1", 1) <= 0) {
|
||||
uwsgi_error("uwsgi_rados_read_async_cb()/write()");
|
||||
struct uwsgi_rados_cb *urcb = (struct uwsgi_rados_cb *) data;
|
||||
struct uwsgi_rados_io *urio = urcb->urio;
|
||||
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
if (urcb->rid != urio->rid) {
|
||||
uwsgi_log_verbose("[uwsgi-rados] callback %llu woke up too late\n", (unsigned long long) urcb->rid);
|
||||
}
|
||||
else {
|
||||
// signal the core
|
||||
if (write(urio->fds[1], "\1", 1) <= 0) {
|
||||
uwsgi_error("uwsgi_rados_read_async_cb()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
|
||||
free(urcb);
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_rados_read_async(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
char buf[8192];
|
||||
struct uwsgi_rados_async_io aio;
|
||||
static int uwsgi_rados_delete(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, char *key, int timeout) {
|
||||
if (uwsgi.async <= 1) {
|
||||
return rados_remove(ctx, key);
|
||||
}
|
||||
struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
|
||||
int ret = -1;
|
||||
if (pipe(aio.fd)) {
|
||||
uwsgi_error("uwsgi_rados_read_async()/pipe()");
|
||||
return -1;
|
||||
}
|
||||
aio.rlen = -1;
|
||||
rados_completion_t comp;
|
||||
if (rados_aio_create_completion(&aio, uwsgi_rados_read_async_cb, NULL, &comp) < 0) goto end;
|
||||
|
||||
while(remains > 0) {
|
||||
// trigger an async read
|
||||
if (rados_aio_read(ctx, key, comp, buf, 8192, off) < 0) goto end;
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(aio.fd[0], urados.timeout) <= 0) goto end;
|
||||
if (aio.rlen <= 0) goto end;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, aio.rlen)) goto end;
|
||||
remains -= aio.rlen;
|
||||
}
|
||||
ret = 0;
|
||||
// increase request counter
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
urio->rid++;
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
|
||||
struct uwsgi_rados_cb *urcb = uwsgi_malloc(sizeof(struct uwsgi_rados_cb));
|
||||
// map the current request id to the callback
|
||||
urcb->rid = urio->rid;
|
||||
// map urio to the callback
|
||||
urcb->urio = urio;
|
||||
|
||||
rados_completion_t comp;
|
||||
// we use the safe cb here
|
||||
if (rados_aio_create_completion(urcb, NULL, uwsgi_rados_read_async_cb, &comp) < 0) {
|
||||
free(urcb);
|
||||
goto end;
|
||||
}
|
||||
if (rados_aio_remove(ctx, key, comp) < 0) {
|
||||
free(urcb);
|
||||
rados_aio_release(comp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(urio->fds[0], timeout) <= 0) {
|
||||
rados_aio_release(comp);
|
||||
goto end;
|
||||
}
|
||||
char ack = 1;
|
||||
if (read(urio->fds[0], &ack, 1) != 1) {
|
||||
rados_aio_release(comp);
|
||||
uwsgi_error("uwsgi_rados_delete()/read()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (rados_aio_is_safe_and_cb(comp)) {
|
||||
ret = rados_aio_get_return_value(comp);
|
||||
}
|
||||
rados_aio_release(comp);
|
||||
|
||||
end:
|
||||
rados_aio_release(&comp);
|
||||
close(aio.fd[0]);
|
||||
close(aio.fd[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_rados_put(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, char *key, int timeout) {
|
||||
struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
|
||||
size_t remains = wsgi_req->post_cl;
|
||||
uint64_t off = 0;
|
||||
while(remains > 0) {
|
||||
ssize_t body_len = 0;
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// increase request counter
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
urio->rid++;
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
|
||||
struct uwsgi_rados_cb *urcb = uwsgi_malloc(sizeof(struct uwsgi_rados_cb));
|
||||
// map the current request id to the callback
|
||||
urcb->rid = urio->rid;
|
||||
// map urio to the callback
|
||||
urcb->urio = urio;
|
||||
|
||||
rados_completion_t comp;
|
||||
// use safe for write
|
||||
if (rados_aio_create_completion(urcb, NULL, uwsgi_rados_read_async_cb, &comp) < 0) {
|
||||
free(urcb);
|
||||
goto error;
|
||||
}
|
||||
if (rados_aio_write(ctx, key, comp, body, body_len, off) < 0) {
|
||||
free(urcb);
|
||||
rados_aio_release(comp);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(urio->fds[0], timeout) <= 0) {
|
||||
rados_aio_release(comp);
|
||||
goto error;
|
||||
}
|
||||
char ack = 1;
|
||||
if (read(urio->fds[0], &ack, 1) != 1) {
|
||||
rados_aio_release(comp);
|
||||
uwsgi_error("uwsgi_rados_read_async()/read()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (rados_aio_is_safe_and_cb(comp)) {
|
||||
if (rados_aio_get_return_value(comp) < 0) {
|
||||
rados_aio_release(comp);
|
||||
goto error;
|
||||
}
|
||||
|
||||
}
|
||||
rados_aio_release(comp);
|
||||
}
|
||||
remains -= body_len;
|
||||
off += body_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// async stat
|
||||
static int uwsgi_rados_async_stat(struct uwsgi_rados_io *urio, rados_ioctx_t ctx, const char *key, uint64_t *stat_size, time_t *stat_mtime, int timeout) {
|
||||
int ret = -1;
|
||||
// increase request counter
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
urio->rid++;
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
|
||||
struct uwsgi_rados_cb *urcb = uwsgi_malloc(sizeof(struct uwsgi_rados_cb));
|
||||
// map the current request id to the callback
|
||||
urcb->rid = urio->rid;
|
||||
// map urio to the callback
|
||||
urcb->urio = urio;
|
||||
|
||||
rados_completion_t comp;
|
||||
if (rados_aio_create_completion(urcb, uwsgi_rados_read_async_cb, NULL, &comp) < 0) {
|
||||
free(urcb);
|
||||
goto end;
|
||||
}
|
||||
if (rados_aio_stat(ctx, key, comp, stat_size, stat_mtime) < 0) {
|
||||
free(urcb);
|
||||
rados_aio_release(comp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(urio->fds[0], timeout) <= 0) {
|
||||
rados_aio_release(comp);
|
||||
goto end;
|
||||
}
|
||||
char ack = 1;
|
||||
if (read(urio->fds[0], &ack, 1) != 1) {
|
||||
rados_aio_release(comp);
|
||||
uwsgi_error("uwsgi_rados_read_async()/read()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (rados_aio_is_complete_and_cb(comp)) {
|
||||
ret = rados_aio_get_return_value(comp);
|
||||
}
|
||||
rados_aio_release(comp);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_rados_read_async(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, const char *key, size_t remains, int timeout) {
|
||||
uint64_t off = 0;
|
||||
int ret = -1;
|
||||
char buf[8192];
|
||||
|
||||
struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
|
||||
// increase request counter
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
urio->rid++;
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
|
||||
while(remains > 0) {
|
||||
struct uwsgi_rados_cb *urcb = uwsgi_malloc(sizeof(struct uwsgi_rados_cb));
|
||||
// map the current request id to the callback
|
||||
urcb->rid = urio->rid;
|
||||
// map urio to the callback
|
||||
urcb->urio = urio;
|
||||
|
||||
|
||||
rados_completion_t comp;
|
||||
if (rados_aio_create_completion(urcb, uwsgi_rados_read_async_cb, NULL, &comp) < 0) {
|
||||
free(urcb);
|
||||
break;
|
||||
}
|
||||
// trigger an async read
|
||||
if (rados_aio_read(ctx, key, comp, buf, UMIN(remains, 8192), off) < 0) {
|
||||
free(urcb);
|
||||
rados_aio_release(comp);
|
||||
break;
|
||||
}
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(urio->fds[0], timeout) <= 0) {
|
||||
rados_aio_release(comp);
|
||||
break;
|
||||
}
|
||||
char ack = 1;
|
||||
if (read(urio->fds[0], &ack, 1) != 1) {
|
||||
rados_aio_release(comp);
|
||||
uwsgi_error("uwsgi_rados_read_async()/read()");
|
||||
break;
|
||||
}
|
||||
int rlen = -1;
|
||||
if (rados_aio_is_complete_and_cb(comp)) {
|
||||
rlen = rados_aio_get_return_value(comp);
|
||||
}
|
||||
rados_aio_release(comp);
|
||||
if (rlen <= 0) break;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) break;
|
||||
remains -= rlen;
|
||||
off += rlen;
|
||||
}
|
||||
|
||||
if (remains == 0) ret = 0;
|
||||
|
||||
pthread_mutex_lock(&urio->mutex);
|
||||
// increase the counter again
|
||||
urio->rid++;
|
||||
pthread_mutex_unlock(&urio->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
|
||||
char *rad_mountpoint = NULL;
|
||||
char *rad_config = NULL;
|
||||
char *rad_poolname = NULL;
|
||||
struct uwsgi_rados_mountpoint *urmp = uwsgi_calloc(sizeof(struct uwsgi_rados_mountpoint));
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &rad_mountpoint,
|
||||
"config", &rad_config,
|
||||
"pool", &rad_poolname,
|
||||
"mountpoint", &urmp->mountpoint,
|
||||
"config", &urmp->config,
|
||||
"pool", &urmp->pool,
|
||||
"timeout", &urmp->str_timeout,
|
||||
"allow_put", &urmp->allow_put,
|
||||
"allow_delete", &urmp->allow_delete,
|
||||
"allow_mkcol", &urmp->allow_mkcol,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse rados mountpoint definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!rad_mountpoint|| !rad_poolname) {
|
||||
if (!urmp->mountpoint|| !urmp->pool) {
|
||||
uwsgi_log("[rados] mount requires a mountpoint, and a pool name.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (urmp->str_timeout) {
|
||||
urmp->timeout = atoi(urmp->str_timeout);
|
||||
}
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
uwsgi_log("[rados] mounting %s ...\n", rad_mountpoint);
|
||||
uwsgi_log("[rados] mounting %s ...\n", urmp->mountpoint);
|
||||
|
||||
rados_t cluster;
|
||||
if (rados_create(&cluster, NULL) < 0) {
|
||||
uwsgi_error("Can't create Ceph cluster handle");
|
||||
uwsgi_error("can't create Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
if (rad_config)
|
||||
uwsgi_log("Using Ceph conf:%s\n", rad_config);
|
||||
urmp->cluster = cluster;
|
||||
|
||||
if (urmp->config)
|
||||
uwsgi_log("using Ceph conf:%s\n", urmp->config);
|
||||
else
|
||||
uwsgi_log("Using default Ceph conf.\n");
|
||||
if (rados_conf_read_file(cluster, rad_config) < 0) {
|
||||
uwsgi_error("Can't configure Ceph cluster handle");
|
||||
uwsgi_log("using default Ceph conf.\n");
|
||||
|
||||
if (rados_conf_read_file(cluster, urmp->config) < 0) {
|
||||
uwsgi_error("can't configure Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int timeout = urmp->timeout ? urmp->timeout : urados.timeout;
|
||||
char *timeout_str = uwsgi_num2str(timeout);
|
||||
|
||||
rados_conf_set(cluster, "client_mount_timeout", timeout_str);
|
||||
rados_conf_set(cluster, "rados_mon_op_timeout", timeout_str);
|
||||
rados_conf_set(cluster, "rados_osd_op_timeout", timeout_str);
|
||||
|
||||
free(timeout_str);
|
||||
|
||||
|
||||
if (rados_connect(cluster) < 0) {
|
||||
uwsgi_error("Can't connect with Ceph cluster");
|
||||
uwsgi_error("can't connect with Ceph cluster");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rados_ioctx_t ctx;
|
||||
uwsgi_log("Ceph pool: %s\n", rad_poolname);
|
||||
if (rados_ioctx_create(cluster, rad_poolname, &ctx) < 0) {
|
||||
uwsgi_error("Can't open rados pool")
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
|
||||
|
||||
void *ctx_ptr;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
int i;
|
||||
rados_ioctx_t *ctxes = uwsgi_calloc(sizeof(rados_ioctx_t) * uwsgi.threads);
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
if (rados_ioctx_create(cluster, urmp->pool, &ctxes[i]) < 0) {
|
||||
uwsgi_error("can't open rados pool")
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
ctx_ptr = ctxes;
|
||||
}
|
||||
else {
|
||||
rados_ioctx_t ctx;
|
||||
if (rados_ioctx_create(cluster, urmp->pool, &ctx) < 0) {
|
||||
uwsgi_error("can't open rados pool")
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
ctx_ptr = ctx;
|
||||
}
|
||||
|
||||
char fsid[37];
|
||||
rados_cluster_fsid(cluster, fsid, 37);
|
||||
uwsgi_log("connected to Ceph pool: %s on cluster %.*s\n", urmp->pool, 37, fsid);
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, rados_plugin.modifier1, rad_mountpoint, strlen(rad_mountpoint), NULL, NULL);
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, rados_plugin.modifier1, urmp->mountpoint, strlen(urmp->mountpoint), NULL, NULL);
|
||||
if (!ua) {
|
||||
uwsgi_log("[rados] unable to mount %s\n", rad_mountpoint);
|
||||
uwsgi_log("[rados] unable to mount %s\n", urmp->mountpoint);
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ua->responder0 = cluster;
|
||||
ua->responder1 = ctx;
|
||||
ua->responder0 = ctx_ptr;
|
||||
ua->responder1 = urmp;
|
||||
ua->started_at = now;
|
||||
ua->startup_time = uwsgi_now() - now;
|
||||
uwsgi_log("Rados app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, rad_mountpoint, (int) ua->startup_time, ctx);
|
||||
uwsgi_log("Rados app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, urmp->mountpoint, (int) ua->startup_time, ctx_ptr);
|
||||
}
|
||||
|
||||
// we translate the string list to an app representation
|
||||
@@ -166,6 +429,21 @@ static void uwsgi_rados_setup() {
|
||||
uwsgi_rados_add_mountpoint(usl->value, usl->len);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
// now initialize a pthread_mutex for each async core
|
||||
if (uwsgi.async > 1) {
|
||||
int i;
|
||||
urados.urio = uwsgi_calloc(sizeof(struct uwsgi_rados_io) * uwsgi.async);
|
||||
for(i=0;i<uwsgi.async;i++) {
|
||||
urados.urio[i].fds[0] = -1;
|
||||
urados.urio[i].fds[1] = -1;
|
||||
if (pthread_mutex_init(&urados.urio[i].mutex, NULL)) {
|
||||
uwsgi_error("uwsgi_rados_setup()/pthread_mutex_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
@@ -199,29 +477,146 @@ static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
if (wsgi_req->path_info_len > ua->mountpoint_len &&
|
||||
memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0)
|
||||
{
|
||||
memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0) {
|
||||
|
||||
memcpy(filename, wsgi_req->path_info+ua->mountpoint_len, wsgi_req->path_info_len-ua->mountpoint_len);
|
||||
filename[wsgi_req->path_info_len-ua->mountpoint_len] = 0;
|
||||
|
||||
} else {
|
||||
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
filename[wsgi_req->path_info_len] = 0;
|
||||
}
|
||||
filename[wsgi_req->path_info_len] = 0;
|
||||
|
||||
struct {
|
||||
uint64_t size;
|
||||
time_t mtime;
|
||||
} st;
|
||||
rados_ioctx_t ctx = ua->responder1;
|
||||
// in multithread mode the memory is different (as we need a ctx for each thread) !!!
|
||||
rados_ioctx_t ctx;
|
||||
if (uwsgi.threads > 1) {
|
||||
rados_ioctx_t *ctxes = (rados_ioctx_t *) ua->responder0;
|
||||
ctx = ctxes[wsgi_req->async_id];
|
||||
}
|
||||
else {
|
||||
ctx = (rados_ioctx_t) ua->responder0;
|
||||
}
|
||||
struct uwsgi_rados_mountpoint *urmp = (struct uwsgi_rados_mountpoint *) ua->responder1;
|
||||
uint64_t stat_size = 0;
|
||||
time_t stat_mtime = 0;
|
||||
|
||||
struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
// no need to lock here (the rid protect us)
|
||||
if (pipe(urio->fds)) {
|
||||
uwsgi_error("uwsgi_rados_read_async()/pipe()");
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int r = rados_stat(ctx, filename, &st.size, &st.mtime);
|
||||
if (r < 0) {
|
||||
if (r == -ENOENT)
|
||||
int ret = -1;
|
||||
int timeout = urmp->timeout ? urmp->timeout : urados.timeout;
|
||||
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "OPTIONS", 7)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Dav", 3, "1", 1)) goto end;
|
||||
struct uwsgi_buffer *ub_allow = uwsgi_buffer_new(64);
|
||||
if (uwsgi_buffer_append(ub_allow, "OPTIONS, GET, HEAD", 18)) {
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
if (urmp->allow_put) {
|
||||
if (uwsgi_buffer_append(ub_allow, ", PUT", 5)) {
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (urmp->allow_delete) {
|
||||
if (uwsgi_buffer_append(ub_allow, ", DELETE", 8)) {
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (urmp->allow_mkcol) {
|
||||
if (uwsgi_buffer_append(ub_allow, ", MKCOL", 7)) {
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_response_add_header(wsgi_req, "Allow", 5, ub_allow->buf, ub_allow->pos);
|
||||
uwsgi_buffer_destroy(ub_allow);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// MKCOL does not require stat
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) {
|
||||
if (!urmp->allow_mkcol) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
ret = rados_pool_create(urmp->cluster, filename);
|
||||
if (ret < 0) {
|
||||
if (ret == -EEXIST) {
|
||||
uwsgi_405(wsgi_req);
|
||||
}
|
||||
else {
|
||||
uwsgi_500(wsgi_req);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
ret = uwsgi_rados_async_stat(urio, ctx, filename, &stat_size, &stat_mtime, timeout);
|
||||
}
|
||||
else {
|
||||
ret = rados_stat(ctx, filename, &stat_size, &stat_mtime);
|
||||
}
|
||||
|
||||
// PUT AND MKCOL can be used for non-existent objects
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PUT", 3)) {
|
||||
if (!urmp->allow_put) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
if (ret == 0) {
|
||||
if (uwsgi_rados_delete(wsgi_req, ctx, filename, timeout)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (uwsgi_rados_put(wsgi_req, ctx, filename, timeout)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11);
|
||||
goto end;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
uwsgi_404(wsgi_req);
|
||||
else
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "DELETE", 6)) {
|
||||
if (!urmp->allow_delete) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_rados_delete(wsgi_req, ctx, filename, timeout)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) {
|
||||
uwsgi_405(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
size_t mime_type_len = 0;
|
||||
@@ -230,14 +625,14 @@ static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.mtime)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.size)) goto end;
|
||||
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) stat_mtime)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, stat_size)) goto end;
|
||||
|
||||
// skip body on HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
size_t remains = st.size;
|
||||
size_t remains = stat_size;
|
||||
if (uwsgi.async > 1) {
|
||||
if (uwsgi_rados_read_async(wsgi_req, ctx, filename, remains)) goto end;
|
||||
if (uwsgi_rados_read_async(wsgi_req, ctx, filename, remains, timeout)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_rados_read_sync(wsgi_req, ctx, filename, remains)) goto end;
|
||||
@@ -245,6 +640,10 @@ static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
end:
|
||||
if (uwsgi.async > 1) {
|
||||
close(urio->fds[0]);
|
||||
close(urio->fds[1]);
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,6 +387,7 @@ end:
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *response = NULL;
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
@@ -418,7 +419,7 @@ static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsg
|
||||
remote = at+1;
|
||||
}
|
||||
uint64_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
@@ -426,12 +427,13 @@ static int uwsgi_routing_func_rpc_raw(struct wsgi_request *wsgi_req, struct uwsg
|
||||
if (size == 0) goto end;
|
||||
|
||||
ret = uwsgi_blob_to_response(wsgi_req, response, size);
|
||||
free(response);
|
||||
if (ret == 0) {
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
end:
|
||||
free(response);
|
||||
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
@@ -441,6 +443,7 @@ end:
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *response = NULL;
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
@@ -472,7 +475,7 @@ static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsg
|
||||
remote = at+1;
|
||||
}
|
||||
uint64_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
@@ -483,9 +486,9 @@ static int uwsgi_routing_func_rpc_var(struct wsgi_request *wsgi_req, struct uwsg
|
||||
free(response);
|
||||
goto end;
|
||||
}
|
||||
free(response);
|
||||
ret = UWSGI_ROUTE_NEXT;
|
||||
end:
|
||||
free(response);
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
|
||||
@@ -23,7 +23,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *filename = uwsgi_spool_request(wsgi_req, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0);
|
||||
char *filename = uwsgi_spool_request(NULL, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (filename) {
|
||||
|
||||
@@ -92,7 +92,7 @@ static void stats_pusher_statsd(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|g");
|
||||
}
|
||||
else {
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|m");
|
||||
statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|c");
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
|
||||
+1
-1
@@ -423,7 +423,7 @@ static int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
// mute on 0 len...
|
||||
if (wsgi_req->proto_parser_pos > 0) {
|
||||
uwsgi_log("uwsgi_proto_http_parser() -> client closed connection");
|
||||
uwsgi_log("uwsgi_proto_http_parser() -> client closed connection\n");
|
||||
}
|
||||
return -1;
|
||||
|
||||
|
||||
+1
-1
@@ -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-06-01'
|
||||
s.date = '2014-09-05'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UWSGI_PLUGIN_API 1
|
||||
|
||||
#define UMAX16 65536
|
||||
#define UMAX8 256
|
||||
|
||||
@@ -604,6 +606,8 @@ struct uwsgi_daemon {
|
||||
|
||||
int ns_pid;
|
||||
int throttle;
|
||||
|
||||
char *chdir;
|
||||
};
|
||||
|
||||
struct uwsgi_logger {
|
||||
@@ -830,6 +834,8 @@ struct uwsgi_cache {
|
||||
int purge_lru;
|
||||
uint64_t lru_head;
|
||||
uint64_t lru_tail;
|
||||
|
||||
int store_delete;
|
||||
};
|
||||
|
||||
struct uwsgi_option {
|
||||
@@ -996,6 +1002,7 @@ struct uwsgi_protocol {
|
||||
};
|
||||
|
||||
struct uwsgi_server;
|
||||
struct uwsgi_instance;
|
||||
|
||||
struct uwsgi_plugin {
|
||||
|
||||
@@ -1054,6 +1061,9 @@ struct uwsgi_plugin {
|
||||
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
|
||||
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
|
||||
void (*exception_log)(struct wsgi_request *);
|
||||
|
||||
void (*vassal)(struct uwsgi_instance *);
|
||||
void (*vassal_before_exec)(struct uwsgi_instance *);
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
@@ -2723,6 +2733,9 @@ struct uwsgi_server {
|
||||
int stats_no_cores;
|
||||
int stats_no_metrics;
|
||||
|
||||
// uWSGI 2.0.7
|
||||
int vassal_sos;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -3014,6 +3027,7 @@ void uwsgi_xml_config(char *, struct wsgi_request *, char *[]);
|
||||
void uwsgi_500(struct wsgi_request *);
|
||||
void uwsgi_403(struct wsgi_request *);
|
||||
void uwsgi_404(struct wsgi_request *);
|
||||
void uwsgi_405(struct wsgi_request *);
|
||||
void uwsgi_redirect_to_slash(struct wsgi_request *);
|
||||
|
||||
void manage_snmp(int, uint8_t *, int, struct sockaddr_in *);
|
||||
@@ -3790,6 +3804,8 @@ int uwsgi_logic_opt_if_reload(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_reload(char *, char *);
|
||||
int uwsgi_logic_opt_if_plugin(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_plugin(char *, char *);
|
||||
int uwsgi_logic_opt_if_hostname(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_hostname(char *, char *);
|
||||
|
||||
|
||||
void uwsgi_opt_resolve(char *, char *, void *);
|
||||
@@ -4585,6 +4601,7 @@ void uwsgi_master_fifo_prepare();
|
||||
int uwsgi_master_fifo();
|
||||
int uwsgi_master_fifo_manage(int);
|
||||
|
||||
void uwsgi_log_do_rotate(char *, char *, off_t, int);
|
||||
void uwsgi_log_rotate();
|
||||
void uwsgi_log_reopen();
|
||||
void uwsgi_reload_workers();
|
||||
@@ -4783,6 +4800,7 @@ mode_t uwsgi_mode_t(char *, int *);
|
||||
|
||||
int uwsgi_notify_socket_manage(int);
|
||||
int uwsgi_notify_msg(char *, char *, size_t);
|
||||
void vassal_sos();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+6
-1
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '2.0.5'
|
||||
uwsgi_version = '2.0.7'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -53,6 +53,11 @@ if CPUCOUNT < 1:
|
||||
except:
|
||||
CPUCOUNT = 1
|
||||
|
||||
|
||||
# force single cpu in cygwin mode
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
CPUCOUNT=1
|
||||
|
||||
binary_list = []
|
||||
|
||||
started_at = time.time()
|
||||
|
||||
Reference in New Issue
Block a user