mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d09fd561b6 | ||
|
|
eefaa98cf3 | ||
|
|
ceda8a41e3 | ||
|
|
3021ba3f85 | ||
|
|
3be7312aa8 | ||
|
|
83d782051c | ||
|
|
70996049cc | ||
|
|
e219e209a0 | ||
|
|
eb728cfe23 | ||
|
|
7569544329 | ||
|
|
ee86bf593d | ||
|
|
27ea120325 | ||
|
|
dd21877dcb | ||
|
|
36ca76a231 | ||
|
|
0e339cf968 | ||
|
|
762200fdd6 | ||
|
|
688a464451 | ||
|
|
0dafe8aa5e | ||
|
|
5410cb4fe7 | ||
|
|
86f55a69cf | ||
|
|
6bd59ffe1c | ||
|
|
95a139f73d | ||
|
|
2e71d62704 | ||
|
|
8942e832e9 | ||
|
|
14b0a512e4 | ||
|
|
0c062bbc1a | ||
|
|
c63d94cb6e | ||
|
|
4da7564c3b | ||
|
|
d38edd839e | ||
|
|
cce041c7f0 | ||
|
|
ca68d6938a | ||
|
|
6d700e5a8b | ||
|
|
bad07a8520 | ||
|
|
363b88a7b7 | ||
|
|
932ed8ee29 | ||
|
|
7b8e12911a | ||
|
|
c95062856b | ||
|
|
6840b287d4 | ||
|
|
ae9104ed91 | ||
|
|
6c8d6ea15b | ||
|
|
755eb3956d | ||
|
|
225dc6f7a3 | ||
|
|
8509c41fd6 | ||
|
|
2ae9ac8b88 | ||
|
|
fed00ee5d6 | ||
|
|
66099275ca | ||
|
|
e7a40eb173 | ||
|
|
8342150b78 | ||
|
|
e2253f3693 | ||
|
|
d2f07c7583 | ||
|
|
1c87053a13 | ||
|
|
d69e23414f | ||
|
|
3d37d272ee | ||
|
|
9094a0f811 | ||
|
|
97efcca2b7 | ||
|
|
2445fd1f61 | ||
|
|
3234e0aae8 | ||
|
|
c5e7eb5d95 | ||
|
|
e051e4fe1c | ||
|
|
5f691ec987 | ||
|
|
a8e0aac9b0 | ||
|
|
bcdbab247c | ||
|
|
2e378dfc29 | ||
|
|
acc270ad81 | ||
|
|
b0c3ee02f9 | ||
|
|
06ab5eaee5 | ||
|
|
46de2ae0cb | ||
|
|
65fe93ac14 | ||
|
|
f7cdd22f9a | ||
|
|
3d553d2ae0 | ||
|
|
582d5828aa | ||
|
|
245a66b0e5 | ||
|
|
596c81124e | ||
|
|
a86a1fcc40 | ||
|
|
34036ac8b4 | ||
|
|
11cd6c34a5 | ||
|
|
aaea6ff2e2 | ||
|
|
38c30bc257 | ||
|
|
2f3e83b78e | ||
|
|
43e8c65841 | ||
|
|
555902a0ee | ||
|
|
9d4f4eb3c3 | ||
|
|
5d338cfb3a | ||
|
|
3406441d95 | ||
|
|
df08c7bfb5 | ||
|
|
75b4a3cb28 | ||
|
|
c356c01f12 | ||
|
|
ba8aa44baa | ||
|
|
a1dc7a660c | ||
|
|
3a4663844b | ||
|
|
309f449a43 | ||
|
|
f059a69312 | ||
|
|
93116a1239 | ||
|
|
5e4440443a | ||
|
|
373481b888 | ||
|
|
105b9c69cf | ||
|
|
9012ead72c | ||
|
|
6c1d2625a8 | ||
|
|
c0733b5771 | ||
|
|
f4759d7acd | ||
|
|
7082188a06 | ||
|
|
bcd9ed011d | ||
|
|
25c6d7a3a1 | ||
|
|
675c02c7fa | ||
|
|
32896a1418 | ||
|
|
548e736d84 | ||
|
|
87575b1a22 | ||
|
|
1aa6eeca1b | ||
|
|
f778e30d48 | ||
|
|
e071184d53 | ||
|
|
1d09cde778 | ||
|
|
70ee29becb | ||
|
|
60e26333bf | ||
|
|
865b9c199d | ||
|
|
833193a1ba | ||
|
|
4eab050634 | ||
|
|
688d1d3b75 | ||
|
|
349daee614 | ||
|
|
0d272cf747 | ||
|
|
46ac28efae | ||
|
|
31b3bcc83d | ||
|
|
f364d676fa | ||
|
|
c72fde1eed | ||
|
|
a5cacfbba6 | ||
|
|
921cfa5d79 | ||
|
|
9c676c62f5 | ||
|
|
2917de3e76 | ||
|
|
e836272c07 | ||
|
|
7e25452242 | ||
|
|
42d42d9e4c | ||
|
|
73c3e971e6 | ||
|
|
b627edf1b8 | ||
|
|
7fbc46750b | ||
|
|
1a63634359 | ||
|
|
c30e99a0df | ||
|
|
3c53f26cbd | ||
|
|
a5c74293d8 | ||
|
|
e5da0fc28c | ||
|
|
8e9bcc4758 | ||
|
|
bcf1f46d33 | ||
|
|
8cd13f2ad9 | ||
|
|
13df278cc4 | ||
|
|
56fedbd80c | ||
|
|
c4b563f260 | ||
|
|
39706c5899 | ||
|
|
e45f710694 | ||
|
|
0c86212aa2 | ||
|
|
3cfa743cb5 | ||
|
|
f14cb7e02a | ||
|
|
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 | ||
|
|
41b6005d30 | ||
|
|
497f7efa55 | ||
|
|
ad7ca0b098 | ||
|
|
1d591c95f2 | ||
|
|
d3daca0b16 | ||
|
|
bae1ade00a | ||
|
|
fd663aedbd | ||
|
|
6b9ce2d755 | ||
|
|
bd2728b391 | ||
|
|
dc250fd7b5 | ||
|
|
0a9345b8d4 | ||
|
|
db509f2d38 | ||
|
|
b12c39607d | ||
|
|
224260ce3e | ||
|
|
5f86d9522f | ||
|
|
a0fafe7847 | ||
|
|
daeaf1b231 | ||
|
|
fbc0a2775f | ||
|
|
d3c89a3f63 | ||
|
|
cd43a0d12d | ||
|
|
f06df71bfc | ||
|
|
eab2472dd0 | ||
|
|
87a2f3585c | ||
|
|
c257a9aa98 | ||
|
|
43aebe2d66 | ||
|
|
309115d611 | ||
|
|
5881d41b2b | ||
|
|
9fe4b7b14a | ||
|
|
930c19210a | ||
|
|
5beb170cfd | ||
|
|
a13103d851 | ||
|
|
bc5a86694f | ||
|
|
812685096b | ||
|
|
f70c070a0f | ||
|
|
accf622ffc | ||
|
|
04173869ee | ||
|
|
509a3c5cd4 | ||
|
|
81ad3a916d | ||
|
|
3f93a0b8e4 | ||
|
|
4408b655a4 | ||
|
|
71a6b8a304 | ||
|
|
7e9069eabf | ||
|
|
6c77dd0e38 | ||
|
|
27e506c72a | ||
|
|
bea68191e3 | ||
|
|
9b207d8a62 | ||
|
|
68d5b2de3b | ||
|
|
3a62573005 | ||
|
|
1c6dd42318 | ||
|
|
73ad0677bd | ||
|
|
15b2cf0712 | ||
|
|
0da0fa211a | ||
|
|
a8ecd71ffd | ||
|
|
ea0a95a441 | ||
|
|
6ac6e58bf7 | ||
|
|
f2c7addb73 | ||
|
|
fff5fa536b | ||
|
|
95825c9b99 | ||
|
|
1e84fcf880 | ||
|
|
0f742a72bf | ||
|
|
fd96a02576 | ||
|
|
77ca76428d | ||
|
|
9ea8f4f07c | ||
|
|
9ffc311177 | ||
|
|
4f89a350aa | ||
|
|
8f18c77587 | ||
|
|
371cafef94 | ||
|
|
89c31e9280 | ||
|
|
418d784148 | ||
|
|
c146275e9b | ||
|
|
eff23382c2 | ||
|
|
d566469c63 | ||
|
|
e008ce5d56 | ||
|
|
9d21c99183 | ||
|
|
7e80927317 | ||
|
|
6664e7120b | ||
|
|
687aabd30b | ||
|
|
fab656c635 | ||
|
|
72c31dab7a | ||
|
|
f19a301b73 | ||
|
|
19a19a8a67 | ||
|
|
d9c9f41624 | ||
|
|
dc97853f9f | ||
|
|
b089774c36 | ||
|
|
f8a271a027 | ||
|
|
ef12aaf13c | ||
|
|
a559361a30 | ||
|
|
6aad281441 | ||
|
|
7604c67018 | ||
|
|
afc962709f | ||
|
|
c11e0654a0 | ||
|
|
6e4f47cc76 | ||
|
|
20c9f0ef40 | ||
|
|
ef3c8a5bd9 | ||
|
|
76d0438fee | ||
|
|
18fd338908 | ||
|
|
2b35e95706 | ||
|
|
4761146599 | ||
|
|
3924cc639e | ||
|
|
5f09de0469 | ||
|
|
4f0e3fb79f | ||
|
|
05b6baf173 | ||
|
|
149823aac4 | ||
|
|
85d86dc10e | ||
|
|
e97d921909 | ||
|
|
c5e20bf4da | ||
|
|
a09d25ccaa | ||
|
|
bf01cea062 | ||
|
|
b6459be3e4 | ||
|
|
d42788c17b | ||
|
|
872730c116 | ||
|
|
6fce0aee84 | ||
|
|
e3d8a02614 | ||
|
|
b58696399e | ||
|
|
519c9f58b3 | ||
|
|
2c77c5c639 | ||
|
|
fb9e5a1891 | ||
|
|
5aa7d1a79f | ||
|
|
bc3442ba29 | ||
|
|
3061e36089 | ||
|
|
4f8c41cf61 | ||
|
|
b0065c379e | ||
|
|
57f71c974d | ||
|
|
b820fefbbd | ||
|
|
5f759f0d26 | ||
|
|
f7eb9ed1cd | ||
|
|
3a82732b19 | ||
|
|
d74e826f71 | ||
|
|
c846a9b388 | ||
|
|
001e4b6e39 | ||
|
|
a51a396f47 | ||
|
|
17965ea870 | ||
|
|
8a032b41ec | ||
|
|
a489cfc2c1 | ||
|
|
3b32672ff9 | ||
|
|
858131ba57 | ||
|
|
8a8d2f8675 | ||
|
|
9d37725323 | ||
|
|
e973492267 | ||
|
|
105a68bce9 | ||
|
|
0587a0ca53 | ||
|
|
d4b259d5e0 | ||
|
|
9e591c587f | ||
|
|
e7cce7b785 | ||
|
|
3285b224c2 | ||
|
|
2bba4cf15a |
+10
@@ -4,6 +4,12 @@
|
||||
*.jar
|
||||
*~
|
||||
*.so
|
||||
*.gox
|
||||
*.a
|
||||
*.dll
|
||||
*.key
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
@@ -12,3 +18,7 @@
|
||||
/t/ring/target
|
||||
|
||||
core/dot_h.c
|
||||
|
||||
+# coverity
|
||||
+/cov-int/
|
||||
+uwsgi.tar.xz
|
||||
|
||||
+6
-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>
|
||||
@@ -27,3 +27,8 @@ Roberto Leandrini
|
||||
Ryan Petrello
|
||||
Danila Shtan <danila@shtan.ru>
|
||||
Ævar Arnfjörð Bjarmason
|
||||
Yu Zhao (getcwd)
|
||||
Mathieu Dupuy
|
||||
Adriano Di Luzio (adriano@unbit.it)
|
||||
Curtis Maloney
|
||||
Vladimir Didenko
|
||||
|
||||
+80
-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);
|
||||
|
||||
@@ -321,12 +365,13 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
|
||||
ap_set_content_type(r, apr_pstrdup(r->pool, buf));
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int finish = 0;
|
||||
while(!finish) {
|
||||
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))) {
|
||||
|| (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 +387,46 @@ 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);
|
||||
|
||||
// found the last brigade?
|
||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) finish = 1;
|
||||
|
||||
// do not pass chunk if it is zero_sized
|
||||
apr_brigade_length(pass_bb, 0, &readbytes);
|
||||
|
||||
if ((readbytes > 0 && ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS) || c->aborted) {
|
||||
finish = 1;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,asyncio,greenlet
|
||||
inherit = base
|
||||
Binary file not shown.
+22
-23
@@ -363,6 +363,19 @@ void uwsgi_alarm_thread_start() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_alarm_trigger_uai(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// check if a log should raise an alarm
|
||||
void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
@@ -372,7 +385,14 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
while (ual) {
|
||||
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
|
||||
if (!ual->negate) {
|
||||
uwsgi_alarm_log_run(ual, msg, len);
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_trigger_uai(uall->alarm, msg, len);
|
||||
else
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
@@ -397,18 +417,6 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uai->last_msg_size = len;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// call the alarms mapped to a log line
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while (uall) {
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// this is the api function workers,mules and whatever you want can call from code
|
||||
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
if (!uwsgi.alarm_thread) return;
|
||||
@@ -416,16 +424,7 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
|
||||
if (!uai) return;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = &uai;
|
||||
iov[0].iov_len = sizeof(long);
|
||||
iov[1].iov_base = msg;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
// now send the message to the alarm thread
|
||||
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
|
||||
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
|
||||
}
|
||||
uwsgi_alarm_trigger_uai(uai, msg, len);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
|
||||
|
||||
+2
-1
@@ -369,7 +369,8 @@ void async_schedule_to_req_green(void) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
if (uwsgi.schedule_to_main)
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
+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] == '\\') {
|
||||
|
||||
+230
-46
@@ -24,6 +24,49 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
*/
|
||||
|
||||
static void cache_full(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
int force_clear = 0;
|
||||
|
||||
if (!uc->ignore_full) {
|
||||
if (uc->purge_lru)
|
||||
uwsgi_log("LRU item will be purged from cache \"%s\"\n", uc->name);
|
||||
else
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
}
|
||||
|
||||
uc->full++;
|
||||
|
||||
if (uc->purge_lru && uc->lru_head)
|
||||
uwsgi_cache_del2(uc, NULL, 0, uc->lru_head, UWSGI_CACHE_FLAG_LOCAL);
|
||||
|
||||
// we do not need locking here !
|
||||
if (uc->sweep_on_full) {
|
||||
uint64_t removed = 0;
|
||||
uint64_t now = (uint64_t) uwsgi_now();
|
||||
if (uc->next_scan <= now) {
|
||||
uc->next_scan = now + uc->sweep_on_full;
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
if (uci->expires > 0 && uci->expires <= now) {
|
||||
if (!uwsgi_cache_del2(uc, NULL, 0, i, 0)) {
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removed == 0) {
|
||||
force_clear = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uc->clear_on_full || force_clear) {
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_find_free_blocks(struct uwsgi_cache *uc, uint64_t need) {
|
||||
// how many blocks we need ?
|
||||
uint64_t needed_blocks = need/uc->blocksize;
|
||||
@@ -331,6 +374,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);
|
||||
@@ -412,6 +463,17 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
|
||||
}
|
||||
|
||||
static uint64_t check_lazy(struct uwsgi_cache *uc, struct uwsgi_cache_item *uci, uint64_t slot) {
|
||||
if (!uci->expires || !uc->lazy_expire) return slot;
|
||||
uint64_t now = (uint64_t) uwsgi_now();
|
||||
// expired ?
|
||||
if (uci->expires <= now) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, slot, UWSGI_CACHE_FLAG_LOCAL);
|
||||
return 0;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = uc->hash->func(key, keylen);
|
||||
@@ -437,7 +499,7 @@ static uint64_t uwsgi_cache_get_index(struct uwsgi_cache *uc, char *key, uint16_
|
||||
if (memcmp(uci->key, key, keylen))
|
||||
goto cycle;
|
||||
|
||||
return slot;
|
||||
return check_lazy(uc, uci, slot);
|
||||
|
||||
cycle:
|
||||
while (uci->next) {
|
||||
@@ -460,8 +522,9 @@ cycle:
|
||||
continue;
|
||||
if (uci->keysize != keylen)
|
||||
continue;
|
||||
if (!memcmp(uci->key, key, keylen))
|
||||
return slot;
|
||||
if (!memcmp(uci->key, key, keylen)) {
|
||||
return check_lazy(uc, uci, slot);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -472,6 +535,38 @@ uint32_t uwsgi_cache_exists2(struct uwsgi_cache *uc, char *key, uint16_t keylen)
|
||||
return uwsgi_cache_get_index(uc, key, keylen);
|
||||
}
|
||||
|
||||
static void lru_remove_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
{
|
||||
struct uwsgi_cache_item *prev, *next, *curr = cache_item(index);
|
||||
|
||||
if (curr->lru_next) {
|
||||
next = cache_item(curr->lru_next);
|
||||
next->lru_prev = curr->lru_prev;
|
||||
} else
|
||||
uc->lru_tail = curr->lru_prev;
|
||||
|
||||
if (curr->lru_prev) {
|
||||
prev = cache_item(curr->lru_prev);
|
||||
prev->lru_next = curr->lru_next;
|
||||
} else
|
||||
uc->lru_head = curr->lru_next;
|
||||
}
|
||||
|
||||
static void lru_add_item(struct uwsgi_cache *uc, uint64_t index)
|
||||
{
|
||||
struct uwsgi_cache_item *prev, *curr = cache_item(index);
|
||||
|
||||
if (uc->lru_tail) {
|
||||
prev = cache_item(uc->lru_tail);
|
||||
prev->lru_next = index;
|
||||
} else
|
||||
uc->lru_head = index;
|
||||
|
||||
curr->lru_next = 0;
|
||||
curr->lru_prev = uc->lru_tail;
|
||||
uc->lru_tail = index;
|
||||
}
|
||||
|
||||
char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_t * valsize) {
|
||||
|
||||
uint64_t index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
@@ -481,6 +576,10 @@ char *uwsgi_cache_get2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
if (uci->flags & UWSGI_CACHE_FLAG_UNGETTABLE)
|
||||
return NULL;
|
||||
*valsize = uci->valsize;
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
}
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
@@ -520,6 +619,10 @@ char *uwsgi_cache_get3(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint6
|
||||
*valsize = uci->valsize;
|
||||
if (expires)
|
||||
*expires = uci->expires;
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
}
|
||||
uci->hits++;
|
||||
uc->hits++;
|
||||
return uc->data + (uci->first_block * uc->blocksize);
|
||||
@@ -588,6 +691,10 @@ int uwsgi_cache_del2(struct uwsgi_cache *uc, char *key, uint16_t keylen, uint64_
|
||||
// reset hashtable entry
|
||||
uc->hashtable[uci->hash % uc->hashsize] = 0;
|
||||
}
|
||||
|
||||
if (uc->purge_lru)
|
||||
lru_remove_item(uc, index);
|
||||
|
||||
uc->n_items--;
|
||||
}
|
||||
|
||||
@@ -666,9 +773,9 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
index = uwsgi_cache_get_index(uc, key, keylen);
|
||||
if (!index) {
|
||||
if (!uc->unused_blocks_stack_ptr) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
goto end;
|
||||
cache_full(uc);
|
||||
if (!uc->unused_blocks_stack_ptr)
|
||||
goto end;
|
||||
}
|
||||
|
||||
index = uc->unused_blocks_stack[uc->unused_blocks_stack_ptr];
|
||||
@@ -681,24 +788,27 @@ 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) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
uc->unused_blocks_stack_ptr++;
|
||||
cache_full(uc);
|
||||
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 {
|
||||
uc->blocks_bitmap_pos = uci->first_block + needed_blocks;
|
||||
}
|
||||
}
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
if (uc->purge_lru)
|
||||
lru_add_item(uc, index);
|
||||
else if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!uc->next_scan || uc->next_scan > expires)
|
||||
uc->next_scan = expires;
|
||||
}
|
||||
uci->expires = expires;
|
||||
uci->hash = uc->hash->func(key, keylen);
|
||||
@@ -763,9 +873,16 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = cache_item(index);
|
||||
if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE) && !(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!(flags & UWSGI_CACHE_FLAG_FIXEXPIRE)) {
|
||||
if (uc->purge_lru) {
|
||||
lru_remove_item(uc, index);
|
||||
lru_add_item(uc, index);
|
||||
} else if (expires && !(flags & UWSGI_CACHE_FLAG_ABSEXPIRE)) {
|
||||
now = uwsgi_now();
|
||||
expires += now;
|
||||
if (!uc->next_scan || uc->next_scan > expires)
|
||||
uc->next_scan = expires;
|
||||
}
|
||||
uci->expires = expires;
|
||||
}
|
||||
if (uc->blocks_bitmap) {
|
||||
@@ -773,15 +890,14 @@ 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) {
|
||||
uwsgi_log("*** DANGER cache \"%s\" is FULL !!! ***\n", uc->name);
|
||||
uc->full++;
|
||||
uci->first_block = old_first_block;
|
||||
cache_full(uc);
|
||||
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 {
|
||||
@@ -983,39 +1099,66 @@ void *cache_udp_server_loop(void *ucache) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint64_t cache_sweeper_free_items(struct uwsgi_cache *uc) {
|
||||
uint64_t i;
|
||||
uint64_t freed_items = 0;
|
||||
|
||||
if (uc->no_expire || uc->purge_lru || uc->lazy_expire)
|
||||
return 0;
|
||||
|
||||
uwsgi_rlock(uc->lock);
|
||||
if (!uc->next_scan || uc->next_scan > (uint64_t)uwsgi.current_time) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
|
||||
// skip the first slot
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
|
||||
uwsgi_wlock(uc->lock);
|
||||
// we reset next scan time first, then we find the least
|
||||
// expiration time from those that are NOT expired yet.
|
||||
if (i == 1)
|
||||
uc->next_scan = 0;
|
||||
|
||||
if (uci->expires) {
|
||||
if (uci->expires <= (uint64_t)uwsgi.current_time) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, UWSGI_CACHE_FLAG_LOCAL);
|
||||
freed_items++;
|
||||
} else if (!uc->next_scan || uc->next_scan > uci->expires) {
|
||||
uc->next_scan = uci->expires;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
}
|
||||
|
||||
return freed_items;
|
||||
}
|
||||
|
||||
static void *cache_sweeper_loop(void *ucache) {
|
||||
|
||||
uint64_t i;
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
struct uwsgi_cache *uc = (struct uwsgi_cache *) ucache;
|
||||
|
||||
if (!uwsgi.cache_expire_freq)
|
||||
uwsgi.cache_expire_freq = 3;
|
||||
|
||||
// remove expired cache items TODO use rb_tree timeouts
|
||||
for (;;) {
|
||||
struct uwsgi_cache *uc;
|
||||
|
||||
for (uc = (struct uwsgi_cache *)ucache; uc; uc = uc->next) {
|
||||
uint64_t freed_items = cache_sweeper_free_items(uc);
|
||||
if (uwsgi.cache_report_freed_items && freed_items)
|
||||
uwsgi_log("freed %llu items for cache \"%s\"\n", (unsigned long long)freed_items, uc->name);
|
||||
}
|
||||
|
||||
sleep(uwsgi.cache_expire_freq);
|
||||
uint64_t freed_items = 0;
|
||||
// skip the first slot
|
||||
for (i = 1; i < uc->max_items; i++) {
|
||||
uwsgi_wlock(uc->lock);
|
||||
struct uwsgi_cache_item *uci = cache_item(i);
|
||||
if (uci->expires) {
|
||||
if (uci->expires < (uint64_t) uwsgi.current_time) {
|
||||
uwsgi_cache_del2(uc, NULL, 0, i, UWSGI_CACHE_FLAG_LOCAL);
|
||||
freed_items++;
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
}
|
||||
if (uwsgi.cache_report_freed_items && freed_items > 0) {
|
||||
uwsgi_log("freed %llu items for cache \"%s\"\n", (unsigned long long) freed_items, uc->name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1035,19 +1178,28 @@ void uwsgi_cache_sync_all() {
|
||||
|
||||
void uwsgi_cache_start_sweepers() {
|
||||
struct uwsgi_cache *uc = uwsgi.caches;
|
||||
|
||||
if (uwsgi.cache_no_expire)
|
||||
return;
|
||||
|
||||
int need_to_run = 0;
|
||||
while(uc) {
|
||||
pthread_t cache_sweeper;
|
||||
if (!uwsgi.cache_no_expire && !uc->no_expire) {
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, (void *) uc)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
uwsgi_log("unable to run the sweeper for cache \"%s\" !!!\n", uc->name);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("sweeper thread enabled for cache \"%s\"\n", uc->name);
|
||||
}
|
||||
if (!uc->no_expire && !uc->purge_lru && !uc->lazy_expire) {
|
||||
need_to_run = 1;
|
||||
break;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
|
||||
if (!need_to_run) return;
|
||||
|
||||
pthread_t cache_sweeper;
|
||||
if (pthread_create(&cache_sweeper, NULL, cache_sweeper_loop, uwsgi.caches)) {
|
||||
uwsgi_error("uwsgi_cache_start_sweepers()/pthread_create()");
|
||||
uwsgi_log("unable to run the cache sweeper!!!\n");
|
||||
return;
|
||||
}
|
||||
uwsgi_log("cache sweeper thread enabled\n");
|
||||
}
|
||||
|
||||
void uwsgi_cache_start_sync_servers() {
|
||||
@@ -1115,12 +1267,19 @@ 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;
|
||||
char *c_bitmap = NULL;
|
||||
char *c_use_last_modified = NULL;
|
||||
char *c_math_initial = NULL;
|
||||
char *c_ignore_full = NULL;
|
||||
char *c_purge_lru = NULL;
|
||||
char *c_lazy_expire = NULL;
|
||||
char *c_sweep_on_full = NULL;
|
||||
char *c_clear_on_full = NULL;
|
||||
char *c_no_expire = NULL;
|
||||
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"name", &c_name,
|
||||
@@ -1137,6 +1296,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,
|
||||
@@ -1148,6 +1309,14 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
"bitmap", &c_bitmap,
|
||||
"lastmod", &c_use_last_modified,
|
||||
"math_initial", &c_math_initial,
|
||||
"ignore_full", &c_ignore_full,
|
||||
"purge_lru", &c_purge_lru,
|
||||
"lru", &c_purge_lru,
|
||||
"lazy_expire", &c_lazy_expire,
|
||||
"lazy", &c_lazy_expire,
|
||||
"sweep_on_full", &c_sweep_on_full,
|
||||
"clear_on_full", &c_clear_on_full,
|
||||
"no_expire", &c_no_expire,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse cache definition\n");
|
||||
exit(1);
|
||||
@@ -1195,9 +1364,19 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->max_item_size = uc->blocksize * uc->blocks;
|
||||
}
|
||||
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);
|
||||
|
||||
if (c_lazy_expire) uc->lazy_expire = 1;
|
||||
if (c_sweep_on_full) {
|
||||
uc->sweep_on_full = uwsgi_n64(c_sweep_on_full);
|
||||
}
|
||||
if (c_clear_on_full) uc->clear_on_full = 1;
|
||||
if (c_no_expire) uc->no_expire = 1;
|
||||
|
||||
uc->store_sync = uwsgi.cache_store_sync;
|
||||
if (c_store_sync) { uc->store_sync = uwsgi_n64(c_store_sync); }
|
||||
|
||||
@@ -1229,6 +1408,8 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
if (c_purge_lru)
|
||||
uc->purge_lru = 1;
|
||||
}
|
||||
|
||||
uwsgi_cache_init(uc);
|
||||
@@ -1484,7 +1665,10 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, uint64
|
||||
|
||||
// we have a local cache !!!
|
||||
if (uc) {
|
||||
uwsgi_rlock(uc->lock);
|
||||
if (uc->purge_lru)
|
||||
uwsgi_wlock(uc->lock);
|
||||
else
|
||||
uwsgi_rlock(uc->lock);
|
||||
char *value = uwsgi_cache_get3(uc, key, keylen, vallen, expires);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uc->lock);
|
||||
|
||||
@@ -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;
|
||||
@@ -816,3 +836,19 @@ char *uwsgi_manage_placeholder(char *key) {
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_resolve(char *opt, char *value, void *foo) {
|
||||
char *equal = strchr(value, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid resolve syntax, must be placeholder=domain\n");
|
||||
exit(1);
|
||||
}
|
||||
char *ip = uwsgi_resolve_ip(equal+1);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve name %s\n", equal+1);
|
||||
uwsgi_error("uwsgi_resolve_ip()");
|
||||
exit(1);
|
||||
}
|
||||
char *new_opt = uwsgi_concat2n(value, (equal-value)+1, ip, strlen(ip));
|
||||
uwsgi_opt_set_placeholder(opt, new_opt, (void *) 1);
|
||||
}
|
||||
|
||||
+18
-2
@@ -237,7 +237,12 @@ void uwsgi_detach_daemons() {
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
if (uwsgi_instance_is_reloading && ud->reload_signal > 0) {
|
||||
kill(-(ud->pid), ud->reload_signal);
|
||||
}
|
||||
else {
|
||||
kill(-(ud->pid), ud->stop_signal);
|
||||
}
|
||||
sleep(1);
|
||||
waitpid(ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
@@ -292,11 +297,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 +509,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 +531,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 +579,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);
|
||||
|
||||
+777
-575
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
+7
-6
@@ -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) {
|
||||
@@ -947,7 +948,7 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct timespec ts;
|
||||
struct kevent ev;
|
||||
|
||||
if (timeout <= 0) {
|
||||
if (timeout < 0) {
|
||||
ret = kevent(eq, NULL, 0, &ev, 1, NULL);
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-2
@@ -464,6 +464,7 @@ void uwsgi_exception_setup_handlers() {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
|
||||
while(usl) {
|
||||
// do not free handler !!!
|
||||
char *handler = uwsgi_str(usl->value);
|
||||
char *colon = strchr(handler, ':');
|
||||
if (colon) {
|
||||
@@ -472,10 +473,8 @@ void uwsgi_exception_setup_handlers() {
|
||||
struct uwsgi_exception_handler *ueh = uwsgi_exception_handler_by_name(handler);
|
||||
if (!ueh) {
|
||||
uwsgi_log("unable to find exception handler: %s\n", handler);
|
||||
free(handler);
|
||||
exit(1);
|
||||
}
|
||||
free(handler);
|
||||
|
||||
struct uwsgi_exception_handler_instance *uehi = uwsgi_calloc(sizeof(struct uwsgi_exception_handler_instance));
|
||||
uehi->handler = ueh;
|
||||
|
||||
@@ -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
@@ -72,7 +72,7 @@ void gateway_respawn(int id) {
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
uwsgi_close_all_sockets();
|
||||
uwsgi_close_all_unshared_sockets();
|
||||
if (uwsgi.master_as_root)
|
||||
uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
|
||||
+119
-6
@@ -91,6 +91,14 @@ static int uwsgi_hook_exec(char *arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_safeexec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exit(char *arg) {
|
||||
int exit_code = 0;
|
||||
if (strlen(arg) > 1) {
|
||||
@@ -233,17 +241,26 @@ static int uwsgi_hook_writen(char *arg) {
|
||||
|
||||
static int uwsgi_hook_appendn(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook appendn syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
if (space)
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
if (space)
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
if (!space) {
|
||||
// simple newline
|
||||
if (write(fd, "\n", 1) != 1) {
|
||||
uwsgi_error("uwsgi_hook_appendn()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
char *buf = uwsgi_malloc(l + 1);
|
||||
@@ -485,6 +502,76 @@ static int uwsgi_hook_callret(char *arg) {
|
||||
return func();
|
||||
}
|
||||
|
||||
static int uwsgi_hook_rpc(char *arg) {
|
||||
|
||||
int ret = -1;
|
||||
size_t i, argc = 0;
|
||||
char **rargv = uwsgi_split_quoted(arg, strlen(arg), " \t", &argc);
|
||||
if (!argc) goto end;
|
||||
if (argc > 256) goto destroy;
|
||||
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
|
||||
char *node = NULL;
|
||||
char *func = rargv[0];
|
||||
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
node = at + 1;
|
||||
}
|
||||
|
||||
for(i=0;i<(argc-1);i++) {
|
||||
size_t a_len = strlen(rargv[i+1]);
|
||||
if (a_len > 0xffff) goto destroy;
|
||||
argv[i] = rargv[i+1] ;
|
||||
argvs[i] = a_len;
|
||||
}
|
||||
|
||||
uint64_t size = 0;
|
||||
// response must be always freed
|
||||
char *response = uwsgi_do_rpc(node, func, argc-1, argv, argvs, &size);
|
||||
if (response) {
|
||||
if (at) *at = '@';
|
||||
uwsgi_log("[rpc result from \"%s\"] %.*s\n", rargv[0], size, response);
|
||||
free(response);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
destroy:
|
||||
for(i=0;i<argc;i++) {
|
||||
free(rargv[i]);
|
||||
}
|
||||
end:
|
||||
free(rargv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_retryrpc(char *arg) {
|
||||
for(;;) {
|
||||
int ret = uwsgi_hook_rpc(arg);
|
||||
if (!ret) break;
|
||||
sleep(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_wait_for_fs(char *arg) {
|
||||
return uwsgi_wait_for_fs(arg, 0);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_wait_for_file(char *arg) {
|
||||
return uwsgi_wait_for_fs(arg, 1);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_wait_for_dir(char *arg) {
|
||||
return uwsgi_wait_for_fs(arg, 2);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_wait_for_socket(char *arg) {
|
||||
return uwsgi_wait_for_socket(arg);
|
||||
}
|
||||
|
||||
void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
@@ -499,6 +586,7 @@ void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("sticky", uwsgi_hook_sticky);
|
||||
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
uwsgi_register_hook("safeexec", uwsgi_hook_safeexec);
|
||||
|
||||
uwsgi_register_hook("create", uwsgi_hook_creat);
|
||||
uwsgi_register_hook("creat", uwsgi_hook_creat);
|
||||
@@ -523,6 +611,15 @@ void uwsgi_register_base_hooks() {
|
||||
|
||||
uwsgi_register_hook("alarm", uwsgi_hook_alarm);
|
||||
|
||||
uwsgi_register_hook("rpc", uwsgi_hook_rpc);
|
||||
uwsgi_register_hook("retryrpc", uwsgi_hook_retryrpc);
|
||||
|
||||
uwsgi_register_hook("wait_for_fs", uwsgi_hook_wait_for_fs);
|
||||
uwsgi_register_hook("wait_for_file", uwsgi_hook_wait_for_file);
|
||||
uwsgi_register_hook("wait_for_dir", uwsgi_hook_wait_for_dir);
|
||||
|
||||
uwsgi_register_hook("wait_for_socket", uwsgi_hook_wait_for_socket);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
@@ -561,6 +658,22 @@ void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
uwsgi_log_verbose("FATAL hook failed, destroying instance\n");
|
||||
if (uwsgi.master_process) {
|
||||
if (uwsgi.workers) {
|
||||
if (uwsgi.workers[0].pid == getpid()) {
|
||||
kill_them_all(0);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (kill(uwsgi.workers[0].pid, SIGINT)) {
|
||||
uwsgi_error("uwsgi_hooks_run()/kill()");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -3,9 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct http_status_codes {
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
const char key[3];
|
||||
const char *message;
|
||||
int message_size;
|
||||
};
|
||||
|
||||
/* statistically ordered */
|
||||
@@ -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;
|
||||
@@ -113,6 +113,7 @@ void uwsgi_init_default() {
|
||||
uwsgi.log_master_bufsize = 8192;
|
||||
|
||||
uwsgi.worker_reload_mercy = 60;
|
||||
uwsgi.mule_reload_mercy = 60;
|
||||
|
||||
uwsgi.max_vars = MAX_VARS;
|
||||
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
|
||||
@@ -470,6 +471,10 @@ void sanitize_args() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
|
||||
if (!uwsgi.mem_collector_freq) uwsgi.mem_collector_freq = 3;
|
||||
}
|
||||
|
||||
/* here we try to choose if thunder lock is a good thing */
|
||||
#ifdef UNBIT
|
||||
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+9
-8
@@ -277,14 +277,12 @@ static void legions_check_nodes_step2() {
|
||||
memcpy(best_uuid, node->uuid, 36);
|
||||
}
|
||||
// go on if i am not an arbiter
|
||||
else if (ul->valor > 0) {
|
||||
// no potential Lord is available, i will propose myself
|
||||
// but only if i am not suspended...
|
||||
if (uwsgi_now() > ul->suspended_til) {
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
// no potential Lord is available, i will propose myself
|
||||
// but only if i am not suspended...
|
||||
else if (ul->valor > 0 && uwsgi_now() > ul->suspended_til) {
|
||||
best_valor = ul->valor;
|
||||
memcpy(best_uuid, ul->uuid, 36);
|
||||
i_am_the_best = 1;
|
||||
}
|
||||
else {
|
||||
// empty lord
|
||||
@@ -1212,6 +1210,9 @@ next:
|
||||
legion = legion->next;
|
||||
}
|
||||
|
||||
// this must be called only by the master !!!
|
||||
if (!uwsgi.workers) return;
|
||||
if (uwsgi.workers[0].pid != getpid()) return;
|
||||
uwsgi_legion_announce_death();
|
||||
}
|
||||
|
||||
|
||||
+109
-92
@@ -3,6 +3,7 @@
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
#include <sys/user.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <kvm.h>
|
||||
#elif defined(__sun__)
|
||||
/* Terrible Hack !!! */
|
||||
@@ -13,10 +14,6 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
@@ -301,19 +298,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 +351,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) {
|
||||
@@ -477,13 +482,19 @@ void uwsgi_check_logrotate(void) {
|
||||
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
off_t logsize;
|
||||
|
||||
if (uwsgi.log_master) {
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
else {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
if (logsize < 0) {
|
||||
uwsgi_error("uwsgi_check_logrotate()/lseek()");
|
||||
return;
|
||||
}
|
||||
uwsgi.shared->logsize = logsize;
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
@@ -505,40 +516,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() {
|
||||
@@ -917,7 +934,7 @@ struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
|
||||
while (ul) {
|
||||
if (!strcmp(ul->id, id)) {
|
||||
if (ul->id && !strcmp(ul->id, id)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
@@ -1839,7 +1856,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
size_t msg_len = len;
|
||||
if (msg[len-1] == '\n') msg_len--;
|
||||
char *e_json = uwsgi_malloc(msg_len * 2);
|
||||
char *e_json = uwsgi_malloc((msg_len * 2)+1);
|
||||
escape_json(msg, msg_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1848,7 +1865,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
char *e_json = uwsgi_malloc(len * 2);
|
||||
char *e_json = uwsgi_malloc((len * 2)+1);
|
||||
escape_json(msg, len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
@@ -1869,7 +1886,7 @@ static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, si
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
char *e_json = uwsgi_malloc(strftime_len * 2);
|
||||
char *e_json = uwsgi_malloc((strftime_len * 2)+1);
|
||||
escape_json(sftime, strftime_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
|
||||
+46
-8
@@ -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;
|
||||
@@ -135,6 +145,15 @@ void uwsgi_master_check_mercy() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0 && uwsgi.mules[i].cursed_at) {
|
||||
if (uwsgi_now() > uwsgi.mules[i].no_mercy_at) {
|
||||
uwsgi_log_verbose("mule %d (pid: %d) is taking too much time to die...NO MERCY !!!\n", i + 1, uwsgi.mules[i].pid);
|
||||
uwsgi_curse_mule(i, SIGKILL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -264,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;
|
||||
@@ -836,7 +861,10 @@ int master_loop(char **argv, char **environ) {
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... reloading daemon \"%s\" (pid: %d) !!! ***\n", touched, ud->command, (int) ud->pid);
|
||||
if (kill(-ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
// killing process group failed, try to kill by process id
|
||||
if (kill(ud->pid, ud->stop_signal)) {
|
||||
uwsgi_error("[uwsgi-daemon/touch] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -907,6 +935,7 @@ int master_loop(char **argv, char **environ) {
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid == diedpid) {
|
||||
uwsgi_log("mule %d (pid: %d) annihilated\n", i + 1, (int) diedpid);
|
||||
uwsgi.mules[i].pid = 0;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
@@ -954,6 +983,11 @@ next:
|
||||
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
|
||||
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
|
||||
if (uwsgi.lazy_apps && uwsgi.need_app) {
|
||||
uwsgi_log_verbose("need-app requested, destroying the instance...\n");
|
||||
kill_them_all(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
|
||||
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
|
||||
@@ -969,6 +1003,10 @@ next:
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_GO_CHEAP_CODE) {
|
||||
uwsgi_log("worker %d asked for cheap mode (pid: %d)...\n", thewid, (int) diedpid);
|
||||
uwsgi.workers[thewid].cheaped = 1;
|
||||
}
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
|
||||
+61
-18
@@ -25,6 +25,11 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
@@ -34,27 +39,51 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
static time_t last_check = 0;
|
||||
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
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) {
|
||||
time_t now = uwsgi_now();
|
||||
if (now != last_check) {
|
||||
uwsgi_log_verbose("chain is still waiting for worker %d...\n", uwsgi.status.chain_reloading-1);
|
||||
last_check = now;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -115,12 +144,25 @@ void uwsgi_master_check_idle() {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
// first send SIGINT
|
||||
kill(uwsgi.workers[i].pid, SIGINT);
|
||||
// and start waiting upto 3 seconds
|
||||
int j;
|
||||
for(j=0;j<3;j++) {
|
||||
sleep(1);
|
||||
int ret = waitpid(uwsgi.workers[i].pid, &waitpid_status, WNOHANG);
|
||||
if (ret == 0) continue;
|
||||
if (ret == (int) uwsgi.workers[i].pid) goto done;
|
||||
// on error, directly send SIGKILL
|
||||
break;
|
||||
}
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
done:
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].rss_size = 0;
|
||||
uwsgi.workers[i].vsz_size = 0;
|
||||
@@ -312,6 +354,7 @@ int uwsgi_master_check_daemons_death(int diedpid) {
|
||||
|
||||
int uwsgi_worker_is_busy(int wid) {
|
||||
int i;
|
||||
if (uwsgi.workers[uwsgi.mywid].sig) return 1;
|
||||
for(i=0;i<uwsgi.cores;i++) {
|
||||
if (uwsgi.workers[wid].cores[i].in_request) {
|
||||
return 1;
|
||||
|
||||
+21
-12
@@ -24,6 +24,15 @@ void uwsgi_curse(int wid, int sig) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_curse_mule(int mid, int sig) {
|
||||
uwsgi.mules[mid].cursed_at = uwsgi_now();
|
||||
uwsgi.mules[mid].no_mercy_at = uwsgi.mules[mid].cursed_at + uwsgi.mule_reload_mercy;
|
||||
|
||||
if (sig) {
|
||||
(void) kill(uwsgi.mules[mid].pid, sig);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_signal_spoolers(int signum) {
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
@@ -53,15 +62,6 @@ void uwsgi_destroy_processes() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO mules can be programmed to be gracefully reloaded
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
kill(uwsgi.mules[i].pid, SIGKILL);
|
||||
waitpid(uwsgi.mules[i].pid, &waitpid_status, 0);
|
||||
uwsgi_log("mule %d has been buried (pid: %d)\n", i, (int) uwsgi.mules[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_pid > 0) {
|
||||
kill(uwsgi.emperor_pid, SIGINT);
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
@@ -162,6 +162,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
ignore_algo = 1;
|
||||
}
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
goto safe;
|
||||
}
|
||||
|
||||
// if cheaper limits wants to change worker count, then skip cheaper algo
|
||||
@@ -172,6 +173,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
needed_workers = 0;
|
||||
}
|
||||
|
||||
safe:
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
@@ -796,7 +798,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
// allocate 2x the size of original command
|
||||
// in case we need to escape all chars
|
||||
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ud->command)*2)+1);
|
||||
escape_json(ud->command, strlen(ud->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
|
||||
free(cmd);
|
||||
@@ -913,7 +915,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi.has_metrics && !uwsgi.stats_no_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
@@ -1145,6 +1147,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.stats_no_cores) goto nocores;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
@@ -1206,9 +1210,12 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
nocores:
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
|
||||
if (i < uwsgi.numproc - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
@@ -1284,7 +1291,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
|
||||
goto end;
|
||||
|
||||
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
|
||||
char *cmd = uwsgi_malloc((strlen(ucron->command)*2)+1);
|
||||
escape_json(ucron->command, strlen(ucron->command), cmd);
|
||||
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
|
||||
free(cmd);
|
||||
@@ -1714,6 +1721,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) {
|
||||
@@ -1772,6 +1780,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) {
|
||||
|
||||
+27
-2
@@ -321,6 +321,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
char *m_initial_value = NULL;
|
||||
char *m_children = NULL;
|
||||
char *m_alias = NULL;
|
||||
char *m_reset_after_push = NULL;
|
||||
|
||||
if (!strchr(arg, '=')) {
|
||||
m_name = uwsgi_str(arg);
|
||||
@@ -340,6 +341,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
"arg3n", &m_arg3n,
|
||||
"children", &m_children,
|
||||
"alias", &m_alias,
|
||||
"reset_after_push", &m_reset_after_push,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid metric keyval syntax: %s\n", arg);
|
||||
exit(1);
|
||||
@@ -381,6 +383,10 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
struct uwsgi_metric* um = uwsgi_register_metric(m_name, m_oid, type, collector, NULL, freq, NULL);
|
||||
um->initial_value = initial_value;
|
||||
|
||||
if (m_reset_after_push){
|
||||
um->reset_after_push = 1;
|
||||
}
|
||||
|
||||
if (m_children) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(m_children, ";", p, ctx) {
|
||||
@@ -427,6 +433,7 @@ struct uwsgi_metric *uwsgi_register_keyval_metric(char *arg) {
|
||||
if (m_initial_value) free(m_initial_value);
|
||||
if (m_children) free(m_children);
|
||||
if (m_alias) free(m_alias);
|
||||
if (m_reset_after_push) free(m_reset_after_push);
|
||||
return um;
|
||||
}
|
||||
|
||||
@@ -613,7 +620,7 @@ struct uwsgi_metric *uwsgi_metric_find_by_asn(char *asn, size_t len) {
|
||||
}\
|
||||
if (!um) return -1;\
|
||||
if (um->collector || um->type == UWSGI_METRIC_ALIAS) return -1;\
|
||||
uwsgi_rlock(uwsgi.metrics_lock)
|
||||
uwsgi_wlock(uwsgi.metrics_lock)
|
||||
|
||||
int uwsgi_metric_set(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
@@ -694,6 +701,22 @@ int64_t uwsgi_metric_getn(char *name, size_t nlen, char *oid, size_t olen) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_metric_set_max(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if (value > *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_metric_set_min(char *name, char *oid, int64_t value) {
|
||||
um_op;
|
||||
if ((value > um->initial_value || 0) && value < *um->value)
|
||||
*um->value = value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define uwsgi_metric_name(f, n) ret = snprintf(buf, 4096, f, n); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
#define uwsgi_metric_name2(f, n, n2) ret = snprintf(buf, 4096, f, n, n2); if (ret <= 1 || ret >= 4096) { uwsgi_log("unable to register metric name %s\n", f); exit(1);}
|
||||
|
||||
@@ -768,9 +791,11 @@ void uwsgi_setup_metrics() {
|
||||
struct uwsgi_metric *vsz = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].vsz_size, 0, NULL);
|
||||
if (i > 0) uwsgi_metric_add_child(total_vsz, vsz);
|
||||
|
||||
// skip core metrics for core 0
|
||||
// skip core metrics for worker 0
|
||||
if (i == 0) continue;
|
||||
|
||||
if (uwsgi.metrics_no_cores) continue;
|
||||
|
||||
int j;
|
||||
for(j=0;j<uwsgi.cores;j++) {
|
||||
uwsgi_metric_name2("worker.%d.core.%d.requests", i, j) ; uwsgi_metric_oid2("3.%d.2.%d.1", i, j);
|
||||
|
||||
+9
-6
@@ -43,7 +43,7 @@ void uwsgi_mule(int id) {
|
||||
#endif
|
||||
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGHUP, end_me);
|
||||
signal(SIGINT, end_me);
|
||||
signal(SIGTERM, end_me);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
@@ -329,11 +329,13 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count + farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
int ret = -1;
|
||||
retry:
|
||||
ret = poll(mulepoll, count + farms_count, timeout);
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_mule_get_msg()/poll()");
|
||||
}
|
||||
else {
|
||||
else if (ret > 0 ) {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
@@ -353,7 +355,7 @@ next:
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
@@ -380,6 +382,7 @@ next:
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
if (uwsgi_is_again()) goto retry;
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] created session %p\n", uor);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -159,6 +162,12 @@ static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsg
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
|
||||
// call the free function asap
|
||||
if (uor->free) {
|
||||
uor->free(uor);
|
||||
}
|
||||
|
||||
// close the socket and the file descriptor
|
||||
if (uor->takeover && uor->s > -1) {
|
||||
close(uor->s);
|
||||
@@ -197,12 +206,41 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
|
||||
uwsgi_buffer_destroy(uor->ubuf);
|
||||
}
|
||||
|
||||
if (uor->ubuf1) {
|
||||
uwsgi_buffer_destroy(uor->ubuf1);
|
||||
}
|
||||
if (uor->ubuf2) {
|
||||
uwsgi_buffer_destroy(uor->ubuf2);
|
||||
}
|
||||
if (uor->ubuf3) {
|
||||
uwsgi_buffer_destroy(uor->ubuf3);
|
||||
}
|
||||
if (uor->ubuf4) {
|
||||
uwsgi_buffer_destroy(uor->ubuf4);
|
||||
}
|
||||
if (uor->ubuf5) {
|
||||
uwsgi_buffer_destroy(uor->ubuf5);
|
||||
}
|
||||
if (uor->ubuf6) {
|
||||
uwsgi_buffer_destroy(uor->ubuf6);
|
||||
}
|
||||
if (uor->ubuf7) {
|
||||
uwsgi_buffer_destroy(uor->ubuf7);
|
||||
}
|
||||
if (uor->ubuf8) {
|
||||
uwsgi_buffer_destroy(uor->ubuf8);
|
||||
}
|
||||
|
||||
if (uor->pipe[0] != -1) {
|
||||
close(uor->pipe[1]);
|
||||
close(uor->pipe[0]);
|
||||
}
|
||||
|
||||
free(uor);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[offload] destroyed session %p\n", uor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
|
||||
@@ -237,6 +275,7 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(uwsgi.offload_threads_events);
|
||||
|
||||
for (;;) {
|
||||
// TODO make timeout tunable
|
||||
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.offload_threads_events);
|
||||
for (i = 0; i < nevents; i++) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
@@ -456,6 +495,13 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
// write event (or just connected)
|
||||
case 1:
|
||||
if (fd == uor->fd) {
|
||||
// maybe we want only a connection...
|
||||
if (uor->ubuf->pos == 0) {
|
||||
uor->status = 2;
|
||||
if (event_queue_add_fd_read(ut->queue, uor->s)) return -1;
|
||||
if (event_queue_fd_write_to_read(ut->queue, uor->fd)) return -1;
|
||||
return 0;
|
||||
}
|
||||
rlen = write(uor->fd, uor->ubuf->buf + uor->written, uor->ubuf->pos-uor->written);
|
||||
if (rlen > 0) {
|
||||
uor->written += rlen;
|
||||
|
||||
+40
-20
@@ -527,6 +527,11 @@ static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!uwsgi_proto_key("HTTP_X_FORWARDED_PROTO", 22)) {
|
||||
wsgi_req->scheme = buf;
|
||||
wsgi_req->scheme_len = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -731,25 +736,40 @@ next:
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi_apps_cnt; i++) {
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
if (orig_path_info_len >= uwsgi_apps[i].mountpoint_len) {
|
||||
if (!uwsgi_startswith(orig_path_info, uwsgi_apps[i].mountpoint, uwsgi_apps[i].mountpoint_len) && uwsgi_apps[i].mountpoint_len > best_found) {
|
||||
best_found = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
char* mountpoint = uwsgi_apps[i].mountpoint;
|
||||
int mountpoint_len = uwsgi_apps[i].mountpoint_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
// Ignore trailing mountpoint slashes
|
||||
if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') {
|
||||
mountpoint_len -= 1;
|
||||
}
|
||||
|
||||
//uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
|
||||
|
||||
// Check if mountpoint could be a possible candidate
|
||||
if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info
|
||||
mountpoint_len <= best_found || // it should be better than the previous found
|
||||
// should have the same prefix of path_info
|
||||
uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) ||
|
||||
// and should not be "misleading"
|
||||
(orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
best_found = mountpoint_len;
|
||||
wsgi_req->script_name = uwsgi_apps[i].mountpoint;
|
||||
wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
|
||||
wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
|
||||
wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
|
||||
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
|
||||
wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1051,7 +1071,7 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
wsgi_req->var_cnt++;
|
||||
ptr += keylen;
|
||||
|
||||
|
||||
|
||||
|
||||
*ptr++ = (uint8_t) (vallen & 0xff);
|
||||
*ptr++ = (uint8_t) ((vallen >> 8) & 0xff);
|
||||
@@ -1118,13 +1138,13 @@ int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *i
|
||||
*ptr ++= '/';
|
||||
}
|
||||
memcpy(ptr, index, index_len);
|
||||
|
||||
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
|
||||
wsgi_req->var_cnt++;
|
||||
|
||||
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
|
||||
wsgi_req->path_info = new_path_info;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+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 ?
|
||||
|
||||
+156
-1
@@ -583,6 +583,39 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route)
|
||||
{
|
||||
|
||||
if (route->data_len < 3)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
uint16_t status_msg_len = 0;
|
||||
const char *status_msg = uwsgi_http_status_msg(route->data, &status_msg_len);
|
||||
|
||||
if (!status_msg)
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
char *buf = uwsgi_concat3n(route->data, route->data_len, " ", 1, (char *) status_msg, status_msg_len);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, buf, route->data_len + 1 + status_msg_len))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10))
|
||||
goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, status_msg_len))
|
||||
goto end;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) status_msg, status_msg_len);
|
||||
|
||||
end:
|
||||
free(buf);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_return(struct uwsgi_route *ur, char *arg)
|
||||
{
|
||||
ur->func = uwsgi_router_return_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// simple math router
|
||||
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -723,6 +756,27 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// force content length
|
||||
static int transform_forcecl(struct wsgi_request *wsgi_req, struct uwsgi_transformation *ut) {
|
||||
char buf[sizeof(UMAX64_STR)+1];
|
||||
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) ut->chunk->pos);
|
||||
if (ret <= 0 || ret >= (int) (sizeof(UMAX64_STR)+1)) {
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
// do not check for errors !!!
|
||||
uwsgi_response_add_header_force(wsgi_req, "Content-Length", 14, buf, ret);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_forcecl_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
uwsgi_add_transformation(wsgi_req, transform_forcecl, NULL);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_forcecl(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_forcecl_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// log route
|
||||
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
@@ -1086,6 +1140,32 @@ static int uwsgi_router_seturi(struct uwsgi_route *ur, char *arg) {
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setremoteaddr route
|
||||
static int uwsgi_router_setremoteaddr_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "REMOTE_ADDR", 11, ub->buf, ub->pos);
|
||||
if (!ptr) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->remote_addr = ptr;
|
||||
wsgi_req->remote_addr_len = ub->pos;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setremoteaddr(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setremoteaddr_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setdocroot route
|
||||
static int uwsgi_router_setdocroot_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -1135,6 +1215,27 @@ static int uwsgi_router_setpathinfo(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fixpathinfo route
|
||||
static int uwsgi_router_fixpathinfo_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
if (wsgi_req->script_name_len == 0)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
|
||||
char *ptr = uwsgi_req_append(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info+wsgi_req->script_name_len, wsgi_req->path_info_len - wsgi_req->script_name_len);
|
||||
if (!ptr) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
wsgi_req->path_info = wsgi_req->path_info+wsgi_req->script_name_len;
|
||||
wsgi_req->path_info_len = wsgi_req->path_info_len - wsgi_req->script_name_len;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_fixpathinfo(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_fixpathinfo_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setscheme route
|
||||
static int uwsgi_router_setscheme_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
@@ -1159,6 +1260,26 @@ static int uwsgi_router_setscheme(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// setmodifiers
|
||||
static int uwsgi_router_setmodifier1_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
wsgi_req->uh->modifier1 = ur->custom;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmodifier1(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmodifier1_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
static int uwsgi_router_setmodifier2_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
wsgi_req->uh->modifier2 = ur->custom;
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_setmodifier2(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_setmodifier2_func;
|
||||
ur->custom = atoi(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// setuser route
|
||||
static int uwsgi_router_setuser_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
@@ -1674,6 +1795,14 @@ 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);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "sor", 3)) {
|
||||
ret = uwsgi_64bit2str(wsgi_req->start_of_request);
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1684,7 +1813,7 @@ static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint
|
||||
char *var_value = uwsgi_get_var(wsgi_req, key, keylen, &var_vallen);
|
||||
if (var_value) {
|
||||
size_t mime_type_len = 0;
|
||||
char *ret = uwsgi_get_mime_type(key, keylen, &mime_type_len);
|
||||
ret = uwsgi_get_mime_type(var_value, var_vallen, &mime_type_len);
|
||||
if (ret) *vallen = mime_type_len;
|
||||
}
|
||||
return ret;
|
||||
@@ -1710,6 +1839,10 @@ static char *uwsgi_route_var_time(struct wsgi_request *wsgi_req, char *key, uint
|
||||
ret = uwsgi_num2str(uwsgi_now());
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "micros", 6)) {
|
||||
ret = uwsgi_64bit2str(uwsgi_micros());
|
||||
*vallen = strlen(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1741,6 +1874,8 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
uwsgi_register_router("last", uwsgi_router_continue);
|
||||
uwsgi_register_router("break", uwsgi_router_break);
|
||||
uwsgi_register_router("return", uwsgi_router_return);
|
||||
uwsgi_register_router("break-with-status", uwsgi_router_return);
|
||||
uwsgi_register_router("log", uwsgi_router_log);
|
||||
uwsgi_register_router("donotlog", uwsgi_router_donotlog);
|
||||
uwsgi_register_router("logvar", uwsgi_router_logvar);
|
||||
@@ -1763,12 +1898,17 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("setscriptname", uwsgi_router_setscriptname);
|
||||
uwsgi_register_router("setmethod", uwsgi_router_setmethod);
|
||||
uwsgi_register_router("seturi", uwsgi_router_seturi);
|
||||
uwsgi_register_router("setremoteaddr", uwsgi_router_setremoteaddr);
|
||||
uwsgi_register_router("setpathinfo", uwsgi_router_setpathinfo);
|
||||
uwsgi_register_router("fixpathinfo", uwsgi_router_fixpathinfo);
|
||||
uwsgi_register_router("setdocroot", uwsgi_router_setdocroot);
|
||||
uwsgi_register_router("setscheme", uwsgi_router_setscheme);
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("setmodifier1", uwsgi_router_setmodifier1);
|
||||
uwsgi_register_router("setmodifier2", uwsgi_router_setmodifier2);
|
||||
|
||||
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
|
||||
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
|
||||
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
|
||||
@@ -1776,6 +1916,7 @@ void uwsgi_register_embedded_routers() {
|
||||
|
||||
uwsgi_register_router("flush", uwsgi_router_flush);
|
||||
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
|
||||
uwsgi_register_router("forcecl", uwsgi_router_forcecl);
|
||||
|
||||
uwsgi_register_router("harakiri", uwsgi_router_harakiri);
|
||||
|
||||
@@ -1956,5 +2097,19 @@ next4:
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.pull_headers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid pull header syntax, must be <header> <var>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
usl->custom = strlen(usl->value);
|
||||
*space = ' ';
|
||||
usl->custom_ptr = space+1;
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("pulling header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+7
-2
@@ -104,8 +104,12 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
if (!uwsgi.rpc_table) {
|
||||
uwsgi_log("local rpc subsystem is still not initialized !!!\n");
|
||||
return NULL;
|
||||
}
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
|
||||
if (*buffer)
|
||||
if (buffer)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
@@ -189,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:
|
||||
|
||||
+70
-13
@@ -229,8 +229,11 @@ int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
|
||||
uwsgi.wait_milliseconds_hook(freq);
|
||||
while(timeout == 0 || waiting == 0 || (timeout > 0 && waiting > 0 && (waiting/1000) < timeout)) {
|
||||
if (uwsgi.wait_milliseconds_hook(freq)) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return -1;
|
||||
}
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
@@ -266,14 +269,35 @@ static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
return sa;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_fd(int fd, uint64_t len, off_t offset) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
|
||||
if (uwsgi.sharedareas[id]->area == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_sharedarea_init_fd()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = fd;
|
||||
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
|
||||
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared((size_t)uwsgi.page_size * (size_t)(pages + 1));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + (size_t) uwsgi.page_size;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = pages;
|
||||
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
|
||||
uwsgi.sharedareas[id]->max_pos = ((size_t)uwsgi.page_size * (size_t)pages) -1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
@@ -286,8 +310,8 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
|
||||
uwsgi.sharedareas[id]->area = area;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->pages = len / (size_t) uwsgi.page_size;
|
||||
if (len % (size_t) uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
@@ -301,23 +325,40 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
char *s_offset = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
"offset", &s_offset,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid sharedarea keyval syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t len = 0;
|
||||
off_t offset = 0;
|
||||
int pages = 0;
|
||||
if (s_size) {
|
||||
len = uwsgi_n64(s_size);
|
||||
pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) pages++;
|
||||
if (strlen(s_size) > 2 && s_size[0] == '0' && s_size[1] == 'x') {
|
||||
len = strtoul(s_size+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
len = uwsgi_n64(s_size);
|
||||
}
|
||||
pages = len / (size_t) uwsgi.page_size;
|
||||
if (len % (size_t) uwsgi.page_size != 0) pages++;
|
||||
}
|
||||
|
||||
if (s_offset) {
|
||||
if (strlen(s_offset) > 2 && s_offset[0] == '0' && s_offset[1] == 'x') {
|
||||
offset = strtoul(s_offset+2, NULL, 16);
|
||||
}
|
||||
else {
|
||||
offset = uwsgi_n64(s_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pages) {
|
||||
@@ -326,27 +367,43 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
|
||||
char *area = NULL;
|
||||
struct uwsgi_sharedarea *sa = NULL;
|
||||
|
||||
int fd = -1;
|
||||
if (s_file) {
|
||||
fd = open(s_file, O_RDWR|O_SYNC);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(s_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (s_fd) {
|
||||
fd = atoi(s_fd);
|
||||
}
|
||||
else if (s_ptr) {
|
||||
}
|
||||
|
||||
if (pages) {
|
||||
if (!area) {
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
if (fd > -1) {
|
||||
sa = uwsgi_sharedarea_init_fd(fd, len, offset);
|
||||
}
|
||||
else if (area) {
|
||||
sa = uwsgi_sharedarea_init_ptr(area, len);
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_ptr(area, len);
|
||||
sa = uwsgi_sharedarea_init(pages);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you need to set a size for a sharedarea !!! [%s]\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (s_pages) free(s_pages);
|
||||
if (s_file) free(s_file);
|
||||
if (s_fd) free(s_fd);
|
||||
if (s_ptr) free(s_ptr);
|
||||
if (s_size) free(s_size);
|
||||
if (s_offset) free(s_offset);
|
||||
|
||||
return sa;
|
||||
}
|
||||
|
||||
@@ -331,6 +331,16 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// send to al lactive workers
|
||||
else if (!strcmp(use->receiver, "active-workers")) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && !uwsgi.workers[i].cheaped && !uwsgi.workers[i].suspended) {
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// route to specific worker
|
||||
else if (!strncmp(use->receiver, "worker", 6)) {
|
||||
i = atoi(use->receiver + 6);
|
||||
|
||||
+42
-9
@@ -189,7 +189,10 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
serverfd = create_server_socket(AF_UNIX, SOCK_STREAM);
|
||||
if (serverfd < 0) return -1;
|
||||
if (serverfd < 0) {
|
||||
free(uws_addr);
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
uwsgi_error("error removing unix socket, unlink()");
|
||||
@@ -563,6 +566,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
ifa = ifap;
|
||||
while (ifa) {
|
||||
memset(new_addr, 0, 16);
|
||||
if (!ifa->ifa_addr) goto next;
|
||||
sin = (struct sockaddr_in *) ifa->ifa_addr;
|
||||
if (inet_ntop(AF_INET, (void *) &sin->sin_addr.s_addr, new_addr, 16)) {
|
||||
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
|
||||
@@ -575,6 +579,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
|
||||
}
|
||||
|
||||
next:
|
||||
ifaf = ifa;
|
||||
ifa = ifaf->ifa_next;
|
||||
|
||||
@@ -1244,10 +1249,20 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
}
|
||||
|
||||
void uwsgi_close_all_sockets() {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->bound)
|
||||
close(uwsgi_sock->fd);
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_close_all_unshared_sockets() {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->bound)
|
||||
if (uwsgi_sock->bound && !uwsgi_sock->shared)
|
||||
close(uwsgi_sock->fd);
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
@@ -1733,13 +1748,6 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
int zero_used = 0;
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1760,6 +1768,24 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_sock->fd = 0;
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
|
||||
if (!uwsgi.is_a_reload) {
|
||||
if (uwsgi.chown_socket) {
|
||||
uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
|
||||
}
|
||||
if (uwsgi.chmod_socket) {
|
||||
if (uwsgi.chmod_socket_value) {
|
||||
if (chmod(uwsgi_sock->name, uwsgi.chmod_socket_value) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("chmod() fd0 socket to 666 for lazy and brave users\n");
|
||||
if (chmod(uwsgi_sock->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
uwsgi_error("inherit fd0: chmod()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
|
||||
@@ -1794,6 +1820,13 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
stdin_done:
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
|
||||
+7
-9
@@ -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);
|
||||
@@ -482,7 +480,7 @@ static void spooler_scandir(struct uwsgi_spooler *uspool, char *dir) {
|
||||
if (!dir)
|
||||
dir = uspool->dir;
|
||||
|
||||
n = scandir(dir, &tasklist, 0, versionsort);
|
||||
n = scandir(dir, &tasklist, NULL, versionsort);
|
||||
if (n < 0) {
|
||||
uwsgi_error("scandir()");
|
||||
return;
|
||||
|
||||
+23
-1
@@ -30,7 +30,18 @@ void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
|
||||
}
|
||||
|
||||
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
|
||||
return 1;
|
||||
if (!ok && uwsgi.ssl_verbose) {
|
||||
char buf[256];
|
||||
X509 *err_cert;
|
||||
int depth;
|
||||
int err;
|
||||
depth = X509_STORE_CTX_get_error_depth(x509_store);
|
||||
err_cert = X509_STORE_CTX_get_current_cert(x509_store);
|
||||
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
|
||||
err = X509_STORE_CTX_get_error(x509_store);
|
||||
uwsgi_log("[uwsgi-ssl] client certificate verify error: num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
|
||||
@@ -210,6 +221,10 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
ssloptions |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
if (!uwsgi.sslv3) {
|
||||
ssloptions |= SSL_OP_NO_SSLv3;
|
||||
}
|
||||
|
||||
// release/reuse buffers as soon as possibile
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
@@ -243,6 +258,7 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
||||
BIO_free(bio);
|
||||
if (dh) {
|
||||
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
|
||||
SSL_CTX_set_tmp_dh(ctx, dh);
|
||||
DH_free(dh);
|
||||
}
|
||||
@@ -252,6 +268,7 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
#ifdef NID_X9_62_prime256v1
|
||||
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if (ecdh) {
|
||||
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
|
||||
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
@@ -394,6 +411,11 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
|
||||
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.ssl_options) {
|
||||
ssloptions |= atoi(usl->value);
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ctx, ssloptions);
|
||||
|
||||
|
||||
|
||||
+14
-13
@@ -459,25 +459,26 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
size_t fsize = st->st_size;
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = wsgi_req->range_to - wsgi_req->range_from;
|
||||
if (fsize > (size_t)st->st_size) {
|
||||
fsize = st->st_size;
|
||||
}
|
||||
// security check
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
wsgi_req->range_to = 0;
|
||||
}
|
||||
else {
|
||||
// reset in case of inconsistent size
|
||||
if (wsgi_req->range_from > fsize) {
|
||||
wsgi_req->range_from = 0;
|
||||
fsize = 0;
|
||||
}
|
||||
else {
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
fsize -= wsgi_req->range_from;
|
||||
}
|
||||
|
||||
if (wsgi_req->range_to) {
|
||||
fsize = (wsgi_req->range_to - wsgi_req->range_from)+1;
|
||||
if (fsize + wsgi_req->range_from > (size_t) (st->st_size)) {
|
||||
fsize = st->st_size - wsgi_req->range_from;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP status
|
||||
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
|
||||
|
||||
+6
-15
@@ -551,25 +551,16 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
uint16_t i;
|
||||
// replace " with '
|
||||
for(i=0;i<kl;i++) {
|
||||
if (k[i] == '"') {
|
||||
k[i] = '\'';
|
||||
}
|
||||
}
|
||||
for(i=0;i<vl;i++) {
|
||||
if (v[i] == '"') {
|
||||
v[i] = '\'';
|
||||
}
|
||||
}
|
||||
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
|
||||
if (uwsgi_stats_str(us, var)) {
|
||||
char *escaped_var = uwsgi_malloc(((kl+vl+1)*2)+1);
|
||||
escape_json(var, strlen(var), escaped_var);
|
||||
free(var);
|
||||
if (uwsgi_stats_str(us, escaped_var)) {
|
||||
us->dirty = 1;
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
return;
|
||||
}
|
||||
free(var);
|
||||
free(escaped_var);
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
us->dirty = 1;
|
||||
}
|
||||
|
||||
@@ -427,6 +427,8 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
|
||||
return NULL;
|
||||
}
|
||||
// eventually the packet could be upgraded to sni...
|
||||
uwsgi_subscription_sni_check(current_slot, usr);
|
||||
#endif
|
||||
// remove death mark and update cores and load
|
||||
node->death_mark = 0;
|
||||
@@ -677,6 +679,10 @@ static struct uwsgi_buffer *uwsgi_subscription_ub(char *key, size_t keysize, uin
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name)))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.subscribe_with_modifier1) {
|
||||
modifier1 = atoi(uwsgi.subscribe_with_modifier1);
|
||||
}
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1))
|
||||
goto end;
|
||||
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2))
|
||||
@@ -1070,6 +1076,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) {
|
||||
|
||||
+124
-9
@@ -699,6 +699,22 @@ void uwsgi_as_root() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_fs) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 0)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_file) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 1)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_dir) {
|
||||
if (uwsgi_wait_for_fs(usl->value, 2)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_mountpoint) {
|
||||
if (uwsgi_wait_for_mountpoint(usl->value)) exit(1);
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_root) {
|
||||
@@ -1019,8 +1035,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
|
||||
@@ -1051,10 +1073,11 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uint64_t end_of_request = uwsgi_micros();
|
||||
wsgi_req->end_of_request = end_of_request;
|
||||
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
if (!wsgi_req->do_not_account_avg_rt) {
|
||||
tmp_rt = wsgi_req->end_of_request - wsgi_req->start_of_request;
|
||||
uwsgi.workers[uwsgi.mywid].running_time += tmp_rt;
|
||||
uwsgi.workers[uwsgi.mywid].avg_response_time = (uwsgi.workers[uwsgi.mywid].avg_response_time + tmp_rt) / 2;
|
||||
}
|
||||
|
||||
// get memory usage
|
||||
if (uwsgi.logging_options.memory_report == 1 || uwsgi.force_get_memusage) {
|
||||
@@ -1165,8 +1188,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;
|
||||
|
||||
@@ -3155,6 +3178,10 @@ void escape_json(char *src, size_t len, char *dst) {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '"';
|
||||
}
|
||||
else if (src[i] == '\\') {
|
||||
*ptr++ = '\\';
|
||||
*ptr++ = '\\';
|
||||
}
|
||||
else {
|
||||
*ptr++ = src[i];
|
||||
}
|
||||
@@ -3388,7 +3415,7 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
|
||||
}
|
||||
|
||||
if (!uwsgi.no_default_app) {
|
||||
if ((mountpoint_len == 0 || (mountpoint_len = -1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
|
||||
if ((mountpoint_len == 0 || (mountpoint_len == 1 && mountpoint[0] == '/')) && uwsgi.default_app == -1) {
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
}
|
||||
@@ -3487,7 +3514,7 @@ int uwsgi_tmpfd() {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
#ifdef O_TMPFILE
|
||||
fd = open(tmpdir, O_TMPFILE | O_RDWR);
|
||||
fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd >= 0) {
|
||||
return fd;
|
||||
}
|
||||
@@ -3752,7 +3779,7 @@ static void *uwsgi_thread_run(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
struct uwsgi_thread *uwsgi_thread_new_with_data(void (*func) (struct uwsgi_thread *), void *data) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_calloc(sizeof(struct uwsgi_thread));
|
||||
|
||||
@@ -3769,6 +3796,7 @@ struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
uwsgi_socket_nb(ut->pipe[1]);
|
||||
|
||||
ut->func = func;
|
||||
ut->data = data;
|
||||
|
||||
pthread_attr_init(&ut->tattr);
|
||||
pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED);
|
||||
@@ -3788,6 +3816,10 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func) (struct uwsgi_thread *)) {
|
||||
return uwsgi_thread_new_with_data(func, NULL);
|
||||
}
|
||||
|
||||
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
|
||||
size_t i;
|
||||
va_list ap;
|
||||
@@ -4414,6 +4446,7 @@ void uwsgi_setns(char *path) {
|
||||
}
|
||||
}
|
||||
free(fds);
|
||||
close(ns_fd);
|
||||
break;
|
||||
}
|
||||
if (fds)
|
||||
@@ -4447,3 +4480,85 @@ mode_t uwsgi_mode_t(char *value, int *error) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_wait_for_mountpoint(char *mountpoint) {
|
||||
if (!uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi.wait_for_fs_timeout = 60;
|
||||
}
|
||||
uwsgi_log("waiting for %s (max %d seconds) ...\n", mountpoint, uwsgi.wait_for_fs_timeout);
|
||||
int counter = 0;
|
||||
for (;;) {
|
||||
if (counter > uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi_log("%s unavailable after %d seconds\n", mountpoint, counter);
|
||||
return -1;
|
||||
}
|
||||
struct stat st0;
|
||||
struct stat st1;
|
||||
if (stat(mountpoint, &st0)) goto retry;
|
||||
if (!S_ISDIR(st0.st_mode)) goto retry;
|
||||
char *relative = uwsgi_concat2(mountpoint, "/../");
|
||||
if (stat(relative, &st1)) {
|
||||
free(relative);
|
||||
goto retry;
|
||||
}
|
||||
free(relative);
|
||||
// useless :P
|
||||
if (!S_ISDIR(st1.st_mode)) goto retry;
|
||||
if (st0.st_dev == st1.st_dev) goto retry;
|
||||
uwsgi_log_verbose("%s mounted\n", mountpoint);
|
||||
return 0;
|
||||
retry:
|
||||
sleep(1);
|
||||
counter++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// type -> 1 file, 2 dir, 0 both
|
||||
int uwsgi_wait_for_fs(char *filename, int type) {
|
||||
if (!uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi.wait_for_fs_timeout = 60;
|
||||
}
|
||||
uwsgi_log("waiting for %s (max %d seconds) ...\n", filename, uwsgi.wait_for_fs_timeout);
|
||||
int counter = 0;
|
||||
for (;;) {
|
||||
if (counter > uwsgi.wait_for_fs_timeout) {
|
||||
uwsgi_log("%s unavailable after %d seconds\n", filename, counter);
|
||||
return -1;
|
||||
}
|
||||
struct stat st;
|
||||
if (stat(filename, &st)) goto retry;
|
||||
if (type == 1 && !S_ISREG(st.st_mode)) goto retry;
|
||||
if (type == 2 && !S_ISDIR(st.st_mode)) goto retry;
|
||||
uwsgi_log_verbose("%s found\n", filename);
|
||||
return 0;
|
||||
retry:
|
||||
sleep(1);
|
||||
counter++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_wait_for_socket(char *socket_name) {
|
||||
if (!uwsgi.wait_for_socket_timeout) {
|
||||
uwsgi.wait_for_socket_timeout = 60;
|
||||
}
|
||||
uwsgi_log("waiting for %s (max %d seconds) ...\n", socket_name, uwsgi.wait_for_socket_timeout);
|
||||
int counter = 0;
|
||||
for (;;) {
|
||||
if (counter > uwsgi.wait_for_socket_timeout) {
|
||||
uwsgi_log("%s unavailable after %d seconds\n", socket_name, counter);
|
||||
return -1;
|
||||
}
|
||||
// wait for 1 second to respect uwsgi.wait_for_fs_timeout
|
||||
int fd = uwsgi_connect(socket_name, 1, 0);
|
||||
if (fd < 0) goto retry;
|
||||
close(fd);
|
||||
uwsgi_log_verbose("%s ready\n", socket_name);
|
||||
return 0;
|
||||
retry:
|
||||
sleep(1);
|
||||
counter++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+163
-27
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI ***
|
||||
|
||||
Copyright (C) 2009-2014 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright (C) 2009-2015 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -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},
|
||||
@@ -101,6 +101,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"declare-option2", required_argument, 0, "declare a new uWSGI custom option (non-immediate)", uwsgi_opt_add_custom_option, NULL, 0},
|
||||
|
||||
{"resolve", required_argument, 0, "place the result of a dns query in the specified placeholder, sytax: placeholder=name (immediate option)", uwsgi_opt_resolve, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
|
||||
{"for-times", required_argument, 0, "(opt logic) for cycle (expand the specified num to a list starting from 1)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_times, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -118,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},
|
||||
@@ -197,6 +202,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-proxy-socket", required_argument, 0, "force the vassal to became an Emperor proxy", uwsgi_opt_set_str, &uwsgi.emperor_proxy, 0},
|
||||
{"emperor-wrapper", required_argument, 0, "set a binary wrapper for vassals", uwsgi_opt_set_str, &uwsgi.emperor_wrapper, 0},
|
||||
{"emperor-wrapper-override", required_argument, 0, "set a binary wrapper for vassals to try before the default one", uwsgi_opt_add_string_list, &uwsgi.emperor_wrapper_override, 0},
|
||||
{"emperor-wrapper-fallback", required_argument, 0, "set a binary wrapper for vassals to try as a last resort", uwsgi_opt_add_string_list, &uwsgi.emperor_wrapper_fallback, 0},
|
||||
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
@@ -219,6 +226,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"emperor-extra-extension", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
{"emperor-no-blacklist", no_argument, 0, "disable Emperor blacklisting subsystem", uwsgi_opt_true, &uwsgi.emperor_no_blacklist, 0},
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
@@ -235,6 +243,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},
|
||||
@@ -243,6 +252,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"mule-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a mule can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.mule_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
@@ -385,6 +395,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
|
||||
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
|
||||
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
|
||||
{"hook-post-fork", required_argument, 0, "run the specified hook after each fork", uwsgi_opt_add_string_list, &uwsgi.hook_post_fork, 0},
|
||||
{"hook-accepting", required_argument, 0, "run the specified hook after each worker enter the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting, 0},
|
||||
{"hook-accepting1", required_argument, 0, "run the specified hook after the first worker enters the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1, 0},
|
||||
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
|
||||
@@ -452,6 +463,15 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"wait-for-fs", required_argument, 0, "wait for the specified filesystem item to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-file", required_argument, 0, "wait for the specified file to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-dir", required_argument, 0, "wait for the specified directory to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_fs, 0},
|
||||
{"wait-for-mountpoint", required_argument, 0, "wait for the specified mountpoint to appear before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_mountpoint, 0},
|
||||
{"wait-for-fs-timeout", required_argument, 0, "set the timeout for wait-for-fs/file/dir", uwsgi_opt_set_int, &uwsgi.wait_for_fs_timeout, 0},
|
||||
|
||||
{"wait-for-socket", required_argument, 0, "wait for the specified socket to be ready before loading apps", uwsgi_opt_add_string_list, &uwsgi.wait_for_socket, 0},
|
||||
{"wait-for-socket-timeout", required_argument, 0, "set the timeout for wait-for-socket", uwsgi_opt_set_int, &uwsgi.wait_for_socket_timeout, 0},
|
||||
|
||||
{"call-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
|
||||
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
|
||||
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
|
||||
@@ -501,6 +521,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"reload-on-rss", required_argument, 0, "reload if rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_rss, UWSGI_OPT_MEMORY},
|
||||
{"evil-reload-on-as", required_argument, 0, "force the master to reload a worker if its address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_as, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
|
||||
{"evil-reload-on-rss", required_argument, 0, "force the master to reload a worker if its rss memory is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.evil_reload_on_rss, UWSGI_OPT_MASTER | UWSGI_OPT_MEMORY},
|
||||
{"mem-collector-freq", required_argument, 0, "set the memory collector frequency when evil reloads are in place", uwsgi_opt_set_int, &uwsgi.mem_collector_freq, 0},
|
||||
|
||||
{"reload-on-fd", required_argument, 0, "reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.reload_on_fd, UWSGI_OPT_MASTER},
|
||||
{"brutal-reload-on-fd", required_argument, 0, "brutal reload if the specified file descriptor is ready", uwsgi_opt_add_string_list, &uwsgi.brutal_reload_on_fd, UWSGI_OPT_MASTER},
|
||||
@@ -560,6 +581,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-no-cores", no_argument, 0, "disable generation of cores-related metrics", uwsgi_opt_true, &uwsgi.metrics_no_cores, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
|
||||
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
|
||||
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
@@ -570,6 +592,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER|UWSGI_OPT_METRICS},
|
||||
{"stats-pusher-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-pushers-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-no-cores", no_argument, 0, "disable generation of cores-related stats", uwsgi_opt_true, &uwsgi.stats_no_cores, UWSGI_OPT_MASTER},
|
||||
{"stats-no-metrics", no_argument, 0, "do not include metrics in stats output", uwsgi_opt_true, &uwsgi.stats_no_metrics, UWSGI_OPT_MASTER},
|
||||
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
|
||||
@@ -614,6 +638,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"subscription-tolerance", required_argument, 0, "set tolerance for subscription servers", uwsgi_opt_set_int, &uwsgi.subscription_tolerance, 0},
|
||||
{"unsubscribe-on-graceful-reload", no_argument, 0, "force unsubscribe request even during graceful reload", uwsgi_opt_true, &uwsgi.unsubscribe_on_graceful_reload, 0},
|
||||
{"start-unsubscribed", no_argument, 0, "configure subscriptions but do not send them (useful with master fifo)", uwsgi_opt_true, &uwsgi.subscriptions_blocked, 0},
|
||||
|
||||
{"subscribe-with-modifier1", required_argument, 0, "force the specififed modifier1 when subscribing", uwsgi_opt_set_str, &uwsgi.subscribe_with_modifier1, UWSGI_OPT_MASTER},
|
||||
|
||||
{"snmp", optional_argument, 0, "enable the embedded snmp server", uwsgi_opt_snmp, NULL, 0},
|
||||
{"snmp-community", required_argument, 0, "set the snmp community string", uwsgi_opt_snmp_community, NULL, 0},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -626,6 +653,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"sni", required_argument, 0, "add an SNI-governed SSL context", uwsgi_opt_sni, NULL, 0},
|
||||
{"sni-dir", required_argument, 0, "check for cert/key/client_ca file in the specified directory and create a sni/ssl context on demand", uwsgi_opt_set_str, &uwsgi.sni_dir, 0},
|
||||
{"sni-dir-ciphers", required_argument, 0, "set ssl ciphers for sni-dir option", uwsgi_opt_set_str, &uwsgi.sni_dir_ciphers, 0},
|
||||
{"ssl-enable3", no_argument, 0, "enable SSLv3 (insecure)", uwsgi_opt_true, &uwsgi.sslv3, 0},
|
||||
{"ssl-option", no_argument, 0, "set a raw ssl option (numeric value)", uwsgi_opt_add_string_list, &uwsgi.ssl_options, 0},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"sni-regexp", required_argument, 0, "add an SNI-governed SSL context (the key is a regexp)", uwsgi_opt_sni, NULL, 0},
|
||||
#endif
|
||||
@@ -672,7 +701,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"use-abort", no_argument, 0, "call abort() on segfault/fpe, could be useful for generating a core dump", uwsgi_opt_true, &uwsgi.use_abort, 0},
|
||||
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-cheap", required_argument, 0, "use main alarm thread rather than create dedicated threads for curl-based alarms", uwsgi_opt_true, &uwsgi.alarm_cheap, 0},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alarm system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER},
|
||||
{"alarm-segfault", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
{"segfault-alarm", required_argument, 0, "raise the specified alarm when the segmentation fault handler is executed", uwsgi_opt_add_string_list, &uwsgi.alarm_segfault, UWSGI_OPT_MASTER},
|
||||
@@ -691,13 +721,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},
|
||||
@@ -838,6 +868,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"collect-header", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
{"response-header-collect", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
|
||||
{"pull-header", required_argument, 0, "store the specified response header in a request var and remove it from the response (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.pull_headers, 0},
|
||||
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
@@ -1148,7 +1180,7 @@ void wait_for_threads() {
|
||||
int sudden_death = 0;
|
||||
|
||||
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
|
||||
for (i = 0; i < uwsgi.threads; i++) {
|
||||
for (i = 1; i < uwsgi.threads; i++) {
|
||||
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
|
||||
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[i].thread_id)) {
|
||||
uwsgi_error("pthread_cancel()\n");
|
||||
@@ -1161,7 +1193,7 @@ void wait_for_threads() {
|
||||
goto end;
|
||||
|
||||
// wait for thread termination
|
||||
for (i = 0; i < uwsgi.threads; i++) {
|
||||
for (i = 1; i < uwsgi.threads; i++) {
|
||||
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, pthread_self())) {
|
||||
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[i].thread_id, NULL);
|
||||
if (ret) {
|
||||
@@ -1170,6 +1202,22 @@ void wait_for_threads() {
|
||||
}
|
||||
}
|
||||
|
||||
// cancel inital thread last since after pthread_cancel() and
|
||||
// pthread_join() is called on it, the whole process will appear to be
|
||||
// a zombie. although it won't eliminate process zombie time, but it
|
||||
// should minimize it.
|
||||
if (!pthread_equal(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, pthread_self())) {
|
||||
if (pthread_cancel(uwsgi.workers[uwsgi.mywid].cores[0].thread_id)) {
|
||||
uwsgi_error("pthread_cancel() on initial thread\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = pthread_join(uwsgi.workers[uwsgi.mywid].cores[0].thread_id, NULL);
|
||||
if (ret) {
|
||||
uwsgi_log("pthread_join() = %d on initial thread\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
|
||||
@@ -1247,6 +1295,11 @@ void kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGINT);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1268,6 +1321,11 @@ void gracefully_kill_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
@@ -1309,6 +1367,12 @@ void grace_them_all(int signum) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
@@ -1355,6 +1419,11 @@ void reap_them_all(int signum) {
|
||||
if (uwsgi.workers[i].pid > 0)
|
||||
uwsgi_curse(i, SIGTERM);
|
||||
}
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
if (uwsgi.mules[i].pid > 0) {
|
||||
uwsgi_curse_mule(i, SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void harakiri() {
|
||||
@@ -1501,8 +1570,10 @@ static void vacuum(void) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.restore_tc) {
|
||||
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
|
||||
uwsgi_error("tcsetattr()");
|
||||
if (getpid() == masterpid) {
|
||||
if (tcsetattr(0, TCSANOW, &uwsgi.termios)) {
|
||||
uwsgi_error("vacuum()/tcsetattr()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1551,25 +1622,40 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void signal_pidfile(int sig, char *filename) {
|
||||
int signal_pidfile(int sig, char *filename) {
|
||||
|
||||
int ret = 0;
|
||||
size_t size = 0;
|
||||
|
||||
char *buffer = uwsgi_open_and_read(filename, &size, 1, NULL);
|
||||
|
||||
if (size > 0) {
|
||||
if (kill((pid_t) atoi(buffer), sig)) {
|
||||
uwsgi_error("kill()");
|
||||
uwsgi_error("signal_pidfile()/kill()");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("error: invalid pidfile\n");
|
||||
ret = -1;
|
||||
}
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/ void uwsgi_command_signal(char *opt) {
|
||||
@@ -2478,6 +2564,11 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
// wait for socket
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_socket) {
|
||||
if (uwsgi_wait_for_socket(usl->value)) exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.logto2) {
|
||||
if (!uwsgi.is_a_reload || uwsgi.log_reopen) {
|
||||
logto(uwsgi.logto2);
|
||||
@@ -2485,6 +2576,7 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
|
||||
if (uwsgi.chdir) {
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.chdir);
|
||||
if (chdir(uwsgi.chdir)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
@@ -3145,6 +3237,24 @@ next2:
|
||||
|
||||
}
|
||||
|
||||
// this lives in a worker thread and periodically scans for memory usage
|
||||
// when evil reloaders are in place
|
||||
void *mem_collector(void *foobar) {
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
uwsgi_log_verbose("mem-collector thread started for worker %d\n", uwsgi.mywid);
|
||||
for(;;) {
|
||||
sleep(uwsgi.mem_collector_freq);
|
||||
uint64_t rss, vsz;
|
||||
get_memusage(&rss, &vsz);
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = rss;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = vsz;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_run() {
|
||||
|
||||
// !!! from now on, we could be in the master or in a worker !!!
|
||||
@@ -3171,6 +3281,11 @@ int uwsgi_run() {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.evil_reload_on_rss || uwsgi.evil_reload_on_as) {
|
||||
pthread_t t;
|
||||
pthread_create(&t, NULL, mem_collector, NULL);
|
||||
}
|
||||
|
||||
|
||||
// eventually maps (or disable) sockets for the worker
|
||||
uwsgi_map_sockets();
|
||||
@@ -3233,6 +3348,8 @@ int uwsgi_run() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_post_fork, "post-fork", 1);
|
||||
|
||||
if (uwsgi.worker_exec2) {
|
||||
char *w_argv[2];
|
||||
w_argv[0] = uwsgi.worker_exec2;
|
||||
@@ -3309,6 +3426,7 @@ void uwsgi_worker_run() {
|
||||
}
|
||||
|
||||
if (uwsgi.chdir2) {
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.chdir2);
|
||||
if (chdir(uwsgi.chdir2)) {
|
||||
uwsgi_error("chdir()");
|
||||
exit(1);
|
||||
@@ -3382,7 +3500,10 @@ void uwsgi_ignition() {
|
||||
if (uwsgi.has_emperor && uwsgi.mywid == 1) {
|
||||
char byte = 5;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor-i-am-ready-to-accept/write()");
|
||||
uwsgi_log_verbose("lost communication with the Emperor, goodbye...\n");
|
||||
gracefully_kill_them_all(0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3663,6 +3784,13 @@ void uwsgi_init_all_apps() {
|
||||
if (uwsgi.need_app) {
|
||||
if (!uwsgi.lazy)
|
||||
uwsgi_log("*** no app loaded. GAME OVER ***\n");
|
||||
if (uwsgi.lazy_apps) {
|
||||
if (uwsgi.master_process) {
|
||||
if (kill(uwsgi.workers[0].pid, SIGINT)) {
|
||||
uwsgi_error("kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
else {
|
||||
@@ -3743,7 +3871,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)
|
||||
@@ -3772,7 +3901,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)
|
||||
@@ -3819,7 +3949,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) {
|
||||
@@ -3837,7 +3968,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) {
|
||||
@@ -4138,15 +4270,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;
|
||||
}
|
||||
@@ -4193,8 +4323,7 @@ void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
|
||||
long *signum_fake_ptr = (long *) sig;
|
||||
int signum = (long) signum_fake_ptr;
|
||||
signal_pidfile(signum, pidfile);
|
||||
exit(0);
|
||||
exit(signal_pidfile(signum, pidfile));
|
||||
}
|
||||
|
||||
void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
@@ -4334,6 +4463,7 @@ int uwsgi_zerg_attach(char *value) {
|
||||
|
||||
if (zerg == NULL) {
|
||||
uwsgi_log("--- invalid data received from zerg-server ---\n");
|
||||
close(zerg_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4629,7 +4759,7 @@ extern char *uwsgi_dot_h;
|
||||
char *uwsgi_get_dot_h() {
|
||||
char *src = uwsgi_dot_h;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *ptr = uwsgi_malloc((len / 2) + 1);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
@@ -4650,6 +4780,9 @@ char *uwsgi_get_dot_h() {
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#else
|
||||
// add final null byte
|
||||
*ptr = '\0';
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
@@ -4662,7 +4795,7 @@ extern char *uwsgi_config_py;
|
||||
char *uwsgi_get_config_py() {
|
||||
char *src = uwsgi_config_py;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *ptr = uwsgi_malloc((len / 2) + 1);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
@@ -4683,6 +4816,9 @@ char *uwsgi_get_config_py() {
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#else
|
||||
// add final null byte
|
||||
*ptr = '\0';
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_re
|
||||
}
|
||||
else {
|
||||
wsgi_req->websocket_need += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
|
||||
wsgi_req->websocket_phase = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
+10
-1
@@ -124,9 +124,18 @@ error:
|
||||
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
|
||||
// collect the header ?
|
||||
// pull/collect the header ?
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.pull_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
wsgi_req->write_errors++ ; return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
|
||||
@@ -271,12 +271,11 @@ static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_airbrake_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_airbrake_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_airbrake_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_airbrake_loop, uacc);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
}
|
||||
|
||||
static void uwsgi_airbrake_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
|
||||
@@ -3,9 +3,18 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_alarm_curl {
|
||||
CURL *curl;
|
||||
struct uwsgi_thread *ut;
|
||||
int pos;
|
||||
int blen;
|
||||
char *body;
|
||||
int hlen;
|
||||
char hdr[];
|
||||
};
|
||||
|
||||
struct uwsgi_alarm_curl_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *url;
|
||||
char *subject;
|
||||
char *to;
|
||||
};
|
||||
@@ -17,7 +26,7 @@ struct uwsgi_alarm_curl_opt {
|
||||
};
|
||||
|
||||
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
#ifdef CURLPROTO_SMTP
|
||||
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->to = arg;
|
||||
struct curl_slist *list = NULL;
|
||||
@@ -29,6 +38,7 @@ static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
curl_easy_setopt(curl, option, list);
|
||||
free(items);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -44,16 +54,33 @@ static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *ar
|
||||
uacc->subject = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
#ifdef CURLOPT_MAIL_RCPT
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
|
||||
static void uwsgi_alarm_curl_url(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
#ifndef CURLPROTO_SMTP
|
||||
if (!uwsgi_strnicmp(arg, 4, "smtp", 4)) {
|
||||
uwsgi_error("Please update libcurl to use SMTP protocol.\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef CURLOPT_MAIL_FROM
|
||||
uacc->url = arg;
|
||||
curl_easy_setopt(curl, option, arg);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_ssl_insecure(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, uwsgi_alarm_curl_url},
|
||||
#ifdef CURLPROTO_SMTP
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to},
|
||||
{"mail_from", CURLOPT_MAIL_FROM, NULL},
|
||||
#endif
|
||||
{"subject", 0, uwsgi_alarm_curl_set_subject},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
|
||||
{"ssl_insecure", 0, uwsgi_alarm_curl_ssl_insecure},
|
||||
{"auth_user", CURLOPT_USERNAME, NULL},
|
||||
{"auth_pass", CURLOPT_PASSWORD, NULL},
|
||||
{"method", CURLOPT_CUSTOMREQUEST, NULL},
|
||||
@@ -65,14 +92,10 @@ static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
|
||||
struct uwsgi_alarm_curl_opt *o = uaco;
|
||||
char *equal = strchr(opt,'=');
|
||||
if (!equal) {
|
||||
if (!uacc->first) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, opt);
|
||||
uacc->first = 1;
|
||||
}
|
||||
if (!equal && !uacc->url) {
|
||||
uwsgi_alarm_curl_url(curl, CURLOPT_URL, opt, uacc);
|
||||
return;
|
||||
}
|
||||
uacc->first = 1;
|
||||
*equal = 0;
|
||||
while(o->name) {
|
||||
if (!strcmp(o->name, opt)) {
|
||||
@@ -82,91 +105,137 @@ static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_cu
|
||||
else {
|
||||
curl_easy_setopt(curl, o->option, equal+1);
|
||||
}
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
struct uwsgi_alarm_curl *uac = userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
struct uwsgi_alarm_curl_config *uacc = ut->data;
|
||||
int remains = full_size;
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr+=4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
if (uac->pos < uac->hlen) {
|
||||
if (remains > uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->hdr + uac->pos, uac->hlen - uac->pos);
|
||||
ptr += uac->hlen - uac->pos;
|
||||
remains -= uac->hlen - uac->pos;
|
||||
uac->pos = uac->hlen;
|
||||
} else {
|
||||
memcpy(ptr, uac->hdr + uac->pos, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr+=9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
}
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
if (remains > uac->blen + uac->hlen - uac->pos) {
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, uac->blen + uac->hlen - uac->pos);
|
||||
remains -= uac->blen + uac->hlen - uac->pos;
|
||||
uac->pos = uac->blen + uac->hlen;
|
||||
return full_size - remains;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
memcpy(ptr, uac->body + uac->pos - uac->hlen, remains);
|
||||
uac->pos += remains;
|
||||
return full_size;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_alloc(struct uwsgi_alarm_curl_config *uacc)
|
||||
{
|
||||
char *addr;
|
||||
struct uwsgi_alarm_curl *uac;
|
||||
size_t required = 0;
|
||||
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 2;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 2;
|
||||
if (required)
|
||||
required += 2; /* newline between MIME header and body */
|
||||
|
||||
uac = uwsgi_malloc(sizeof(*uac) + required);
|
||||
uac->hlen = required;
|
||||
addr = uac->hdr;
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr += 4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr += 9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr++ = '\r';
|
||||
*addr++ = '\n';
|
||||
}
|
||||
|
||||
if (required) {
|
||||
*addr++ = '\r';
|
||||
*addr = '\n';
|
||||
}
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl *uwsgi_alarm_curl_init_curl(struct uwsgi_alarm_instance *uai) {
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
if (!curl) {
|
||||
uwsgi_error("Failed to initialize libcurl.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.socket_timeout);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
struct uwsgi_alarm_curl_config uacc;
|
||||
memset(&uacc, 0, sizeof(uacc));
|
||||
char *opts = uwsgi_str(uai->arg);
|
||||
|
||||
// fill curl options
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
|
||||
uwsgi_alarm_curl_setopt(curl, p, &uacc);
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
if (!uacc.url) {
|
||||
uwsgi_error("An URL is required to trigger curl-based alarm.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_alloc(&uacc);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, uac);
|
||||
free(opts);
|
||||
uac->curl = curl;
|
||||
uai->data_ptr = uac;
|
||||
|
||||
return uac;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_call_curl(struct uwsgi_alarm_curl *uac, char *msg, int len)
|
||||
{
|
||||
uac->pos = 0;
|
||||
uac->body = msg;
|
||||
uac->blen = len;
|
||||
curl_easy_setopt(uac->curl, CURLOPT_INFILESIZE, uac->hlen + uac->blen);
|
||||
CURLcode res = curl_easy_perform(uac->curl);
|
||||
if (res != CURLE_OK)
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
struct uwsgi_alarm_curl *uac = uwsgi_alarm_curl_init_curl(ut->data);
|
||||
uac->ut = ut;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret < 0) return;
|
||||
@@ -174,31 +243,26 @@ static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
ut->pos = 0;
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
uwsgi_alarm_curl_call_curl(uac, ut->buf, rlen);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_init_curl(uai);
|
||||
else
|
||||
uwsgi_thread_new_with_data(uwsgi_alarm_curl_loop, uai);
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
struct uwsgi_alarm_curl *uac = uai->data_ptr;
|
||||
if (uwsgi.alarm_cheap)
|
||||
uwsgi_alarm_curl_call_curl(uac, msg, len);
|
||||
else {
|
||||
struct uwsgi_thread *ut = uac->ut;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_load(void) {
|
||||
|
||||
@@ -4,10 +4,9 @@ void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
|
||||
|
||||
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new_with_data(uwsgi_alarm_xmpp_loop, uai->arg);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
ut->data = uai->arg;
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
/*
|
||||
|
||||
python >= 3.4 asyncio (PEP 3156) loop engine
|
||||
|
||||
EXPERIMENTAL !!!
|
||||
|
||||
Author: Roberto De Ioris
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
static struct uwsgi_asyncio {
|
||||
PyObject *mod;
|
||||
PyObject *loop;
|
||||
PyObject *request;
|
||||
PyObject *hook_fd;
|
||||
PyObject *hook_timeout;
|
||||
PyObject *hook_fix;
|
||||
} uasyncio;
|
||||
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req
|
||||
|
||||
static void uwsgi_opt_setup_asyncio(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi.socket_timeout = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "asyncio";
|
||||
|
||||
}
|
||||
|
||||
static struct uwsgi_option asyncio_options[] = {
|
||||
{"asyncio", required_argument, 0, "a shortcut enabling asyncio loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_asyncio, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
static void gil_asyncio_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
}
|
||||
|
||||
static void gil_asyncio_release() {
|
||||
PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key));
|
||||
}
|
||||
|
||||
static int uwsgi_asyncio_wait_read_hook(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", fd, uasyncio.hook_fd,(long) wsgi_req) == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOl", timeout, uasyncio.hook_timeout, (long)wsgi_req);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", fd) == NULL) PyErr_Print();
|
||||
goto error;
|
||||
}
|
||||
// back to loop
|
||||
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
|
||||
// back from loop
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", fd) == NULL) PyErr_Print();
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
|
||||
Py_DECREF(ob_timeout);
|
||||
|
||||
if (wsgi_req->async_timed_out) return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int uwsgi_asyncio_wait_write_hook(int fd, int timeout) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_writer", "iOl", fd, uasyncio.hook_fd,(long) wsgi_req) == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOl", timeout, uasyncio.hook_timeout, (long)wsgi_req);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_writer", "i", fd) == NULL) PyErr_Print();
|
||||
goto error;
|
||||
}
|
||||
// back to loop
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
// back from loop
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_writer", "i", fd) == NULL) PyErr_Print();
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
|
||||
Py_DECREF(ob_timeout);
|
||||
|
||||
if (wsgi_req->async_timed_out) return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *py_uwsgi_asyncio_request(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
int timed_out = 0;
|
||||
if (!PyArg_ParseTuple(args, "l|i:uwsgi_asyncio_request", &wsgi_req_ptr, &timed_out)) {
|
||||
uwsgi_log_verbose("[BUG] invalid arguments for asyncio callback !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
PyObject *ob_timeout = (PyObject *) wsgi_req->async_timeout;
|
||||
if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
|
||||
Py_DECREF(ob_timeout);
|
||||
// avoid mess when closing the request
|
||||
wsgi_req->async_timeout = NULL;
|
||||
|
||||
if (timed_out > 0) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
int status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status > 0) {
|
||||
ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOli", uwsgi.socket_timeout, uasyncio.request, wsgi_req_ptr, 1);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
// trick for reference counting
|
||||
wsgi_req->async_timeout = (struct uwsgi_rb_timer *) ob_timeout;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) {
|
||||
PyErr_Print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
// we call this two time... overengineering :(
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
|
||||
uwsgi.schedule_to_req();
|
||||
goto again;
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
free_req_queue;
|
||||
again:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *py_uwsgi_asyncio_accept(PyObject *self, PyObject *args) {
|
||||
long uwsgi_sock_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l:uwsgi_asyncio_accept", &uwsgi_sock_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
uwsgi_async_queue_is_full(uwsgi_now());
|
||||
goto end;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) uwsgi_sock_ptr;
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
// in case of errors (or thundering herd, just reset it)
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
free_req_queue;
|
||||
goto end;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.harakiri_options.workers > 0) {
|
||||
set_harakiri(uwsgi.harakiri_options.workers);
|
||||
}
|
||||
|
||||
uwsgi.async_proto_fd_table[wsgi_req->fd] = wsgi_req;
|
||||
|
||||
// add callback for protocol
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", wsgi_req->fd, uasyncio.request, (long) wsgi_req) == NULL) {
|
||||
free_req_queue;
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
// add timeout
|
||||
PyObject *ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOli", uwsgi.socket_timeout, uasyncio.request, (long)wsgi_req, 1);
|
||||
if (!ob_timeout) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
|
||||
free_req_queue;
|
||||
}
|
||||
else {
|
||||
// trick for reference counting
|
||||
wsgi_req->async_timeout = (struct uwsgi_rb_timer *) ob_timeout;
|
||||
}
|
||||
end:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_fd(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l:uwsgi_asyncio_hook_fd", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_timeout(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.wsgi_req->async_timed_out = 1;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_asyncio_hook_fix(PyObject *self, PyObject *args) {
|
||||
long wsgi_req_ptr = 0;
|
||||
if (!PyArg_ParseTuple(args, "l", &wsgi_req_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
|
||||
uwsgi.schedule_to_req();
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef uwsgi_asyncio_accept_def[] = { {"uwsgi_asyncio_accept", py_uwsgi_asyncio_accept, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_request_def[] = { {"uwsgi_asyncio_request", py_uwsgi_asyncio_request, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_fd_def[] = { {"uwsgi_asyncio_hook_fd", py_uwsgi_asyncio_hook_fd, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_timeout_def[] = { {"uwsgi_asyncio_hook_timeout", py_uwsgi_asyncio_hook_timeout, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_asyncio_hook_fix_def[] = { {"uwsgi_asyncio_hook_fix", py_uwsgi_asyncio_hook_fix, METH_VARARGS, ""} };
|
||||
|
||||
static void uwsgi_asyncio_schedule_fix(struct wsgi_request *wsgi_req) {
|
||||
PyObject *cb = PyObject_CallMethod(uasyncio.loop, "call_soon", "Ol", uasyncio.hook_fix, (long) wsgi_req);
|
||||
if (!cb) goto error;
|
||||
Py_DECREF(cb);
|
||||
return;
|
||||
|
||||
error:
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
static void asyncio_loop() {
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running asyncio without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
if (uwsgi.socket_timeout < 30) {
|
||||
uwsgi_log("!!! Running asyncio with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
|
||||
}
|
||||
|
||||
if (!uwsgi.async_waiting_fd_table)
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
if (!uwsgi.async_proto_fd_table)
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
up.gil_get = gil_asyncio_get;
|
||||
up.gil_release = gil_asyncio_release;
|
||||
|
||||
uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uwsgi.schedule_to_main) {
|
||||
uwsgi_log("*** DANGER *** asyncio mode without coroutine/greenthread engine loaded !!!\n");
|
||||
}
|
||||
|
||||
if (!uwsgi.schedule_to_req) {
|
||||
uwsgi.schedule_to_req = async_schedule_to_req_green;
|
||||
}
|
||||
else {
|
||||
uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
|
||||
}
|
||||
|
||||
#ifndef PYTHREE
|
||||
PyObject *asyncio = PyImport_ImportModule("trollius");
|
||||
#else
|
||||
PyObject *asyncio = PyImport_ImportModule("asyncio");
|
||||
#endif
|
||||
if (!asyncio) uwsgi_pyexit;
|
||||
|
||||
uasyncio.mod = asyncio;
|
||||
|
||||
uasyncio.loop = PyObject_CallMethod(asyncio, "get_event_loop", NULL);
|
||||
if (!uasyncio.loop) uwsgi_pyexit;
|
||||
|
||||
// main greenlet waiting for connection (one greenlet per-socket)
|
||||
PyObject *asyncio_accept = PyCFunction_New(uwsgi_asyncio_accept_def, NULL);
|
||||
Py_INCREF(asyncio_accept);
|
||||
|
||||
uasyncio.request = PyCFunction_New(uwsgi_asyncio_request_def, NULL);
|
||||
if (!uasyncio.request) uwsgi_pyexit;
|
||||
|
||||
uasyncio.hook_fd = PyCFunction_New(uwsgi_asyncio_hook_fd_def, NULL);
|
||||
if (!uasyncio.hook_fd) uwsgi_pyexit;
|
||||
uasyncio.hook_timeout = PyCFunction_New(uwsgi_asyncio_hook_timeout_def, NULL);
|
||||
if (!uasyncio.hook_timeout) uwsgi_pyexit;
|
||||
uasyncio.hook_fix = PyCFunction_New(uwsgi_asyncio_hook_fix_def, NULL);
|
||||
if (!uasyncio.hook_fix) uwsgi_pyexit;
|
||||
|
||||
Py_INCREF(uasyncio.request);
|
||||
Py_INCREF(uasyncio.hook_fd);
|
||||
Py_INCREF(uasyncio.hook_timeout);
|
||||
Py_INCREF(uasyncio.hook_fix);
|
||||
|
||||
// call add_handler on each socket
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", uwsgi_sock->fd, asyncio_accept, (long) uwsgi_sock) == NULL) {
|
||||
uwsgi_pyexit;
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (PyObject_CallMethod(uasyncio.loop, "run_forever", NULL) == NULL) {
|
||||
uwsgi_pyexit;
|
||||
}
|
||||
|
||||
// never here ?
|
||||
}
|
||||
|
||||
static void asyncio_init() {
|
||||
uwsgi_register_loop( (char *) "asyncio", asyncio_loop);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin asyncio_plugin = {
|
||||
.name = "asyncio",
|
||||
.options = asyncio_options,
|
||||
.on_load = asyncio_init,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='asyncio'
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['asyncio']
|
||||
+10
-2
@@ -71,7 +71,9 @@ static void carbon_post_init() {
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(usl->value, ":", p, ctx) {
|
||||
// make a copy to not clobber argv
|
||||
char *tmp = uwsgi_str(usl->value);
|
||||
uwsgi_foreach_token(tmp, ":", p, ctx) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
@@ -81,6 +83,7 @@ static void carbon_post_init() {
|
||||
else
|
||||
break;
|
||||
}
|
||||
free(tmp);
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
@@ -196,7 +199,7 @@ static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
|
||||
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
|
||||
u_carbon.was_busy[i] += uwsgi_worker_is_busy(i+1);
|
||||
}
|
||||
|
||||
needs_retry = 0;
|
||||
@@ -380,6 +383,11 @@ metrics_loop:
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
if (!wok) goto clear;
|
||||
um = um->next;
|
||||
}
|
||||
|
||||
@@ -533,9 +533,9 @@ static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
memcpy(full_path, tmp_path, full_path_len+1);
|
||||
|
||||
if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) {
|
||||
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ struct corerouter_peer *uwsgi_cr_peer_add(struct corerouter_session *cs) {
|
||||
if (!bufsize) bufsize = uwsgi.page_size;
|
||||
peers->in = uwsgi_buffer_new(bufsize);
|
||||
// add timeout
|
||||
peers->current_timeout = cs->corerouter->socket_timeout;
|
||||
peers->timeout = cr_add_timeout(cs->corerouter, peers);
|
||||
peers->prev = old_peers;
|
||||
|
||||
@@ -74,6 +75,12 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
|
||||
peer->hook_write = NULL;
|
||||
}
|
||||
|
||||
if (peer->is_buffering) {
|
||||
if (peer->buffering_fd != -1) {
|
||||
close(peer->buffering_fd);
|
||||
}
|
||||
}
|
||||
|
||||
peer->failed = 0;
|
||||
peer->soopt = 0;
|
||||
peer->timed_out = 0;
|
||||
@@ -83,7 +90,13 @@ void uwsgi_cr_peer_reset(struct corerouter_peer *peer) {
|
||||
}
|
||||
|
||||
// destroy a peer
|
||||
void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
int uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
// first of all check if we need to run a flush procedure
|
||||
if (peer->flush && !peer->is_flushing) {
|
||||
peer->is_flushing = 1;
|
||||
// on success, suspend the execution
|
||||
if (peer->flush(peer) >= 0) return -1;
|
||||
}
|
||||
struct corerouter_peer *prev = peer->prev;
|
||||
struct corerouter_peer *next = peer->next;
|
||||
|
||||
@@ -110,6 +123,7 @@ void uwsgi_cr_peer_del(struct corerouter_peer *peer) {
|
||||
uwsgi_buffer_destroy(peer->out);
|
||||
}
|
||||
free(peer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_opt_corerouter(char *opt, char *value, void *cr) {
|
||||
@@ -309,7 +323,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));
|
||||
@@ -383,7 +396,7 @@ void corerouter_close_peer(struct uwsgi_corerouter *ucr, struct corerouter_peer
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_cr_peer_del(peer);
|
||||
if (uwsgi_cr_peer_del(peer) < 0) return;
|
||||
|
||||
if (peer == cs->main_peer) {
|
||||
cs->main_peer = NULL;
|
||||
@@ -401,7 +414,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
|
||||
struct corerouter_peer *main_peer = cr_session->main_peer;
|
||||
if (main_peer) {
|
||||
uwsgi_cr_peer_del(main_peer);
|
||||
if (uwsgi_cr_peer_del(main_peer) < 0) return;
|
||||
}
|
||||
|
||||
// free peers
|
||||
@@ -413,7 +426,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
if (ucr->subscriptions && tmp_peer->un && tmp_peer->un->len) {
|
||||
tmp_peer->un->reference--;
|
||||
}
|
||||
uwsgi_cr_peer_del(tmp_peer);
|
||||
if (uwsgi_cr_peer_del(tmp_peer) < 0) return;
|
||||
}
|
||||
|
||||
// could be used to free additional resources
|
||||
@@ -582,8 +595,8 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
cs->corerouter = ucr;
|
||||
cs->ugs = ugs;
|
||||
|
||||
// set initial timeout
|
||||
peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
// set initial timeout (could be overridden)
|
||||
peer->current_timeout = ucr->socket_timeout;
|
||||
|
||||
ucr->active_sessions++;
|
||||
|
||||
@@ -622,6 +635,10 @@ struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr
|
||||
corerouter_close_session(ucr, cs);
|
||||
cs = NULL;
|
||||
}
|
||||
else {
|
||||
// truly set the timeout
|
||||
peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
}
|
||||
|
||||
return cs;
|
||||
}
|
||||
|
||||
+15
-7
@@ -3,12 +3,12 @@
|
||||
#define COREROUTER_STATUS_RECV_HDR 2
|
||||
#define COREROUTER_STATUS_RESPONSE 3
|
||||
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, uwsgi_now()+u->socket_timeout, x)
|
||||
#define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+u->socket_timeout, x)
|
||||
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, uwsgi_now()+x->current_timeout, x)
|
||||
#define cr_add_timeout_fast(u, x, t) uwsgi_add_rb_timer(u->timeouts, t+x->current_timeout, x)
|
||||
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
|
||||
|
||||
#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, x->session->main_peer ? x->session->main_peer->key_len : 0, x->session->main_peer ? x->session->main_peer->key: "", x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__)
|
||||
#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, x->session->main_peer ? x->session->main_peer->key_len : 0, x->session->main_peer ? x->session->main_peer->key : "", x->session->client_address, x->session->client_port, __VA_ARGS__)
|
||||
#define uwsgi_cr_error(x, y) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s] %s: %s [%s line %d]\n", x->session->corerouter->short_name, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key_len: 0) : x->key_len, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key: "") : x->key, x->session->client_address, x->session->client_port, y, strerror(errno), __FILE__, __LINE__)
|
||||
#define uwsgi_cr_log(x, y, ...) uwsgi_log("[uwsgi-%s key: %.*s client_addr: %s client_port: %s]" y, x->session->corerouter->short_name, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key_len: 0) : x->key_len, (x == x->session->main_peer) ? (x->session->peers ? x->session->peers->key: "") : x->key, x->session->client_address, x->session->client_port, __VA_ARGS__)
|
||||
|
||||
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
|
||||
errno = EINPROGRESS;\
|
||||
@@ -180,14 +180,22 @@ struct corerouter_peer {
|
||||
uint16_t retries;
|
||||
|
||||
// parsed key
|
||||
char *key;
|
||||
uint16_t key_len;
|
||||
char key[0xff];
|
||||
uint8_t key_len;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
struct corerouter_peer *prev;
|
||||
struct corerouter_peer *next;
|
||||
|
||||
int current_timeout;
|
||||
|
||||
ssize_t (*flush)(struct corerouter_peer *);
|
||||
|
||||
int is_flushing;
|
||||
int is_buffering;
|
||||
int buffering_fd;
|
||||
};
|
||||
|
||||
struct uwsgi_corerouter {
|
||||
@@ -269,7 +277,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
|
||||
|
||||
@@ -53,6 +53,7 @@ int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
peer->modifier2 = peer->un->modifier2;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
@@ -88,6 +89,7 @@ split:
|
||||
peer->instance_address = peer->un->name;
|
||||
peer->instance_address_len = peer->un->len;
|
||||
peer->modifier1 = peer->un->modifier1;
|
||||
peer->modifier2 = peer->un->modifier2;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
|
||||
+6
-24
@@ -66,32 +66,14 @@ SV * coroae_coro_new(CV *block) {
|
||||
}
|
||||
|
||||
static int coroae_wait_milliseconds(int timeout) {
|
||||
int ret = -1;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(newSVnv(((double)timeout)/1000.0));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::sleep", G_SCALAR|G_EVAL);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
char buf[256];
|
||||
double d = ((double)timeout)/1000.0;
|
||||
int ret = snprintf(buf, 256, "Coro::AnyEvent::sleep %f", d);
|
||||
if (ret <= 0 || ret > 256) return -1;
|
||||
perl_eval_pv(buf, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
int ret = 0;
|
||||
dSP;
|
||||
|
||||
+17
-26
@@ -2,13 +2,6 @@
|
||||
|
||||
#define AMQP_CONNECTION_HEADER "AMQP\0\0\x09\x01"
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define ntohll(x) x
|
||||
#else
|
||||
#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) )
|
||||
#endif
|
||||
#define htonll(x) ntohll(x)
|
||||
|
||||
#define amqp_send(a, b, c) if (send(a, b, c, 0) < 0) { uwsgi_error("send()"); return -1; }
|
||||
|
||||
struct amqp_frame_header {
|
||||
@@ -69,13 +62,8 @@ static char *amqp_get_long(char *ptr, char *watermark, uint32_t *lv) {
|
||||
|
||||
static char *amqp_get_longlong(char *ptr, char *watermark, uint64_t *llv) {
|
||||
|
||||
uint64_t tmp_longlong;
|
||||
|
||||
if (ptr+8 > watermark) return NULL;
|
||||
|
||||
memcpy(&tmp_longlong, ptr, 8);
|
||||
|
||||
*llv = ntohll(tmp_longlong);
|
||||
*llv = uwsgi_be64(ptr);
|
||||
return ptr+8;
|
||||
}
|
||||
|
||||
@@ -85,26 +73,29 @@ static int amqp_send_ack(int fd, uint64_t delivery_tag) {
|
||||
|
||||
uint32_t size = 4 + 8 + 1;
|
||||
|
||||
size = htonl(size);
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(64);
|
||||
// send type and channel
|
||||
amqp_send(fd, "\1\0\1", 3);
|
||||
if (uwsgi_buffer_append(ub, "\1\0\1", 3)) goto end;
|
||||
// send size
|
||||
amqp_send(fd, &size, 4);
|
||||
|
||||
// send class 60 method 80
|
||||
amqp_send(fd, "\x00\x3C\x00\x50", 4);
|
||||
|
||||
if (uwsgi_buffer_u32be(ub, size)) goto end;
|
||||
// send class 60 method 80
|
||||
if (uwsgi_buffer_append(ub, "\x00\x3C\x00\x50", 4)) goto end;
|
||||
// set delivery_tag
|
||||
delivery_tag = htonll(delivery_tag);
|
||||
amqp_send(fd, &delivery_tag, 8);
|
||||
if (uwsgi_buffer_u64be(ub, delivery_tag)) goto end;
|
||||
if (uwsgi_buffer_append(ub, "\0\xCE", 2)) goto end;
|
||||
|
||||
// empty bits
|
||||
amqp_send(fd, "\0", 1);
|
||||
// send buffer to socket
|
||||
if (write(fd, ub->buf, ub->pos) < 0) {
|
||||
uwsgi_error("amqp_send_ack()/write()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// send frame-end
|
||||
amqp_send(fd, "\xCE", 1);
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
|
||||
@@ -10,6 +10,10 @@ struct uwsgi_emperor_mongodb_state {
|
||||
char *address;
|
||||
char *collection;
|
||||
char *json;
|
||||
char *database;
|
||||
char *username;
|
||||
char *password;
|
||||
char *predigest;
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +33,14 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
// connect
|
||||
c.connect(uems->address);
|
||||
|
||||
if (uems->database && uems->username && uems->password) {
|
||||
std::string err;
|
||||
if (c.auth(uems->database, uems->username, uems->password, err, uems->predigest ? false : true) == false) {
|
||||
uwsgi_log_verbose("[emperor-mongodb] unable to authenticate to db %s: %s\n", uems->database, err.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run the query
|
||||
std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p);
|
||||
while(cursor.get() && cursor->more() ) {
|
||||
@@ -124,3 +136,40 @@ done:
|
||||
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
|
||||
}
|
||||
|
||||
// setup a new mongodb imperial monitor (keyval based)
|
||||
extern "C" void uwsgi_imperial_monitor_mongodb_init2(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
// allocate a new state
|
||||
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
|
||||
size_t arg_len = strlen(ues->arg);
|
||||
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
|
||||
|
||||
// parse args/ set defaults
|
||||
uems->address = (char *) "127.0.0.1:27017";
|
||||
uems->collection = (char *) "uwsgi.emperor.vassals";
|
||||
uems->json = (char *) "";
|
||||
char *args = NULL;
|
||||
if (arg_len <= 11) goto done;
|
||||
args = ues->arg+11;
|
||||
if (uwsgi_kvlist_parse(args, strlen(args), ',', '=',
|
||||
"addr", &uems->address,
|
||||
"address", &uems->address,
|
||||
"server", &uems->address,
|
||||
"collection", &uems->collection,
|
||||
"coll", &uems->collection,
|
||||
"json", &uems->json,
|
||||
"database", &uems->database,
|
||||
"db", &uems->database,
|
||||
"username", &uems->username,
|
||||
"password", &uems->password,
|
||||
"predigest", &uems->predigest,
|
||||
NULL)) {
|
||||
|
||||
uwsgi_log("[emperor-mongodb] invalid keyval syntax !\n");
|
||||
exit(1);
|
||||
}
|
||||
done:
|
||||
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init2(struct uwsgi_emperor_scanner *);
|
||||
|
||||
void emperor_mongodb_init(void) {
|
||||
uwsgi_register_imperial_monitor("mongodb", uwsgi_imperial_monitor_mongodb_init, uwsgi_imperial_monitor_mongodb);
|
||||
uwsgi_register_imperial_monitor("mongodb2", uwsgi_imperial_monitor_mongodb_init2, uwsgi_imperial_monitor_mongodb);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin emperor_mongodb_plugin = {
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
NAME='emperor_zeromq'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['emperor_zeromq']
|
||||
|
||||
+127
-16
@@ -16,6 +16,8 @@ extern struct uwsgi_server uwsgi;
|
||||
struct fastrouter_session {
|
||||
struct corerouter_session session;
|
||||
int has_key;
|
||||
uint64_t content_length;
|
||||
uint64_t buffered;
|
||||
};
|
||||
|
||||
static struct uwsgi_option fastrouter_options[] = {
|
||||
@@ -42,7 +44,7 @@ static struct uwsgi_option fastrouter_options[] = {
|
||||
|
||||
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
|
||||
{"fastrouter-post-buffering", required_argument, 0, "enable fastrouter post buffering", uwsgi_opt_set_64bit, &ufr.cr.post_buffering, 0},
|
||||
{"fastrouter-post-buffering-dir", required_argument, 0, "put fastrouter buffered files to the specified directory", uwsgi_opt_set_str, &ufr.cr.pb_base_dir, 0},
|
||||
{"fastrouter-post-buffering-dir", required_argument, 0, "put fastrouter buffered files to the specified directory (noop, use TMPDIR env)", uwsgi_opt_set_str, &ufr.cr.pb_base_dir, 0},
|
||||
|
||||
{"fastrouter-stats", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
@@ -55,6 +57,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},
|
||||
};
|
||||
|
||||
@@ -65,21 +68,27 @@ static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vall
|
||||
|
||||
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
|
||||
fr->has_key = 1;
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (vallen <= 0xff) {
|
||||
fr->has_key = 1;
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,6 +105,12 @@ static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vall
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ufr.cr.post_buffering > 0) {
|
||||
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
|
||||
fr->content_length = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writing client body to the instance
|
||||
@@ -156,6 +171,23 @@ static ssize_t fr_instance_read(struct corerouter_peer *peer) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t fr_instance_sendfile(struct corerouter_peer *peer) {
|
||||
struct fastrouter_session *fr = (struct fastrouter_session *) peer->session;
|
||||
ssize_t len = uwsgi_sendfile_do(peer->fd, peer->session->main_peer->buffering_fd, fr->buffered, fr->content_length - fr->buffered);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_cr_error(peer, "fr_instance_sendfile()/sendfile()");
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) return 0;
|
||||
fr->buffered += len;
|
||||
if (peer != peer->session->main_peer && peer->un) peer->un->rx+=len;
|
||||
if (fr->buffered >= fr->content_length) {
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// send the uwsgi request header and vars
|
||||
static ssize_t fr_instance_send_request(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_write(peer, "fr_instance_send_request()");
|
||||
@@ -166,9 +198,16 @@ static ssize_t fr_instance_send_request(struct corerouter_peer *peer) {
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the original read buffer
|
||||
peer->out->pos = 0;
|
||||
// start waiting for body
|
||||
peer->session->main_peer->last_hook_read = fr_read_body;
|
||||
cr_reset_hooks(peer);
|
||||
if (!peer->session->main_peer->is_buffering) {
|
||||
// start waiting for body
|
||||
peer->session->main_peer->last_hook_read = fr_read_body;
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
else {
|
||||
peer->hook_write = fr_instance_sendfile;
|
||||
// stop reading from the client
|
||||
peer->session->main_peer->last_hook_read = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -183,8 +222,8 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
peer->can_retry = 0;
|
||||
|
||||
// fix modifiers
|
||||
peer->in->buf[0] = peer->session->main_peer->modifier1;
|
||||
peer->in->buf[3] = peer->session->main_peer->modifier2;
|
||||
peer->in->buf[0] = peer->modifier1;
|
||||
peer->in->buf[3] = peer->modifier2;
|
||||
|
||||
// prepare to write the uwsgi packet
|
||||
peer->out = peer->session->main_peer->in;
|
||||
@@ -196,20 +235,73 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
|
||||
// called after receaving the uwsgi header (read vars)
|
||||
static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
struct fastrouter_session *fr = (struct fastrouter_session *) main_peer->session;
|
||||
|
||||
struct corerouter_peer *new_peer = NULL;
|
||||
ssize_t len = 0;
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf;
|
||||
// better to store it as the original buf address could change
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
|
||||
// are we buffering ?
|
||||
if (main_peer->is_buffering) {
|
||||
// memory or disk ?
|
||||
if (fr->content_length <= ufr.cr.post_buffering) {
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4+fr->content_length))
|
||||
return -1;
|
||||
len = cr_read_exact(main_peer, pktsize+4+fr->content_length, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
// whole body read ?
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4+fr->content_length)) {
|
||||
main_peer->is_buffering = 0;
|
||||
goto done;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
// first round ?
|
||||
if (main_peer->buffering_fd == -1) {
|
||||
main_peer->buffering_fd = uwsgi_tmpfd();
|
||||
if (main_peer->buffering_fd < 0) return -1;
|
||||
}
|
||||
char buf[32768];
|
||||
size_t remains = fr->content_length - fr->buffered;
|
||||
ssize_t rlen = read(main_peer->fd, buf, UMIN(32768, remains));
|
||||
if (rlen < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_cr_error(main_peer, "fr_recv_uwsgi_vars()/read()");
|
||||
return -1;
|
||||
}
|
||||
if (rlen == 0) return 0;
|
||||
fr->buffered += rlen;
|
||||
if (write(main_peer->buffering_fd, buf, rlen) != rlen) {
|
||||
uwsgi_cr_error(main_peer, "fr_recv_uwsgi_vars()/write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// have we done ?
|
||||
if (fr->buffered >= fr->content_length) {
|
||||
fr->buffered = 0;
|
||||
len = rlen;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4))
|
||||
return -1;
|
||||
ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
|
||||
// headers received, ready to choose the instance
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = main_peer->session->corerouter;
|
||||
|
||||
struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer->last_hook_read = fr_instance_read;
|
||||
|
||||
// find the hostname
|
||||
@@ -226,8 +318,27 @@ 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;
|
||||
}
|
||||
|
||||
// buffering ?
|
||||
if (ufr.cr.post_buffering > 0 && fr->content_length > 0) {
|
||||
main_peer->is_buffering = 1;
|
||||
main_peer->buffering_fd = -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!new_peer) {
|
||||
new_peer = main_peer->session->peers;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
|
||||
|
||||
@@ -100,6 +100,31 @@ retry:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_int(PyObject *self, PyObject *args) {
|
||||
|
||||
uwsgi_log("Brutally killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
|
||||
uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL);
|
||||
PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL);
|
||||
|
||||
uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
int i,count = uwsgi_count_sockets(uwsgi.sockets);
|
||||
for(i=0;i<count;i++) {
|
||||
PyObject_CallMethod(ugevent.watchers[i], "stop", NULL);
|
||||
}
|
||||
uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_gevent_gbcw() {
|
||||
|
||||
// already running
|
||||
@@ -333,6 +358,7 @@ PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_geven
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_int_handler_def[] = { {"uwsgi_gevent_unix_signal_int_handler", py_uwsgi_gevent_int, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_ctrl_gl_def[] = { {"uwsgi_gevent_ctrl_gl_handler", py_uwsgi_gevent_ctrl_gl, METH_VARARGS, ""} };
|
||||
|
||||
static void gil_gevent_get() {
|
||||
@@ -345,6 +371,9 @@ static void gil_gevent_release() {
|
||||
|
||||
static void gevent_loop() {
|
||||
|
||||
// ensure SIGPIPE is ignored
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
@@ -485,6 +514,22 @@ static void gevent_loop() {
|
||||
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
// map SIGINT/SIGTERM with gevent.signal
|
||||
ge_signal_tuple = PyTuple_New(2);
|
||||
PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGINT));
|
||||
PyObject *uwsgi_gevent_unix_signal_int_handler = PyCFunction_New(uwsgi_gevent_unix_signal_int_handler_def, NULL);
|
||||
Py_INCREF(uwsgi_gevent_unix_signal_int_handler);
|
||||
PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
ge_signal_tuple = PyTuple_New(2);
|
||||
PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGTERM));
|
||||
PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
|
||||
|
||||
|
||||
PyObject *wait_for_me = ugevent.hub;
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
#define is_not_python(x) strcmp(uwsgi.p[x]->name, "python")
|
||||
|
||||
struct ugreenlet {
|
||||
int enabled;
|
||||
PyObject *callable;
|
||||
@@ -69,7 +71,7 @@ static void greenlet_schedule_to_req() {
|
||||
}
|
||||
|
||||
// call it in the main core
|
||||
if (uwsgi.p[modifier1]->suspend) {
|
||||
if (is_not_python(modifier1) && uwsgi.p[modifier1]->suspend) {
|
||||
uwsgi.p[modifier1]->suspend(NULL);
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ static void greenlet_schedule_to_req() {
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (uwsgi.p[modifier1]->resume) {
|
||||
if (is_not_python(modifier1) && uwsgi.p[modifier1]->resume) {
|
||||
uwsgi.p[modifier1]->resume(NULL);
|
||||
}
|
||||
|
||||
@@ -93,7 +95,7 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
// ensure gil
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
if (is_not_python(wsgi_req->uh->modifier1) && uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
|
||||
}
|
||||
PyObject *ret = PyGreenlet_Switch(ugl.main, NULL, NULL);
|
||||
@@ -103,7 +105,7 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
exit(1);
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
if (is_not_python(wsgi_req->uh->modifier1) && uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
|
||||
}
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
@@ -42,6 +42,12 @@ struct uwsgi_http {
|
||||
|
||||
int server_name_as_http_host;
|
||||
|
||||
int headers_timeout;
|
||||
int connect_timeout;
|
||||
int manage_source;
|
||||
int enable_proxy_protocol;
|
||||
int chunked_input;
|
||||
int manage_rtsp;
|
||||
};
|
||||
|
||||
struct http_session {
|
||||
@@ -130,6 +136,8 @@ struct http_session {
|
||||
|
||||
ssize_t (*func_write)(struct corerouter_peer *);
|
||||
|
||||
int is_rtsp;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -154,7 +162,7 @@ void hr_session_ssl_close(struct corerouter_session *);
|
||||
ssize_t hr_ssl_read(struct corerouter_peer *);
|
||||
ssize_t hr_ssl_write(struct corerouter_peer *);
|
||||
|
||||
int hr_https_add_vars(struct http_session *, struct uwsgi_buffer *);
|
||||
int hr_https_add_vars(struct http_session *, struct corerouter_peer *, struct uwsgi_buffer *);
|
||||
void hr_setup_ssl(struct http_session *, struct uwsgi_gateway_socket *);
|
||||
|
||||
#endif
|
||||
|
||||
+215
-58
@@ -42,6 +42,8 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-raw-body", no_argument, 0, "blindly send HTTP body to backends (required for WebSockets and Icecast support in backends)", uwsgi_opt_true, &uhttp.raw_body, 0},
|
||||
{"http-websockets", no_argument, 0, "automatically detect websockets connections and put the session in raw mode", uwsgi_opt_true, &uhttp.websockets, 0},
|
||||
|
||||
{"http-chunked-input", no_argument, 0, "automatically detect chunked input requests and put the session in raw mode", uwsgi_opt_true, &uhttp.chunked_input, 0},
|
||||
|
||||
{"http-use-code-string", required_argument, 0, "use code string as hostname->server mapper for the http router", uwsgi_opt_corerouter_cs, &uhttp, 0},
|
||||
{"http-use-socket", optional_argument, 0, "forward request to the specified uwsgi socket", uwsgi_opt_corerouter_use_socket, &uhttp, 0},
|
||||
{"http-gracetime", required_argument, 0, "retry connections to dead static nodes after the specified amount of seconds", uwsgi_opt_set_int, &uhttp.cr.static_node_gracetime, 0},
|
||||
@@ -60,43 +62,60 @@ struct uwsgi_option http_options[] = {
|
||||
{"http-buffer-size", required_argument, 0, "set internal buffer size (default: page size)", uwsgi_opt_set_64bit, &uhttp.cr.buffer_size, 0},
|
||||
|
||||
{"http-server-name-as-http-host", required_argument, 0, "force SERVER_NAME to HTTP_HOST", uwsgi_opt_true, &uhttp.server_name_as_http_host, 0},
|
||||
{"http-headers-timeout", required_argument, 0, "set internal http socket timeout for headers", uwsgi_opt_set_int, &uhttp.headers_timeout, 0},
|
||||
{"http-connect-timeout", required_argument, 0, "set internal http socket timeout for backend connections", uwsgi_opt_set_int, &uhttp.connect_timeout, 0},
|
||||
|
||||
{"http-manage-source", no_argument, 0, "manage the SOURCE HTTP method placing the session in raw mode", uwsgi_opt_true, &uhttp.manage_source, 0},
|
||||
{"http-manage-rtsp", no_argument, 0, "manage RTSP sessions", uwsgi_opt_true, &uhttp.manage_rtsp, 0},
|
||||
{"http-enable-proxy-protocol", optional_argument, 0, "manage PROXY protocol requests", uwsgi_opt_true, &uhttp.enable_proxy_protocol, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen) {
|
||||
static void http_set_timeout(struct corerouter_peer *peer, int timeout) {
|
||||
if (peer->current_timeout == timeout) return;
|
||||
peer->current_timeout = timeout;
|
||||
peer->timeout = corerouter_reset_timeout(peer->session->corerouter, peer);
|
||||
}
|
||||
|
||||
static char * http_header_to_cgi(char *hh, size_t hhlen, size_t *keylen, size_t *vallen, int *has_prefix) {
|
||||
size_t i;
|
||||
char *val = hh;
|
||||
int status = 0;
|
||||
for (i = 0; i < hhlen; i++) {
|
||||
if (!status) {
|
||||
hh[i] = toupper((int) hh[i]);
|
||||
if (hh[i] == '-')
|
||||
hh[i] = '_';
|
||||
if (hh[i] == ':') {
|
||||
status = 1;
|
||||
*keylen = i;
|
||||
}
|
||||
}
|
||||
else if (status == 1 && hh[i] != ' ') {
|
||||
status = 2;
|
||||
val += i;
|
||||
*vallen+=1;
|
||||
}
|
||||
else if (status == 2) {
|
||||
*vallen+=1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(*keylen))
|
||||
return NULL;
|
||||
|
||||
if (uwsgi_strncmp("CONTENT_LENGTH", 14, hh, *keylen) && uwsgi_strncmp("CONTENT_TYPE", 12, hh, *keylen)) {
|
||||
*has_prefix = 0x02;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, size_t keylen, char *val, size_t vallen, int prefix) {
|
||||
|
||||
struct uwsgi_buffer *out = peer->out;
|
||||
struct http_session *hr = (struct http_session *) peer->session;
|
||||
|
||||
int i;
|
||||
int status = 0;
|
||||
char *val = hh;
|
||||
uint16_t keylen = 0, vallen = 0;
|
||||
int prefix = 0;
|
||||
|
||||
for (i = 0; i < hhlen; i++) {
|
||||
if (!status) {
|
||||
hh[i] = toupper((int) hh[i]);
|
||||
if (hh[i] == '-')
|
||||
hh[i] = '_';
|
||||
if (hh[i] == ':') {
|
||||
status = 1;
|
||||
keylen = i;
|
||||
}
|
||||
}
|
||||
else if (status == 1 && hh[i] != ' ') {
|
||||
status = 2;
|
||||
val += i;
|
||||
vallen++;
|
||||
}
|
||||
else if (status == 2) {
|
||||
vallen++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!keylen)
|
||||
return -1;
|
||||
|
||||
if (hr->websockets) {
|
||||
if (!uwsgi_strncmp("UPGRADE", 7, hh, keylen)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "websocket", 9)) {
|
||||
@@ -122,9 +141,14 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HOST", 4, hh, keylen)) {
|
||||
peer->key = val;
|
||||
peer->key_len = vallen;
|
||||
if (uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, peer->key, peer->key_len)) return -1;
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
if (uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, peer->key, peer->key_len)) return -1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
@@ -134,13 +158,24 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
// in the future we could support chunked requests...
|
||||
else if (!uwsgi_strncmp("TRANSFER_ENCODING", 17, hh, keylen)) {
|
||||
hr->session.can_keepalive = 0;
|
||||
if (uhttp.chunked_input) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "chunked", 7)) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("CONNECTION", 10, hh, keylen)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "close", 5)) {
|
||||
if (!uwsgi_strnicmp(val, vallen, "close", 5) || !uwsgi_strnicmp(val, vallen, "upgrade", 7)) {
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
}
|
||||
else if (peer->key == uwsgi.hostname && hr->raw_body && !uwsgi_strncmp("ICE_URL", 7, hh, keylen)) {
|
||||
if (vallen <= 0xff) {
|
||||
memcpy(peer->key, val, vallen);
|
||||
peer->key_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
else if (uhttp.auto_gzip && !uwsgi_strncmp("ACCEPT_ENCODING", 15, hh, keylen)) {
|
||||
@@ -151,11 +186,7 @@ int http_add_uwsgi_header(struct corerouter_peer *peer, char *hh, uint16_t hhlen
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
||||
if (uwsgi_strncmp("CONTENT_TYPE", 12, hh, keylen) && uwsgi_strncmp("CONTENT_LENGTH", 14, hh, keylen)) {
|
||||
keylen += 5;
|
||||
prefix = 1;
|
||||
}
|
||||
if (prefix) keylen += 5;
|
||||
|
||||
if (uwsgi_buffer_u16le(out, keylen)) return -1;
|
||||
|
||||
@@ -163,7 +194,7 @@ done:
|
||||
if (uwsgi_buffer_append(out, "HTTP_", 5)) return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_append(out, hh, keylen - (prefix * 5))) return -1;
|
||||
if (uwsgi_buffer_append(out, hh, keylen - (prefix ? 5 : 0))) return -1;
|
||||
|
||||
if (uwsgi_buffer_u16le(out, vallen)) return -1;
|
||||
if (uwsgi_buffer_append(out, val, vallen)) return -1;
|
||||
@@ -180,6 +211,14 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
char *watermark = ptr + hr->headers_size;
|
||||
char *base = ptr;
|
||||
char *query_string = NULL;
|
||||
char *proxy_src = NULL;
|
||||
char *proxy_dst = NULL;
|
||||
char *proxy_src_port = NULL;
|
||||
char *proxy_dst_port = NULL;
|
||||
uint16_t proxy_src_len = 0;
|
||||
uint16_t proxy_dst_len = 0;
|
||||
uint16_t proxy_src_port_len = 0;
|
||||
uint16_t proxy_dst_port_len = 0;
|
||||
|
||||
peer->out = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// force this buffer to be destroyed as soon as possibile
|
||||
@@ -192,10 +231,19 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
struct uwsgi_buffer *out = peer->out;
|
||||
int found = 0;
|
||||
|
||||
if (uwsgi.enable_proxy_protocol || uhttp.enable_proxy_protocol) {
|
||||
ptr = proxy1_parse(ptr, watermark, &proxy_src, &proxy_src_len, &proxy_dst, &proxy_dst_len, &proxy_src_port, &proxy_src_port_len, &proxy_dst_port, &proxy_dst_port_len);
|
||||
base = ptr;
|
||||
}
|
||||
|
||||
// REQUEST_METHOD
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == ' ') {
|
||||
if (uwsgi_buffer_append_keyval(out, "REQUEST_METHOD", 14, base, ptr - base)) return -1;
|
||||
// on SOURCE METHOD, force raw body
|
||||
if (uhttp.manage_source && !uwsgi_strncmp(base, ptr - base, "SOURCE", 6)) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
ptr++;
|
||||
found = 1;
|
||||
break;
|
||||
@@ -283,6 +331,10 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
if (uhttp.keepalive && !uwsgi_strncmp("HTTP/1.1", 8, base, ptr-base)) {
|
||||
hr->session.can_keepalive = 1;
|
||||
}
|
||||
if (uhttp.manage_rtsp && !uwsgi_strncmp("RTSP/1.0", 8, base, ptr-base)) {
|
||||
hr->raw_body = 1;
|
||||
hr->is_rtsp = 1;
|
||||
}
|
||||
ptr += 2;
|
||||
found = 1;
|
||||
break;
|
||||
@@ -300,7 +352,7 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
|
||||
// SERVER_NAME
|
||||
if (!uhttp.server_name_as_http_host && uwsgi_buffer_append_keyval(out, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len)) return -1;
|
||||
peer->key = uwsgi.hostname;
|
||||
memcpy(peer->key, uwsgi.hostname, uwsgi.hostname_len);
|
||||
peer->key_len = uwsgi.hostname_len;
|
||||
|
||||
// SERVER_PORT
|
||||
@@ -315,16 +367,27 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
if (hr_https_add_vars(hr, out)) return -1;
|
||||
if (hr_https_add_vars(hr, peer, out)) return -1;
|
||||
#endif
|
||||
|
||||
// REMOTE_ADDR
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, peer->session->client_address, strlen(peer->session->client_address))) return -1;
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, peer->session->client_port, strlen(peer->session->client_port))) return -1;
|
||||
if (proxy_src) {
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, proxy_src, proxy_src_len)) return -1;
|
||||
if (proxy_src_port) {
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, proxy_src_port, proxy_src_port_len)) return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_ADDR", 11, peer->session->client_address, strlen(peer->session->client_address))) return -1;
|
||||
if (uwsgi_buffer_append_keyval(out, "REMOTE_PORT", 11, peer->session->client_port, strlen(peer->session->client_port))) return -1;
|
||||
}
|
||||
|
||||
//HEADERS
|
||||
base = ptr;
|
||||
|
||||
struct uwsgi_string_list *headers = NULL, *usl = NULL;
|
||||
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == '\r') {
|
||||
if (ptr + 1 >= watermark)
|
||||
@@ -345,13 +408,53 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
hr->send_expect_100 = 1;
|
||||
}
|
||||
}
|
||||
if (http_add_uwsgi_header(peer, base, ptr - base)) return -1;
|
||||
|
||||
size_t key_len = 0, value_len = 0;
|
||||
int has_prefix = 0;
|
||||
// last line, do not waste time
|
||||
if (ptr - base == 0) break;
|
||||
char *value = http_header_to_cgi(base, ptr - base, &key_len, &value_len, &has_prefix);
|
||||
if (!value) goto clear;
|
||||
usl = uwsgi_string_list_has_item(headers, base, key_len);
|
||||
// there is already a HTTP header with the same name, let's merge them
|
||||
if (usl) {
|
||||
char *old_value = usl->custom_ptr;
|
||||
usl->custom_ptr = uwsgi_concat3n(old_value, (size_t) usl->custom, ", ", 2, value, value_len);
|
||||
usl->custom += 2 + value_len;
|
||||
if (usl->custom2 & 0x01) free(old_value);
|
||||
usl->custom2 |= 0x01;
|
||||
}
|
||||
else {
|
||||
// add an entry
|
||||
usl = uwsgi_string_new_list(&headers, NULL);
|
||||
usl->value = base;
|
||||
usl->len = key_len;
|
||||
usl->custom_ptr = value;
|
||||
usl->custom = value_len;
|
||||
usl->custom2 = has_prefix;
|
||||
}
|
||||
ptr++;
|
||||
base = ptr + 1;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
usl = headers;
|
||||
int broken = 0;
|
||||
while(usl) {
|
||||
if (!broken) {
|
||||
if (http_add_uwsgi_header(peer, usl->value, usl->len, usl->custom_ptr, (size_t) usl->custom, usl->custom2 & 0x02)) broken = 1;
|
||||
}
|
||||
if (usl->custom2 & 0x01) {
|
||||
free(usl->custom_ptr);
|
||||
}
|
||||
struct uwsgi_string_list *tmp_usl = usl;
|
||||
usl = usl->next;
|
||||
free(tmp_usl);
|
||||
}
|
||||
|
||||
if (broken) return -1;
|
||||
|
||||
struct uwsgi_string_list *hv = uhttp.http_vars;
|
||||
while (hv) {
|
||||
char *equal = strchr(hv->value, '=');
|
||||
@@ -361,8 +464,33 @@ int http_headers_parse(struct corerouter_peer *peer) {
|
||||
hv = hv->next;
|
||||
}
|
||||
|
||||
if (hr->is_rtsp) {
|
||||
if (uwsgi_starts_with("rtsp://", 7, hr->path_info, hr->path_info_len)) {
|
||||
char *slash = memchr(hr->path_info + 7, '/', hr->path_info_len - 7);
|
||||
if (!slash) return -1;
|
||||
if (slash - (hr->path_info + 7) <= 0xff) {
|
||||
peer->key_len = slash - (hr->path_info + 7);
|
||||
memcpy(peer->key, hr->path_info + 7, peer->key_len);
|
||||
// override PATH_INFO
|
||||
if (uwsgi_buffer_append_keyval(out, "PATH_INFO", 9, slash, hr->path_info_len - (7 + peer->key_len))) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
clear:
|
||||
usl = headers;
|
||||
while(usl) {
|
||||
if (usl->custom2 & 0x01) {
|
||||
free(usl->custom_ptr);
|
||||
}
|
||||
struct uwsgi_string_list *tmp_usl = usl;
|
||||
usl = usl->next;
|
||||
free(tmp_usl);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -446,6 +574,7 @@ ssize_t hr_write(struct corerouter_peer *main_peer) {
|
||||
return 0;
|
||||
}
|
||||
if (main_peer->session->connect_peer_after_write) {
|
||||
http_set_timeout(main_peer->session->connect_peer_after_write, uhttp.connect_timeout);
|
||||
cr_connect(main_peer->session->connect_peer_after_write, hr_instance_connected);
|
||||
main_peer->session->connect_peer_after_write = NULL;
|
||||
return len;
|
||||
@@ -459,6 +588,9 @@ ssize_t hr_write(struct corerouter_peer *main_peer) {
|
||||
ssize_t hr_instance_connected(struct corerouter_peer* peer) {
|
||||
|
||||
cr_peer_connected(peer, "hr_instance_connected()");
|
||||
|
||||
// set the default timeout
|
||||
http_set_timeout(peer, uhttp.cr.socket_timeout);
|
||||
|
||||
// we are connected, we cannot retry anymore
|
||||
peer->can_retry = 0;
|
||||
@@ -523,10 +655,7 @@ ssize_t hr_instance_read(struct corerouter_peer *peer) {
|
||||
hr->has_gzip = 0;
|
||||
#endif
|
||||
if (uhttp.keepalive > 1) {
|
||||
int orig_timeout = peer->session->corerouter->socket_timeout;
|
||||
peer->session->corerouter->socket_timeout = uhttp.keepalive;
|
||||
peer->session->main_peer->timeout = corerouter_reset_timeout(peer->session->corerouter, peer->session->main_peer);
|
||||
peer->session->corerouter->socket_timeout = orig_timeout;
|
||||
http_set_timeout(peer->session->main_peer, uhttp.keepalive);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_ZLIB
|
||||
@@ -655,6 +784,9 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ensure the headers timeout is honoured
|
||||
http_set_timeout(main_peer, uhttp.headers_timeout);
|
||||
|
||||
// read until \r\n\r\n is found
|
||||
size_t j;
|
||||
size_t len = main_peer->in->pos;
|
||||
@@ -708,10 +840,16 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (new_peer->instance_address_len == 0)
|
||||
return -1;
|
||||
|
||||
// fix modifiers
|
||||
if (uhttp.modifier1)
|
||||
new_peer->modifier1 = uhttp.modifier1;
|
||||
if (uhttp.modifier2)
|
||||
new_peer->modifier2 = uhttp.modifier2;
|
||||
|
||||
uint16_t pktsize = new_peer->out->pos-4;
|
||||
// fix modifiers
|
||||
new_peer->out->buf[0] = new_peer->session->main_peer->modifier1;
|
||||
new_peer->out->buf[3] = new_peer->session->main_peer->modifier2;
|
||||
new_peer->out->buf[0] = new_peer->modifier1;
|
||||
new_peer->out->buf[3] = new_peer->modifier2;
|
||||
// fix pktsize
|
||||
new_peer->out->buf[1] = (uint8_t) (pktsize & 0xff);
|
||||
new_peer->out->buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
@@ -729,6 +867,19 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
if (uwsgi_buffer_append(new_peer->out, main_peer->in->buf + hr->headers_size + 1, hr->remains)) return -1;
|
||||
}
|
||||
|
||||
if (new_peer->modifier1 == 123) {
|
||||
// reset modifier1 to 0
|
||||
new_peer->out->buf[0] = 0;
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
// on raw body, ensure keepalive is disabled
|
||||
if (hr->raw_body) hr->session.can_keepalive = 0;
|
||||
|
||||
if (hr->session.can_keepalive && hr->content_length == 0) {
|
||||
main_peer->disabled = 1;
|
||||
// stop reading from the client
|
||||
@@ -740,10 +891,12 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (hr->websockets > 2 && hr->websocket_key_len > 0) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
|
||||
new_peer->can_retry = 1;
|
||||
// reset main timeout
|
||||
http_set_timeout(main_peer, uhttp.cr.socket_timeout);
|
||||
// set peer timeout
|
||||
http_set_timeout(new_peer, uhttp.connect_timeout);
|
||||
cr_connect(new_peer, hr_instance_connected);
|
||||
break;
|
||||
}
|
||||
@@ -830,21 +983,26 @@ static int hr_retry(struct corerouter_peer *peer) {
|
||||
|
||||
retry:
|
||||
// start async connect (again)
|
||||
http_set_timeout(peer, uhttp.connect_timeout);
|
||||
cr_connect(peer, hr_instance_connected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
|
||||
if (!uhttp.headers_timeout) uhttp.headers_timeout = uhttp.cr.socket_timeout;
|
||||
if (!uhttp.connect_timeout) uhttp.connect_timeout = uhttp.cr.socket_timeout;
|
||||
|
||||
// set the retry hook
|
||||
cs->retry = hr_retry;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
// set the modifier1
|
||||
cs->main_peer->modifier1 = uhttp.modifier1;
|
||||
cs->main_peer->modifier2 = uhttp.modifier2;
|
||||
// default hook
|
||||
cs->main_peer->last_hook_read = hr_read;
|
||||
|
||||
// headers timeout
|
||||
cs->main_peer->current_timeout = uhttp.headers_timeout;
|
||||
|
||||
if (uhttp.raw_body) {
|
||||
hr->raw_body = 1;
|
||||
}
|
||||
@@ -906,7 +1064,6 @@ int http_init() {
|
||||
uhttp.cr.socket_num = 0;
|
||||
}
|
||||
uwsgi_corerouter_init((struct uwsgi_corerouter *) &uhttp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+68
-4
@@ -10,6 +10,14 @@
|
||||
|
||||
extern struct uwsgi_http uhttp;
|
||||
|
||||
// taken from nginx
|
||||
static void hr_ssl_clear_errors() {
|
||||
while (ERR_peek_error()) {
|
||||
(void) ERR_get_error();
|
||||
}
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
||||
void uwsgi_opt_https(char *opt, char *value, void *cr) {
|
||||
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
|
||||
char *client_ca = NULL;
|
||||
@@ -166,10 +174,17 @@ void uwsgi_opt_http_to_https(char *opt, char *value, void *cr) {
|
||||
ucr->has_sockets++;
|
||||
}
|
||||
|
||||
int hr_https_add_vars(struct http_session *hr, struct uwsgi_buffer *out) {
|
||||
int hr_https_add_vars(struct http_session *hr, struct corerouter_peer *peer, struct uwsgi_buffer *out) {
|
||||
// HTTPS (adapted from nginx)
|
||||
if (hr->session.ugs->mode == UWSGI_HTTP_SSL) {
|
||||
if (uwsgi_buffer_append_keyval(out, "HTTPS", 5, "on", 2)) return -1;
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
const char *servername = SSL_get_servername(hr->ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername && strlen(servername) <= 0xff) {
|
||||
peer->key_len = strlen(servername);
|
||||
memcpy(peer->key, servername, peer->key_len) ;
|
||||
}
|
||||
#endif
|
||||
hr->ssl_client_cert = SSL_get_peer_certificate(hr->ssl);
|
||||
if (hr->ssl_client_cert) {
|
||||
X509_NAME *name = X509_get_subject_name(hr->ssl_client_cert);
|
||||
@@ -227,7 +242,7 @@ void hr_session_ssl_close(struct corerouter_session *cs) {
|
||||
#endif
|
||||
|
||||
// clear the errors (otherwise they could be propagated)
|
||||
ERR_clear_error();
|
||||
hr_ssl_clear_errors();
|
||||
SSL_free(hr->ssl);
|
||||
}
|
||||
|
||||
@@ -263,6 +278,8 @@ ssize_t hr_ssl_write(struct corerouter_peer *main_peer) {
|
||||
struct corerouter_session *cs = main_peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
int ret = SSL_write(hr->ssl, main_peer->out->buf + main_peer->out_pos, main_peer->out->pos - main_peer->out_pos);
|
||||
if (ret > 0) {
|
||||
main_peer->out_pos += ret;
|
||||
@@ -287,9 +304,11 @@ ssize_t hr_ssl_write(struct corerouter_peer *main_peer) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (ret == 0) return 0;
|
||||
|
||||
int err = SSL_get_error(hr->ssl, ret);
|
||||
|
||||
if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
cr_reset_hooks_and_read(main_peer, hr_ssl_write);
|
||||
return 1;
|
||||
@@ -315,6 +334,8 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
struct corerouter_session *cs = main_peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
// try to always leave 4k available
|
||||
if (uwsgi_buffer_ensure(main_peer->in, uwsgi.page_size)) return -1;
|
||||
int ret = SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, main_peer->in->len - main_peer->in->pos);
|
||||
@@ -343,9 +364,11 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
#endif
|
||||
return http_parse(main_peer);
|
||||
}
|
||||
if (ret == 0) return 0;
|
||||
|
||||
int err = SSL_get_error(hr->ssl, ret);
|
||||
|
||||
if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
cr_reset_hooks_and_read(main_peer, hr_ssl_read);
|
||||
return 1;
|
||||
@@ -367,6 +390,46 @@ ssize_t hr_ssl_read(struct corerouter_peer *main_peer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t hr_ssl_shutdown(struct corerouter_peer *peer) {
|
||||
// ensure no hooks are set
|
||||
if (uwsgi_cr_set_hooks(peer, NULL, NULL)) return -1;
|
||||
|
||||
struct corerouter_session *cs = peer->session;
|
||||
struct http_session *hr = (struct http_session *) cs;
|
||||
|
||||
hr_ssl_clear_errors();
|
||||
|
||||
int ret = SSL_shutdown(hr->ssl);
|
||||
int err = 0;
|
||||
|
||||
if (ret != 1 && ERR_peek_error()) {
|
||||
err = SSL_get_error(hr->ssl, ret);
|
||||
}
|
||||
|
||||
// no error, close the connection
|
||||
if (ret == 1 || err == 0 || err == SSL_ERROR_ZERO_RETURN) return 0;
|
||||
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
if (uwsgi_cr_set_hooks(peer, hr_ssl_shutdown, NULL)) return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_WANT_WRITE) {
|
||||
if (uwsgi_cr_set_hooks(peer, NULL, hr_ssl_shutdown)) return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_SYSCALL) {
|
||||
uwsgi_cr_error(peer, "hr_ssl_shutdown()");
|
||||
}
|
||||
|
||||
else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
|
||||
hr->ssl = SSL_new(ugs->ctx);
|
||||
SSL_set_fd(hr->ssl, hr->session.main_peer->fd);
|
||||
@@ -375,6 +438,7 @@ void hr_setup_ssl(struct http_session *hr, struct uwsgi_gateway_socket *ugs) {
|
||||
SSL_set_ex_data(hr->ssl, uhttp.spdy_index, hr);
|
||||
#endif
|
||||
uwsgi_cr_set_hooks(hr->session.main_peer, hr_ssl_read, NULL);
|
||||
hr->session.main_peer->flush = hr_ssl_shutdown;
|
||||
hr->session.close = hr_session_ssl_close;
|
||||
hr->func_write = hr_ssl_write;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
uint32_t h_len = 0;
|
||||
|
||||
int has_size = 0;
|
||||
int has_connection = 0;
|
||||
|
||||
for(i=next;i<len;i++) {
|
||||
if (key) {
|
||||
@@ -73,6 +74,7 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
if (hr->session.can_keepalive) {
|
||||
#endif
|
||||
if (!uwsgi_strnicmp(key, colon-key, "Connection", 10)) {
|
||||
has_connection = 1;
|
||||
if (!uwsgi_strnicmp(colon+2, h_len-((colon-key)+2), "close", 5)) {
|
||||
goto end;
|
||||
}
|
||||
@@ -169,6 +171,10 @@ int http_response_parse(struct http_session *hr, struct uwsgi_buffer *ub, size_t
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// avoid iOS making mess...
|
||||
if (!has_connection) {
|
||||
if (uwsgi_buffer_insert(ub, len-2, "Connection: close\r\n", 19)) return -1;
|
||||
}
|
||||
hr->session.can_keepalive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-7
@@ -180,8 +180,10 @@ struct uwsgi_buffer *spdy_http_to_spdy(char *buf, size_t len, uint32_t *hh) {
|
||||
if (!key) return ub;
|
||||
|
||||
uint32_t h_len = 0;
|
||||
|
||||
// headers (key lowercase...)
|
||||
// merge header values and ensure keys are all lowercase
|
||||
struct uwsgi_string_list *hr=NULL, *usl=NULL;
|
||||
char *line_value;
|
||||
size_t line_key_len, line_value_len;
|
||||
for(i=next;i<len;i++) {
|
||||
if (key) {
|
||||
if (buf[i] == '\r' || buf[i] == '\n') {
|
||||
@@ -192,10 +194,37 @@ struct uwsgi_buffer *spdy_http_to_spdy(char *buf, size_t len, uint32_t *hh) {
|
||||
// tolower !!!
|
||||
size_t j;
|
||||
for(j=0;j<h_len;j++) {
|
||||
key[j] = tolower((int) key[j]);
|
||||
// don't lowercase values, only keys
|
||||
if (key[j] == ':') break;
|
||||
key[j] = tolower((int) key[j]);
|
||||
}
|
||||
line_key_len = colon - key;
|
||||
key[line_key_len] = 0;
|
||||
line_value_len = h_len - 2 - line_key_len;
|
||||
line_value = uwsgi_strncopy(colon+2, line_value_len);
|
||||
if (hr) {
|
||||
// check if we already store values for this key
|
||||
usl = uwsgi_string_list_has_item(hr, key, line_key_len);
|
||||
if (usl) {
|
||||
// we have this key, append new value
|
||||
char *oldval = usl->custom_ptr;
|
||||
usl->custom_ptr = uwsgi_concat3n(usl->custom_ptr, usl->custom, "\0", 1, line_value, line_value_len);
|
||||
usl->custom = usl->custom + 1 + line_value_len;
|
||||
free(oldval);
|
||||
}
|
||||
else {
|
||||
// this key is new
|
||||
usl = uwsgi_string_new_list(&hr, key);
|
||||
usl->custom_ptr = line_value;
|
||||
usl->custom = line_value_len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// this is first key
|
||||
usl = uwsgi_string_new_list(&hr, key);
|
||||
usl->custom_ptr = line_value;
|
||||
usl->custom = line_value_len;
|
||||
}
|
||||
if (uwsgi_buffer_append_keyval32(ub, key, colon-key, colon+2, h_len-((colon-key)+2))) goto end;
|
||||
*hh+=1;
|
||||
key = NULL;
|
||||
h_len = 0;
|
||||
}
|
||||
@@ -210,6 +239,18 @@ struct uwsgi_buffer *spdy_http_to_spdy(char *buf, size_t len, uint32_t *hh) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append all merged header lines to buffer and free memory
|
||||
struct uwsgi_string_list *ohr;
|
||||
while (hr) {
|
||||
if (uwsgi_buffer_append_keyval32(ub, hr->value, hr->len, hr->custom_ptr, hr->custom)) goto end;
|
||||
*hh+=1;
|
||||
ohr = hr;
|
||||
hr = hr->next;
|
||||
free(ohr->custom_ptr);
|
||||
free(ohr);
|
||||
}
|
||||
|
||||
return ub;
|
||||
|
||||
end:
|
||||
@@ -515,8 +556,10 @@ static ssize_t spdy_inflate_http_headers(struct http_session *hr) {
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp(cgi_name, nk_len, "HTTP_HOST", 9)) {
|
||||
new_peer->key = new_peer->out->buf + (new_peer->out->pos - v_len);
|
||||
new_peer->key_len = v_len;
|
||||
if (v_len <= 0xff) {
|
||||
memcpy(new_peer->key, new_peer->out->buf + (new_peer->out->pos - v_len), v_len);
|
||||
new_peer->key_len = v_len;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(cgi_name, nk_len, "REQUEST_URI", 11)) {
|
||||
char *path_info = new_peer->out->buf + (new_peer->out->pos - v_len);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -811,8 +811,25 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -3) != 0) {
|
||||
http = lua_tolstring(L, -2, &slen);
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
|
||||
if (lua_type(L, -1) == LUA_TTABLE) {
|
||||
for (i = 1; /*empty*/ ; ++i) {
|
||||
lua_rawgeti(L, -1, i);
|
||||
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
http2 = lua_tolstring(L, -1, &slen2);
|
||||
uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -543,7 +543,7 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(NULL, key, key_len, mono_plugin.modifier1);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (wsgi_req->app_id == -1 && key_len > 0) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&umono.lock_loader);
|
||||
}
|
||||
@@ -562,10 +562,15 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- unable to find Mono/ASP.NET application ---\n");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
if (!uwsgi.no_default_app && uwsgi.default_app > -1 && uwsgi_apps[uwsgi.default_app].modifier1 == mono_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
else {
|
||||
uwsgi_500(wsgi_req);
|
||||
uwsgi_log("--- unable to find Mono/ASP.NET application ---\n");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *app = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -121,7 +121,7 @@ int uwsgi_buffer_msgpack_int(struct uwsgi_buffer *ub, int64_t num) {
|
||||
if (num > 0 && num <= 127) {
|
||||
return uwsgi_buffer_byte(ub, (uint8_t) num);
|
||||
}
|
||||
else if (num < 0 && num >= 31) {
|
||||
else if (num < 0 && num >= -31) {
|
||||
return uwsgi_buffer_byte(ub, 224 | (int8_t) num);
|
||||
}
|
||||
else if (num <= 127 && num >= -127) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_variables.h"
|
||||
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
#include "ext/session/php_session.h"
|
||||
|
||||
#include <uwsgi.h>
|
||||
|
||||
+53
-39
@@ -1,12 +1,4 @@
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_variables.h"
|
||||
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include "common.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -34,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) {
|
||||
@@ -66,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
|
||||
};
|
||||
|
||||
@@ -82,7 +77,7 @@ static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
return str_length;
|
||||
}
|
||||
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
@@ -140,7 +135,7 @@ static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
static char *sapi_uwsgi_read_cookies(void)
|
||||
static char *sapi_uwsgi_read_cookies(TSRMLS_D)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
@@ -184,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);
|
||||
@@ -233,8 +228,9 @@ void uwsgi_php_set(char *opt) {
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
|
||||
}
|
||||
|
||||
// future implementation...
|
||||
extern ps_module ps_mod_uwsgi;
|
||||
PHP_MINIT_FUNCTION(uwsgi_php_minit) {
|
||||
php_session_register_module(&ps_mod_uwsgi);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -258,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();
|
||||
}
|
||||
|
||||
@@ -273,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();
|
||||
}
|
||||
|
||||
@@ -291,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();
|
||||
}
|
||||
|
||||
@@ -308,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();
|
||||
}
|
||||
|
||||
@@ -333,15 +333,16 @@ 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();
|
||||
}
|
||||
|
||||
if (uwsgi_cache_magic_set(key, keylen, value, vallen, expires, 0, cache)) {
|
||||
if (!uwsgi_cache_magic_set(key, keylen, value, vallen, expires, 0, cache)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
RETURN_NULL();
|
||||
@@ -355,15 +356,16 @@ 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();
|
||||
}
|
||||
|
||||
if (uwsgi_cache_magic_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE, cache)) {
|
||||
if (!uwsgi_cache_magic_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE, cache)) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
RETURN_NULL();
|
||||
@@ -516,7 +518,7 @@ static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
}
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_log_message(char *message) {
|
||||
static void sapi_uwsgi_log_message(char *message TSRMLS_DC) {
|
||||
|
||||
uwsgi_log("%s\n", message);
|
||||
}
|
||||
@@ -557,6 +559,10 @@ int uwsgi_php_init(void) {
|
||||
struct uwsgi_string_list *pset = uphp.set;
|
||||
struct uwsgi_string_list *append_config = uphp.append_config;
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_startup(1, 1, 0, NULL);
|
||||
#endif
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
|
||||
// applying custom options
|
||||
@@ -585,8 +591,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;
|
||||
@@ -655,15 +663,23 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
size_t real_filename_len = 0;
|
||||
struct stat php_stat;
|
||||
char *filename = NULL;
|
||||
int force_empty_script_name = 0;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
|
||||
#ifdef ZTS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
SG(server_context) = (void *) wsgi_req;
|
||||
|
||||
if (uwsgi_parse_vars(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;
|
||||
}
|
||||
@@ -720,6 +736,7 @@ int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
appready:
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
force_empty_script_name = 1;
|
||||
goto secure2;
|
||||
}
|
||||
|
||||
@@ -740,10 +757,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);
|
||||
@@ -853,24 +866,25 @@ 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);
|
||||
if (force_empty_script_name) {
|
||||
wsgi_req->script_name = "";
|
||||
wsgi_req->script_name_len = 0;
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name = real_filename + wsgi_req->document_root_len;
|
||||
wsgi_req->script_name = orig_path_info;
|
||||
if (path_info) {
|
||||
wsgi_req->script_name_len = path_info - orig_path_info;
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name_len = orig_path_info_len;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
#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);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "common.h"
|
||||
|
||||
PS_OPEN_FUNC(uwsgi) {
|
||||
PS_SET_MOD_DATA((char *)save_path);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PS_CLOSE_FUNC(uwsgi) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PS_READ_FUNC(uwsgi) {
|
||||
char *cache = PS_GET_MOD_DATA();
|
||||
uint64_t valsize = 0;
|
||||
char *value = uwsgi_cache_magic_get((char *)key, strlen(key), &valsize, NULL, cache);
|
||||
if (!value) return FAILURE;
|
||||
char *new_val = emalloc(valsize);
|
||||
memcpy(new_val, value, valsize);
|
||||
free(value);
|
||||
*val = new_val;
|
||||
*vallen = valsize;
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
PS_WRITE_FUNC(uwsgi) {
|
||||
char *cache = PS_GET_MOD_DATA();
|
||||
if (vallen == 0) return SUCCESS;
|
||||
if (!uwsgi_cache_magic_set((char *)key, strlen(key), (char *)val, vallen, 0, UWSGI_CACHE_FLAG_UPDATE, cache)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
PS_DESTROY_FUNC(uwsgi) {
|
||||
char *cache = PS_GET_MOD_DATA();
|
||||
if (!uwsgi_cache_magic_del((char *)key, strlen(key), cache)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
PS_GC_FUNC(uwsgi) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
ps_module ps_mod_uwsgi = {
|
||||
PS_MOD(uwsgi)
|
||||
};
|
||||
|
||||
@@ -25,4 +25,4 @@ phplibdir = os.environ.get('UWSGICONFIG_PHPLIBDIR')
|
||||
if phplibdir:
|
||||
LIBS.append('-Wl,-rpath=%s' % phplibdir)
|
||||
|
||||
GCC_LIST = ['php_plugin']
|
||||
GCC_LIST = ['php_plugin', 'session']
|
||||
|
||||
@@ -11,8 +11,8 @@ XS(XS_input_seek) {
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
psgi_check_args(1);
|
||||
uwsgi_request_body_seek(wsgi_req, SvIV(ST(0)));
|
||||
psgi_check_args(2);
|
||||
uwsgi_request_body_seek(wsgi_req, SvIV(ST(1)));
|
||||
|
||||
XSRETURN(0);
|
||||
}
|
||||
@@ -25,11 +25,12 @@ XS(XS_error) {
|
||||
psgi_check_args(0);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->error)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -41,11 +42,12 @@ XS(XS_input) {
|
||||
psgi_check_args(0);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->input)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -80,11 +82,12 @@ XS(XS_stream)
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
if (uwsgi.threads > 1) {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
}
|
||||
else {
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[0]);
|
||||
ST(0) = sv_bless(newRV_noinc(newSV(0)), ((HV **)wi->stream)[0]);
|
||||
}
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
else {
|
||||
@@ -141,7 +144,7 @@ XS(XS_input_read) {
|
||||
else {
|
||||
long orig_offset = 0;
|
||||
// first of all get the new orig_len;
|
||||
offset = abs(offset);
|
||||
offset = labs(offset);
|
||||
if (offset > (long) orig_len) {
|
||||
new_size = offset;
|
||||
orig_offset = offset - orig_len;
|
||||
@@ -271,6 +274,51 @@ nonworker:
|
||||
newCONSTSUB(stash, "SPOOL_RETRY", newSViv(-1));
|
||||
newCONSTSUB(stash, "SPOOL_IGNORE", newSViv(0));
|
||||
|
||||
HV *_opts = newHV();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (hv_exists(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key))) {
|
||||
SV **value = hv_fetch(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), 0);
|
||||
// last resort !!!
|
||||
if (!value) {
|
||||
uwsgi_log("[perl] WARNING !!! unable to build uwsgi::opt hash !!!\n");
|
||||
goto end;
|
||||
}
|
||||
if (SvTYPE(SvRV(*value)) == SVt_PVAV) {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
av_push((AV *)SvRV(*value), newSViv(1));
|
||||
}
|
||||
else {
|
||||
av_push((AV *)SvRV(*value), newSVpv(uwsgi.exported_opts[i]->value, 0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
AV *_opt_a = newAV();
|
||||
av_push(_opt_a, SvREFCNT_inc(*value));
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
av_push(_opt_a, newSViv(1));
|
||||
}
|
||||
else {
|
||||
av_push(_opt_a, newSVpv(uwsgi.exported_opts[i]->value, 0));
|
||||
}
|
||||
(void ) hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newRV_inc((SV *) _opt_a), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
(void )hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newSViv(1), 0);
|
||||
}
|
||||
else {
|
||||
(void)hv_store(_opts, uwsgi.exported_opts[i]->key, strlen(uwsgi.exported_opts[i]->key), newSVpv(uwsgi.exported_opts[i]->value, 0), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newCONSTSUB(stash, "opt", newRV_inc((SV *) _opts));
|
||||
|
||||
end:
|
||||
|
||||
init_perl_embedded_module();
|
||||
|
||||
}
|
||||
|
||||
+57
-10
@@ -114,7 +114,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
newobj = POPs;
|
||||
newobj = SvREFCNT_inc(POPs);
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
@@ -637,6 +637,19 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
// before the environ is set up.
|
||||
if (!wsgi_req->async_environ) return;
|
||||
|
||||
// we need to restore the context in case of multiple interpreters
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
if (uwsgi.threads < 2) {
|
||||
if (((PerlInterpreter **)wi->interpreter)[0] != uperl.main[0]) {
|
||||
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
|
||||
}
|
||||
}
|
||||
|
||||
// dereference %env
|
||||
SV *env = SvRV((SV *) wsgi_req->async_environ);
|
||||
|
||||
@@ -661,15 +674,21 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
|
||||
}
|
||||
|
||||
// Free the $env hash
|
||||
SvREFCNT_dec(wsgi_req->async_environ);
|
||||
|
||||
// async plagued could be defined in other areas...
|
||||
if (wsgi_req->async_plagued) {
|
||||
uwsgi_log("*** psgix.harakiri.commit requested ***\n");
|
||||
// Before we call exit(0) we'll run the
|
||||
// uwsgi_perl_atexit() hook which'll properly tear
|
||||
// down the interpreter.
|
||||
|
||||
// mark the request as ended (otherwise the atexit hook will be skipped)
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
goodbye_cruel_world();
|
||||
}
|
||||
|
||||
// clear the env
|
||||
SvREFCNT_dec(wsgi_req->async_environ);
|
||||
|
||||
// now we can check for changed files
|
||||
if (uperl.auto_reload) {
|
||||
time_t now = uwsgi_now();
|
||||
@@ -678,6 +697,19 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
// restore main interpreter if needed
|
||||
if (uwsgi.threads > 1) {
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (((PerlInterpreter **)wi->interpreter)[0] != uperl.main[0]) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
@@ -803,24 +835,39 @@ void uwsgi_perl_run_hook(SV *hook) {
|
||||
}
|
||||
|
||||
static void uwsgi_perl_atexit() {
|
||||
int i;
|
||||
|
||||
if (uwsgi.mywid == 0) goto realstuff;
|
||||
|
||||
// if hijacked do not run atexit hooks
|
||||
// if hijacked do not run atexit hooks -- TODO: explain why
|
||||
// not.
|
||||
if (uwsgi.workers[uwsgi.mywid].hijacked)
|
||||
return;
|
||||
goto destroyperl;
|
||||
|
||||
// if busy do not run atexit hooks
|
||||
// if busy do not run atexit hooks (as this part could be called in a signal handler
|
||||
// while a subroutine is running)
|
||||
if (uwsgi_worker_is_busy(uwsgi.mywid))
|
||||
return;
|
||||
|
||||
// managing atexit in async mode is a real pain...skip it for now
|
||||
if (uwsgi.async > 1)
|
||||
return;
|
||||
realstuff:
|
||||
|
||||
if (uperl.atexit) {
|
||||
uwsgi_perl_run_hook(uperl.atexit);
|
||||
}
|
||||
|
||||
destroyperl:
|
||||
|
||||
// We must free our perl context(s) so any DESTROY hooks
|
||||
// etc. will run.
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
PERL_SET_CONTEXT(uperl.main[i]);
|
||||
|
||||
// Destroy the PerlInterpreter, see "perldoc perlembed"
|
||||
perl_destruct(uperl.main[i]);
|
||||
perl_free(uperl.main[i]);
|
||||
}
|
||||
PERL_SYS_TERM();
|
||||
free(uperl.main);
|
||||
}
|
||||
|
||||
static uint64_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
@@ -68,7 +68,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
|
||||
|
||||
hitem = av_fetch(response, 1, 0);
|
||||
if (!hitem) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
if (!hitem || !SvRV(*hitem) || SvTYPE(SvRV(*hitem)) != SVt_PVAV) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
|
||||
headers = (AV *) SvRV(*hitem);
|
||||
if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
|
||||
@@ -318,6 +318,13 @@ XS(XS_alarm) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_worker_id) {
|
||||
dXSARGS;
|
||||
psgi_check_args(0);
|
||||
ST(0) = newSViv(uwsgi.mywid);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_async_connect) {
|
||||
|
||||
dXSARGS;
|
||||
@@ -768,6 +775,9 @@ XS(XS_sharedarea_wait) {
|
||||
id = SvIV(ST(0));
|
||||
if (items > 1) {
|
||||
freq = SvIV(ST(1));
|
||||
if (items > 2) {
|
||||
timeout = SvIV(ST(2));
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_sharedarea_wait(id, freq, timeout)) {
|
||||
@@ -943,7 +953,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));
|
||||
@@ -1039,5 +1049,6 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(spool);
|
||||
|
||||
psgi_xs(add_var);
|
||||
psgi_xs(worker_id);
|
||||
|
||||
}
|
||||
|
||||
@@ -66,17 +66,34 @@ static int uwsgi_pypy_init() {
|
||||
}
|
||||
else {
|
||||
if (upypy.home) {
|
||||
// first try with /bin way:
|
||||
#ifdef __CYGWIN__
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dll");
|
||||
#elif defined(__APPLE__)
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.dylib");
|
||||
#else
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/bin/libpypy-c.so");
|
||||
#endif
|
||||
if (uwsgi_file_exists(libpath)) {
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
free(libpath);
|
||||
|
||||
// fallback to old-style way
|
||||
if (!upypy.handler) {
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dll");
|
||||
#elif defined(__APPLE__)
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.dylib");
|
||||
#else
|
||||
char *libpath = uwsgi_concat2(upypy.home, "/libpypy-c.so");
|
||||
#endif
|
||||
if (uwsgi_file_exists(libpath)) {
|
||||
upypy.handler = dlopen(libpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
free(libpath);
|
||||
}
|
||||
free(libpath);
|
||||
}
|
||||
// fallback to standard library search path
|
||||
if (!upypy.handler) {
|
||||
|
||||
+12
-12
@@ -393,7 +393,7 @@ class WSGIinput(object):
|
||||
rlen = ffi.new('ssize_t*')
|
||||
chunk = lib.uwsgi_request_body_read(self.wsgi_req, size, rlen)
|
||||
if chunk != ffi.NULL:
|
||||
return ffi.string(chunk, rlen[0])
|
||||
return ffi.buffer(chunk, rlen[0])[:]
|
||||
if rlen[0] < 0:
|
||||
raise IOError("error reading wsgi.input")
|
||||
raise IOError("error waiting for wsgi.input")
|
||||
@@ -402,7 +402,7 @@ class WSGIinput(object):
|
||||
rlen = ffi.new('ssize_t*')
|
||||
chunk = lib.uwsgi_request_body_readline(self.wsgi_req, hint, rlen)
|
||||
if chunk != ffi.NULL:
|
||||
return ffi.string(chunk, rlen[0])
|
||||
return ffi.buffer(chunk, rlen[0])[:]
|
||||
if rlen[0] < 0:
|
||||
raise IOError("error reading line from wsgi.input")
|
||||
raise IOError("error waiting for line on wsgi.input")
|
||||
@@ -521,7 +521,7 @@ class uwsgi_pypy_RPC(object):
|
||||
def __call__(self, argc, argv, argvs, buf):
|
||||
pargs = []
|
||||
for i in range(0, argc):
|
||||
pargs.append(ffi.string(argv[i], argvs[i]))
|
||||
pargs.append(ffi.buffer(argv[i], argvs[i])[:])
|
||||
response = self.func(*pargs)
|
||||
if len(response) > 0:
|
||||
buf[0] = lib.uwsgi_malloc(len(response))
|
||||
@@ -560,7 +560,7 @@ def uwsgi_pypy_rpc(node, func, *args):
|
||||
|
||||
response = lib.uwsgi_do_rpc(c_node, ffi.new("char[]",func), argc, argv, argvs, rsize)
|
||||
if response:
|
||||
ret = ffi.string(response, rsize[0])
|
||||
ret = ffi.buffer(response, rsize[0])[:]
|
||||
lib.free(response)
|
||||
return ret
|
||||
return None
|
||||
@@ -587,7 +587,7 @@ def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
|
||||
value = lib.uwsgi_cache_magic_get(key, len(key), vallen, ffi.NULL, cache)
|
||||
if value == ffi.NULL:
|
||||
return None
|
||||
ret = ffi.string(value, vallen[0])
|
||||
ret = ffi.buffer(value, vallen[0])[:]
|
||||
libc.free(value)
|
||||
return ret
|
||||
uwsgi.cache_get = uwsgi_pypy_uwsgi_cache_get
|
||||
@@ -617,8 +617,9 @@ def uwsgi_pypy_uwsgi_cache_keys(cache=ffi.NULL):
|
||||
uci = ffi.new('struct uwsgi_cache_item **')
|
||||
while True:
|
||||
uci[0] = lib.uwsgi_cache_keys(uc, pos, uci)
|
||||
if uci[0] == ffi.NULL: break
|
||||
l.append(ffi.string(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize))
|
||||
if uci[0] == ffi.NULL:
|
||||
break
|
||||
l.append(ffi.buffer(lib.uwsgi_cache_item_key(uci[0]), uci[0].keysize)[:])
|
||||
lib.uwsgi_cache_rwunlock(uc)
|
||||
return l
|
||||
uwsgi.cache_keys = uwsgi_pypy_uwsgi_cache_keys
|
||||
@@ -849,7 +850,7 @@ def uwsgi_pypy_websocket_recv():
|
||||
ub = lib.uwsgi_websocket_recv(wsgi_req);
|
||||
if ub == ffi.NULL:
|
||||
raise IOError("unable to receive websocket message")
|
||||
ret = ffi.string(ub.buf, ub.pos)
|
||||
ret = ffi.buffer(ub.buf, ub.pos)[:]
|
||||
lib.uwsgi_buffer_destroy(ub)
|
||||
return ret
|
||||
uwsgi.websocket_recv = uwsgi_pypy_websocket_recv
|
||||
@@ -862,7 +863,7 @@ def uwsgi_pypy_websocket_recv_nb():
|
||||
ub = lib.uwsgi_websocket_recv_nb(wsgi_req);
|
||||
if ub == ffi.NULL:
|
||||
raise IOError("unable to receive websocket message")
|
||||
ret = ffi.string(ub.buf, ub.pos)
|
||||
ret = ffi.buffer(ub.buf, ub.pos)[:]
|
||||
lib.uwsgi_buffer_destroy(ub)
|
||||
return ret
|
||||
uwsgi.websocket_recv_nb = uwsgi_pypy_websocket_recv_nb
|
||||
@@ -897,7 +898,7 @@ def uwsgi_pypy_chunked_read(timeout=0):
|
||||
chunk = lib.uwsgi_chunked_read(wsgi_req, rlen, timeout, 0)
|
||||
if chunk == ffi.NULL:
|
||||
raise IOError("unable to receive chunked part")
|
||||
return ffi.string(chunk, rlen[0])
|
||||
return ffi.buffer(chunk, rlen[0])[:]
|
||||
uwsgi.chunked_read = uwsgi_pypy_chunked_read
|
||||
|
||||
"""
|
||||
@@ -911,8 +912,7 @@ def uwsgi_pypy_chunked_read_nb():
|
||||
if lib.uwsgi_is_again() > 0:
|
||||
return None
|
||||
raise IOError("unable to receive chunked part")
|
||||
|
||||
return ffi.string(chunk, rlen[0])
|
||||
return ffi.buffer(chunk, rlen[0])[:]
|
||||
uwsgi.chunked_read_nb = uwsgi_pypy_chunked_read_nb
|
||||
|
||||
"""
|
||||
|
||||
@@ -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) );
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"module", required_argument,'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
|
||||
{"wsgi", required_argument, 'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
|
||||
{"callable", required_argument, 0, "set default WSGI callable name", uwsgi_opt_set_str, &up.callable, 0},
|
||||
{"test", required_argument, 'J', "test a mdule import", uwsgi_opt_set_str, &up.test_module, 0},
|
||||
{"test", required_argument, 'J', "test a module import", uwsgi_opt_set_str, &up.test_module, 0},
|
||||
{"home", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
@@ -168,6 +168,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"py-sharedarea", required_argument, 0, "create a sharedarea from a python bytearray object of the specified size", uwsgi_opt_add_string_list, &up.sharedarea, 0},
|
||||
#endif
|
||||
|
||||
{"py-call-osafterfork", no_argument, 0, "enable child processes running cpython to trap OS signals", uwsgi_opt_true, &up.call_osafterfork, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -377,6 +379,11 @@ void uwsgi_python_post_fork() {
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
// reset python signal flags so child processes can trap signals
|
||||
if (up.call_osafterfork) {
|
||||
PyOS_AfterFork();
|
||||
}
|
||||
|
||||
uwsgi_python_reset_random_seed();
|
||||
|
||||
// call the post_fork_hook
|
||||
@@ -390,6 +397,7 @@ void uwsgi_python_post_fork() {
|
||||
PyErr_Clear();
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi_python_set_thread_name(0);
|
||||
if (up.auto_reload) {
|
||||
// spawn the reloader thread
|
||||
pthread_t par_tid;
|
||||
@@ -913,12 +921,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;
|
||||
@@ -1259,11 +1271,39 @@ void uwsgi_python_enable_threads() {
|
||||
up.reset_ts = threaded_reset_ts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uwsgi_log("python threads support enabled\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_set_thread_name(int core_id) {
|
||||
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
|
||||
PyObject *threading_module = PyImport_ImportModule("threading");
|
||||
if (threading_module) {
|
||||
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
|
||||
if (threading_module_dict) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
|
||||
#else
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
|
||||
#endif
|
||||
if (threading_current) {
|
||||
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
|
||||
if (!current_thread) {
|
||||
// ignore the error
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
|
||||
Py_INCREF(current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_python_init_thread(int core_id) {
|
||||
|
||||
// set a new ThreadState for each thread
|
||||
@@ -1275,29 +1315,7 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
uwsgi_log("python ThreadState %d = %p\n", core_id, pts);
|
||||
#endif
|
||||
UWSGI_GET_GIL;
|
||||
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
|
||||
PyObject *threading_module = PyImport_ImportModule("threading");
|
||||
if (threading_module) {
|
||||
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
|
||||
if (threading_module_dict) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
|
||||
#else
|
||||
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
|
||||
#endif
|
||||
if (threading_current) {
|
||||
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
|
||||
if (!current_thread) {
|
||||
// ignore the error
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
|
||||
Py_INCREF(current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_python_set_thread_name(core_id);
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
|
||||
@@ -1407,7 +1425,15 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
|
||||
int found = 0;
|
||||
struct uwsgi_string_list *usl = up.auto_reload_ignore;
|
||||
while(usl) {
|
||||
#ifdef PYTHREE
|
||||
PyObject *zero = PyUnicode_AsUTF8String(mod_name);
|
||||
char *str_mod_name = PyString_AsString(zero);
|
||||
int ret_cmp = strcmp(usl->value, str_mod_name);
|
||||
Py_DECREF(zero);
|
||||
if (!ret_cmp) {
|
||||
#else
|
||||
if (!strcmp(usl->value, PyString_AsString(mod_name))) {
|
||||
#endif
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
@@ -1644,6 +1670,8 @@ int uwsgi_python_spooler(char *filename, char *buf, uint16_t len, char *body, si
|
||||
PyDict_SetItemString(spool_dict, "body", value);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
// PyTuple_SetItem steals a reference !!!
|
||||
Py_INCREF(spool_dict);
|
||||
PyTuple_SetItem(pyargs, 0, spool_dict);
|
||||
|
||||
ret = python_call(spool_func, pyargs, 0, NULL);
|
||||
|
||||
@@ -27,7 +27,18 @@ char *uwsgi_python_get_thread_name(PyObject *thread_id) {
|
||||
if (PyInt_AsLong(thread_ident) == PyInt_AsLong(thread_id)) {
|
||||
PyObject *thread_name = PyObject_GetAttrString(threads_list_next, "name");
|
||||
if (!thread_name) goto clear2;
|
||||
#ifdef PYTHREE
|
||||
PyObject *thread_name_utf8 = PyUnicode_AsUTF8String(thread_name);
|
||||
if (!thread_name_utf8) goto clear2;
|
||||
char *name = NULL;
|
||||
char *tmp_name = PyString_AsString(thread_name_utf8);
|
||||
if (tmp_name) {
|
||||
name = uwsgi_str(tmp_name);
|
||||
Py_DECREF(thread_name_utf8);
|
||||
}
|
||||
#else
|
||||
char *name = PyString_AsString(thread_name);
|
||||
#endif
|
||||
Py_DECREF(threads_list_next);
|
||||
Py_DECREF(threads_list_iter);
|
||||
Py_DECREF(threads_list);
|
||||
@@ -133,6 +144,9 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
PyObject *st_items = PyIter_Next(stacktrace_iter);
|
||||
// we have the first traceback item
|
||||
while(st_items) {
|
||||
#ifdef PYTHREE
|
||||
int thread_name_need_free = 0;
|
||||
#endif
|
||||
PyObject *st_filename = PyTuple_GetItem(st_items, 0);
|
||||
if (!st_filename) { Py_DECREF(st_items); goto next; }
|
||||
PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
|
||||
@@ -149,12 +163,26 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
if (!iov[1].iov_base) {
|
||||
iov[1].iov_base = "<UnnamedPythonThread>";
|
||||
}
|
||||
#ifdef PYTHREE
|
||||
else {
|
||||
thread_name_need_free = 1;
|
||||
}
|
||||
#endif
|
||||
iov[1].iov_len = strlen(iov[1].iov_base);
|
||||
|
||||
iov[2].iov_base = " filename = ";
|
||||
iov[2].iov_len = 12;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_filename_utf8 = PyUnicode_AsUTF8String(st_filename);
|
||||
if (!st_filename_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
goto next;
|
||||
}
|
||||
iov[3].iov_base = PyString_AsString(st_filename_utf8);
|
||||
#else
|
||||
iov[3].iov_base = PyString_AsString(st_filename);
|
||||
#endif
|
||||
iov[3].iov_len = strlen(iov[3].iov_base);
|
||||
|
||||
iov[4].iov_base = " lineno = ";
|
||||
@@ -166,7 +194,17 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
iov[6].iov_base = " function = ";
|
||||
iov[6].iov_len = 12 ;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_name_utf8 = PyUnicode_AsUTF8String(st_name);
|
||||
if (!st_name_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
Py_DECREF(st_filename_utf8);
|
||||
goto next;
|
||||
}
|
||||
iov[7].iov_base = PyString_AsString(st_name_utf8);
|
||||
#else
|
||||
iov[7].iov_base = PyString_AsString(st_name);
|
||||
#endif
|
||||
iov[7].iov_len = strlen(iov[7].iov_base);
|
||||
|
||||
iov[8].iov_base = "";
|
||||
@@ -178,10 +216,24 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
iov[10].iov_base = "\n";
|
||||
iov[10].iov_len = 1;
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_line_utf8 = NULL;
|
||||
#endif
|
||||
if (st_line) {
|
||||
iov[8].iov_base = " line = ";
|
||||
iov[8].iov_len = 8;
|
||||
#ifdef PYTHREE
|
||||
PyObject *st_line_utf8 = PyUnicode_AsUTF8String(st_line);
|
||||
if (!st_line_utf8) {
|
||||
if (thread_name_need_free) free(iov[1].iov_base);
|
||||
Py_DECREF(st_filename_utf8);
|
||||
Py_DECREF(st_name_utf8);
|
||||
goto next;
|
||||
}
|
||||
iov[9].iov_base = PyString_AsString(st_line_utf8);
|
||||
#else
|
||||
iov[9].iov_base = PyString_AsString(st_line);
|
||||
#endif
|
||||
iov[9].iov_len = strlen(iov[9].iov_base);
|
||||
}
|
||||
|
||||
@@ -192,6 +244,15 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
// free the line_no
|
||||
free(iov[5].iov_base);
|
||||
Py_DECREF(st_items);
|
||||
#ifdef PYTHREE
|
||||
Py_DECREF(st_filename_utf8);
|
||||
Py_DECREF(st_name_utf8);
|
||||
if (st_line_utf8) {
|
||||
Py_DECREF(st_line_utf8);
|
||||
}
|
||||
if (thread_name_need_free)
|
||||
free(iov[1].iov_base);
|
||||
#endif
|
||||
st_items = PyIter_Next(stacktrace_iter);
|
||||
}
|
||||
if (write(client_fd, "\n", 1) < 0) {
|
||||
|
||||
+229
-11
@@ -23,6 +23,9 @@ static PyObject *py_uwsgi_add_var(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
static PyObject *py_uwsgi_micros(PyObject * self, PyObject * args) {
|
||||
return PyLong_FromUnsignedLongLong(uwsgi_micros());
|
||||
}
|
||||
|
||||
static PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -379,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);
|
||||
|
||||
@@ -1423,7 +1431,7 @@ PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int64_t value = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_inc64", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iL|l:sharedarea_inc64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1440,12 +1448,122 @@ PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_inc32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL|i:sharedarea_inc32", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_inc32(id, pos, value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_inc32()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_dec64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int64_t value = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL|l:sharedarea_dec64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_dec64(id, pos, value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec64()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_dec32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL|i:sharedarea_dec32", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_dec32(id, pos, value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_dec32()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iLI:sharedarea_write32", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write32(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write32()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write16(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int16_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iLI:sharedarea_write16", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write16(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write16()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int64_t value = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ill:sharedarea_write64", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iLL:sharedarea_write64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1467,7 +1585,7 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
char *value;
|
||||
Py_ssize_t value_len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ils#:sharedarea_write", &id, &pos, &value, &value_len)) {
|
||||
if (!PyArg_ParseTuple(args, "iLs#:sharedarea_write", &id, &pos, &value, &value_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1567,7 +1685,7 @@ PyObject *py_uwsgi_sharedarea_write8(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int8_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ilb:sharedarea_write8", &id, &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "iLb:sharedarea_write8", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1589,7 +1707,7 @@ PyObject *py_uwsgi_sharedarea_read64(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
int64_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read64", &id, &pos)) {
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read64", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1601,16 +1719,59 @@ PyObject *py_uwsgi_sharedarea_read64(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read64()");
|
||||
}
|
||||
|
||||
return PyLong_FromLong(value);
|
||||
return PyLong_FromLongLong(value);
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read32(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int32_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read32", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read32(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read32()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read16(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int16_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read16", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read16(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read16()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read8(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int8_t byte;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read8", &id, &pos)) {
|
||||
if (!PyArg_ParseTuple(args, "iL:sharedarea_read8", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1630,7 +1791,7 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
uint64_t len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_read", &id, &pos, &len)) {
|
||||
if (!PyArg_ParseTuple(args, "iL|L:sharedarea_read", &id, &pos, &len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1765,7 +1926,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;
|
||||
|
||||
@@ -1866,7 +2026,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
|
||||
@@ -1898,6 +2059,16 @@ PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uspool->pid);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_pids(PyObject * self, PyObject * args) {
|
||||
PyObject *ret = PyList_New(0);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
PyList_Append(ret, PyInt_FromLong(uspool->pid));
|
||||
uspool = uspool->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_connect(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -2150,7 +2321,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) {
|
||||
@@ -2329,6 +2501,7 @@ static PyMethodDef uwsgi_spooler_methods[] = {
|
||||
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
|
||||
{"spooler_jobs", py_uwsgi_spooler_jobs, METH_VARARGS, ""},
|
||||
{"spooler_pid", py_uwsgi_spooler_pid, METH_VARARGS, ""},
|
||||
{"spooler_pids", py_uwsgi_spooler_pids, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -2439,6 +2612,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
|
||||
{"add_var", py_uwsgi_add_var, METH_VARARGS, ""},
|
||||
|
||||
{"micros", py_uwsgi_micros, METH_VARARGS, ""},
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
@@ -2454,8 +2629,15 @@ static PyMethodDef uwsgi_sa_methods[] = {
|
||||
{"sharedarea_writelong", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_read64", py_uwsgi_sharedarea_read64, METH_VARARGS, ""},
|
||||
{"sharedarea_write64", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_read32", py_uwsgi_sharedarea_read32, METH_VARARGS, ""},
|
||||
{"sharedarea_write32", py_uwsgi_sharedarea_write32, METH_VARARGS, ""},
|
||||
{"sharedarea_read16", py_uwsgi_sharedarea_read16, METH_VARARGS, ""},
|
||||
{"sharedarea_write16", py_uwsgi_sharedarea_write16, METH_VARARGS, ""},
|
||||
{"sharedarea_inclong", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{"sharedarea_inc64", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{"sharedarea_inc32", py_uwsgi_sharedarea_inc32, METH_VARARGS, ""},
|
||||
{"sharedarea_dec64", py_uwsgi_sharedarea_dec64, METH_VARARGS, ""},
|
||||
{"sharedarea_dec32", py_uwsgi_sharedarea_dec32, METH_VARARGS, ""},
|
||||
{"sharedarea_rlock", py_uwsgi_sharedarea_rlock, METH_VARARGS, ""},
|
||||
{"sharedarea_wlock", py_uwsgi_sharedarea_wlock, METH_VARARGS, ""},
|
||||
{"sharedarea_unlock", py_uwsgi_sharedarea_unlock, METH_VARARGS, ""},
|
||||
@@ -3186,6 +3368,40 @@ PyObject *py_uwsgi_metric_get(PyObject * self, PyObject * args) {
|
||||
return PyLong_FromLongLong(value);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_set_max(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_set_max", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_set_max(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_set_min(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_set_min", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_set_min(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_metrics_methods[] = {
|
||||
{"metric_inc", py_uwsgi_metric_inc, METH_VARARGS, ""},
|
||||
@@ -3194,6 +3410,8 @@ static PyMethodDef uwsgi_metrics_methods[] = {
|
||||
{"metric_div", py_uwsgi_metric_div, METH_VARARGS, ""},
|
||||
{"metric_get", py_uwsgi_metric_get, METH_VARARGS, ""},
|
||||
{"metric_set", py_uwsgi_metric_set, METH_VARARGS, ""},
|
||||
{"metric_set_max", py_uwsgi_metric_set_max, METH_VARARGS, ""},
|
||||
{"metric_set_min", py_uwsgi_metric_set_min, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -197,6 +197,8 @@ struct uwsgi_python {
|
||||
PyObject *raw_callable;
|
||||
|
||||
struct uwsgi_string_list *sharedarea;
|
||||
|
||||
int call_osafterfork;
|
||||
};
|
||||
|
||||
|
||||
@@ -297,6 +299,8 @@ int uwsgi_python_send_body(struct wsgi_request *, PyObject *);
|
||||
|
||||
int uwsgi_request_python_raw(struct wsgi_request *);
|
||||
|
||||
void uwsgi_python_set_thread_name(int);
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -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_full(ctx, key, body, body_len) < 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_full(ctx, key, comp, body, body_len) < 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ static int rawrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_ga
|
||||
peer->last_hook_read = rr_instance_read;
|
||||
|
||||
// use the address as hostname
|
||||
peer->key = cs->ugs->name;
|
||||
memcpy(peer->key, cs->ugs->name, cs->ugs->name_len);
|
||||
peer->key_len = cs->ugs->name_len;
|
||||
|
||||
// the mapper hook
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
struct uwsgi_buffer *ub = NULL;
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->via = UWSGI_VIA_ROUTE;
|
||||
@@ -24,9 +26,17 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// convert the wsgi_request to an http proxy request
|
||||
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
|
||||
if (ur->custom & 0x02) {
|
||||
ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
}
|
||||
else if (ur->custom & 0x04) {
|
||||
ub = uwsgi_to_http_dumb(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
|
||||
}
|
||||
else {
|
||||
ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, ub_url ? ub_url->buf : NULL, ub_url ? ub_url->pos : 0);
|
||||
}
|
||||
|
||||
if (!ub) {
|
||||
if (ub_url) uwsgi_buffer_destroy(ub_url);
|
||||
uwsgi_log("unable to generate http request for %s\n", ub_addr->buf);
|
||||
@@ -46,11 +56,12 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->proto_parser_remains;
|
||||
wsgi_req->proto_parser_remains = 0;
|
||||
}
|
||||
|
||||
// ok now if have offload threads, directly use them
|
||||
if (!wsgi_req->post_file && !ur->custom && wsgi_req->socket->can_offload) {
|
||||
if (!wsgi_req->post_file && !(ur->custom & 0x01) && wsgi_req->socket->can_offload) {
|
||||
// append buffered body
|
||||
if (uwsgi.post_buffering > 0 && wsgi_req->post_cl > 0) {
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->post_buffering_buf, wsgi_req->post_cl)) {
|
||||
@@ -60,6 +71,14 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have a CONNECT request, let's confirm it to the client
|
||||
if (ur->custom & 0x02) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 Connection established", 26)) goto end;
|
||||
// no need to check for return value
|
||||
uwsgi_response_write_headers_do(wsgi_req);
|
||||
}
|
||||
|
||||
if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->status = 202;
|
||||
@@ -72,6 +91,7 @@ static int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
uwsgi_log("error routing request to http server %s\n", ub_addr->buf);
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
|
||||
@@ -102,15 +122,33 @@ static int uwsgi_router_http(struct uwsgi_route *ur, char *args) {
|
||||
}
|
||||
|
||||
static int uwsgi_router_proxyhttp(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 1;
|
||||
ur->custom = 0x1;
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_proxyhttp_connect(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0x1|0x02;
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_http_connect(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0x02;
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
static int uwsgi_router_httpdumb(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0x04;
|
||||
return uwsgi_router_http(ur, args);
|
||||
}
|
||||
|
||||
|
||||
static void router_http_register(void) {
|
||||
|
||||
uwsgi_register_router("http", uwsgi_router_http);
|
||||
uwsgi_register_router("httpdumb", uwsgi_router_httpdumb);
|
||||
uwsgi_register_router("proxyhttp", uwsgi_router_proxyhttp);
|
||||
uwsgi_register_router("httpconnect", uwsgi_router_http_connect);
|
||||
uwsgi_register_router("proxyhttpconnect", uwsgi_router_proxyhttp_connect);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_http_plugin = {
|
||||
|
||||
@@ -18,6 +18,8 @@ struct uwsgi_router_file_conf {
|
||||
char *mime;
|
||||
|
||||
char *no_cl;
|
||||
|
||||
char *no_headers;
|
||||
};
|
||||
|
||||
int uwsgi_routing_func_static(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
@@ -38,6 +40,7 @@ int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *u
|
||||
char buf[32768];
|
||||
struct stat st;
|
||||
int ret = UWSGI_ROUTE_BREAK;
|
||||
size_t remains = 0;
|
||||
|
||||
struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;
|
||||
|
||||
@@ -61,6 +64,11 @@ int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *u
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
uwsgi_buffer_destroy(ub_s);
|
||||
goto end2;
|
||||
@@ -82,8 +90,10 @@ int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *u
|
||||
else {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
|
||||
}
|
||||
|
||||
send:
|
||||
|
||||
size_t remains = st.st_size;
|
||||
remains = st.st_size;
|
||||
while(remains) {
|
||||
ssize_t rlen = read(fd, buf, UMIN(32768, remains));
|
||||
if (rlen <= 0) goto end2;
|
||||
@@ -125,6 +135,11 @@ int uwsgi_routing_func_sendfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
uwsgi_buffer_destroy(ub_s);
|
||||
goto end2;
|
||||
@@ -145,6 +160,8 @@ int uwsgi_routing_func_sendfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
|
||||
}
|
||||
|
||||
send:
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
|
||||
}
|
||||
@@ -188,6 +205,11 @@ int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
|
||||
if (!ub_s) goto end2;
|
||||
|
||||
// static file - don't update avg_rt after request
|
||||
wsgi_req->do_not_account_avg_rt = 1;
|
||||
|
||||
if (urfc->no_headers) goto send;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
|
||||
uwsgi_buffer_destroy(ub_s);
|
||||
goto end2;
|
||||
@@ -208,6 +230,8 @@ int uwsgi_routing_func_fastfile(struct wsgi_request *wsgi_req, struct uwsgi_rout
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
|
||||
}
|
||||
|
||||
send:
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (uwsgi_response_write_headers_do(wsgi_req)) goto end2;
|
||||
}
|
||||
@@ -256,6 +280,7 @@ static int uwsgi_router_file(struct uwsgi_route *ur, char *args) {
|
||||
"no_cl", &urfc->no_cl,
|
||||
"no_content_length", &urfc->no_cl,
|
||||
"mime", &urfc->mime,
|
||||
"no_headers", &urfc->no_headers,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid file route syntax: %s\n", args);
|
||||
return -1;
|
||||
|
||||
@@ -35,7 +35,13 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) ur->data;
|
||||
char *addr = ur->data + sizeof(struct uwsgi_header);
|
||||
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_addr = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, addr, strlen(addr));
|
||||
if (!ub_addr) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->via = UWSGI_VIA_ROUTE;
|
||||
|
||||
@@ -54,6 +60,7 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains)) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->post_pos += wsgi_req->proto_parser_remains;
|
||||
wsgi_req->proto_parser_remains = 0;
|
||||
}
|
||||
|
||||
@@ -65,18 +72,20 @@ static int uwsgi_routing_func_uwsgi_remote(struct wsgi_request *wsgi_req, struct
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
|
||||
if (!uwsgi_offload_request_net_do(wsgi_req, ub_addr->buf, ub)) {
|
||||
wsgi_req->via = UWSGI_VIA_OFFLOAD;
|
||||
wsgi_req->status = 202;
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_proxy_nb(wsgi_req, addr, ub, remains, uwsgi.socket_timeout)) {
|
||||
uwsgi_log("error routing request to uwsgi server %s\n", addr);
|
||||
if (uwsgi_proxy_nb(wsgi_req, ub_addr->buf, ub, remains, uwsgi.socket_timeout)) {
|
||||
uwsgi_log("error routing request to uwsgi server %s\n", ub_addr->buf);
|
||||
}
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub_addr);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -150,6 +150,11 @@ static void rrdtool_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, c
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int ret = snprintf(buf, 1024, "N:%lld", (long long) (*um->value));
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
if (ret < 3 || ret >= 1024) {
|
||||
uwsgi_log("unable to update rrdtool metric for %s\n", um->name);
|
||||
goto next;
|
||||
|
||||
@@ -31,7 +31,12 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->arg[0] == '/') {
|
||||
ul->fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
}
|
||||
else {
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
@@ -62,7 +67,12 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
*port = 0;
|
||||
}
|
||||
|
||||
ul->addr_len = socket_to_in_addr(ul->arg, NULL, portn, &ul->addr.sa_in);
|
||||
if (ul->arg[0] == '/') {
|
||||
ul->addr_len = socket_to_un_addr(ul->arg, &ul->addr.sa_un);
|
||||
}
|
||||
else {
|
||||
ul->addr_len = socket_to_in_addr(ul->arg, NULL, portn, &ul->addr.sa_in);
|
||||
}
|
||||
|
||||
if (port) *port = ':';
|
||||
if (comma) *comma = ',';
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -288,15 +288,15 @@ static ssize_t sr_read(struct corerouter_peer *main_peer) {
|
||||
// set default peer hook
|
||||
peer->last_hook_read = sr_instance_read;
|
||||
// use the address as hostname
|
||||
peer->key = cs->ugs->name;
|
||||
memcpy(peer->key, cs->ugs->name, cs->ugs->name_len);
|
||||
peer->key_len = cs->ugs->name_len;
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
if (usr.sni) {
|
||||
const char *servername = SSL_get_servername(sr->ssl, TLSEXT_NAMETYPE_host_name);
|
||||
if (servername) {
|
||||
peer->key = (char *) servername;
|
||||
if (servername && strlen(servername) <= 0xff) {
|
||||
peer->key_len = strlen(servername);
|
||||
memcpy(peer->key, servername, peer->key_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -92,6 +92,11 @@ static void stats_pusher_socket(struct uwsgi_stats_pusher_instance *uspi, time_t
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
socket_send_metric(ub, uspi, um);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (um->reset_after_push){
|
||||
uwsgi_wlock(uwsgi.metrics_lock);
|
||||
*um->value = um->initial_value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
}
|
||||
um = um->next;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user