mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
237f11dba3 | ||
|
|
313f1c2f29 | ||
|
|
f0862f3bc7 | ||
|
|
1a8850ffe5 | ||
|
|
e640f812ba | ||
|
|
75ea170472 | ||
|
|
1b14b1926e | ||
|
|
edaed7ab01 | ||
|
|
6cceece3d7 | ||
|
|
2add03edb8 | ||
|
|
7aab9bae51 | ||
|
|
46c2c1d885 | ||
|
|
544e97fac0 | ||
|
|
265a700498 | ||
|
|
a657b4b0aa | ||
|
|
ac97c8cf34 | ||
|
|
545f3ee608 | ||
|
|
fcd1a36420 | ||
|
|
47a8ab3da9 | ||
|
|
c4375a8e7a | ||
|
|
a6c5bd3bb3 | ||
|
|
d53127e8cf | ||
|
|
851dd987ab | ||
|
|
cf582af970 | ||
|
|
d0ec331b6b | ||
|
|
cc75f5f7b3 | ||
|
|
3d08b7fdd0 | ||
|
|
7a92449fc3 | ||
|
|
4b3c34469d | ||
|
|
55bf34561e | ||
|
|
7e79dc0405 | ||
|
|
d3053523ab | ||
|
|
e32185cc14 | ||
|
|
8e3e3cf27b | ||
|
|
e2cea376e8 | ||
|
|
2a27b66d96 | ||
|
|
522717ca99 | ||
|
|
5ee106170b | ||
|
|
d62f04a5a6 | ||
|
|
eefe5048b2 | ||
|
|
8f792fde2d | ||
|
|
d8ef2d8300 | ||
|
|
e69dd5cb6a | ||
|
|
8acd57d87e | ||
|
|
a42aa1a273 | ||
|
|
4b2b7ccf82 | ||
|
|
e0fa180a23 | ||
|
|
06ea1fcd1b | ||
|
|
567bcc582d | ||
|
|
844f8c71fa | ||
|
|
bddbbb93cd | ||
|
|
310cc83d36 | ||
|
|
23dcdc5863 | ||
|
|
1286e1835c | ||
|
|
613f2ed939 | ||
|
|
46108f8d0c | ||
|
|
28dcfa4131 | ||
|
|
b48597d3c3 | ||
|
|
fe4c6ba13e | ||
|
|
4049493ffd | ||
|
|
0c9b6e98f7 | ||
|
|
ce33d0be5a | ||
|
|
4f0fb90bff | ||
|
|
66eff0107a | ||
|
|
82f83e610f | ||
|
|
cf7df391ad | ||
|
|
244c9f8204 | ||
|
|
26dc19df7d | ||
|
|
7b8bff1a08 | ||
|
|
0b010124ef | ||
|
|
c7bde15f39 | ||
|
|
b941e4f2f0 | ||
|
|
536c6e7e29 | ||
|
|
dfe4abec35 | ||
|
|
693b80d7d3 | ||
|
|
c9e6475ef4 | ||
|
|
b745132ebd | ||
|
|
19686cb19f | ||
|
|
e0c0593b5b | ||
|
|
415a8af363 | ||
|
|
d44777b1b4 | ||
|
|
e3ff3037b4 | ||
|
|
7add30fd31 | ||
|
|
501cd0349b | ||
|
|
7b4e3f6601 | ||
|
|
8622c2780c | ||
|
|
13de7b6d5b | ||
|
|
53cb864f9c | ||
|
|
72f693f02a | ||
|
|
fb80e32682 | ||
|
|
1db3426ee1 | ||
|
|
a44879e384 | ||
|
|
c0075c817d | ||
|
|
177dc3322b | ||
|
|
21ef4fc89b | ||
|
|
f467643f6f | ||
|
|
3db41e7e05 | ||
|
|
73151729c6 | ||
|
|
5d9c415028 | ||
|
|
b92ed4da4e | ||
|
|
2d1a9a03d2 | ||
|
|
5d6edd2321 | ||
|
|
365f4ba83f | ||
|
|
66e30ae293 | ||
|
|
728425de19 | ||
|
|
b0af1f800b | ||
|
|
543271e856 | ||
|
|
a1564a44fa | ||
|
|
571029cfd3 | ||
|
|
579eaa630a | ||
|
|
9530c8ffe0 | ||
|
|
0d8690091b | ||
|
|
5b5e3a1ec1 | ||
|
|
869ae5e3ed | ||
|
|
d6dc8d86f8 | ||
|
|
758745be68 | ||
|
|
2adfa56d6a | ||
|
|
a4c728f5df | ||
|
|
5c06341b7f | ||
|
|
6f57902a9b | ||
|
|
a3e118893d | ||
|
|
ff2d3c29d6 | ||
|
|
59a8df85f2 | ||
|
|
e303bd182a | ||
|
|
dcef9a497c | ||
|
|
8d4fd66aaf | ||
|
|
471bd23acf | ||
|
|
ffcef81dd0 | ||
|
|
317df5d06b | ||
|
|
ad7b5efd6f | ||
|
|
891f770724 | ||
|
|
0b6d715982 | ||
|
|
76c2415516 | ||
|
|
3260faca17 | ||
|
|
feb493158c | ||
|
|
a5c1556cb7 | ||
|
|
89e640bdd9 | ||
|
|
3ade8daff8 | ||
|
|
049ea3fbed | ||
|
|
715d26beed | ||
|
|
1f5064094c | ||
|
|
7ed522dc29 | ||
|
|
2086500405 | ||
|
|
8f79409ed1 | ||
|
|
c2a3cd1476 | ||
|
|
e195a5d72c | ||
|
|
c86b757904 | ||
|
|
6800d2ac95 | ||
|
|
90fda2b4bb | ||
|
|
bf7ded9058 | ||
|
|
6615dc3a62 | ||
|
|
c35054085c | ||
|
|
fdf2bd7f96 | ||
|
|
1c10b9dfe1 | ||
|
|
6854394e5c | ||
|
|
78a0d5f432 | ||
|
|
5fe5aa70a4 | ||
|
|
e9c0c6bd0b | ||
|
|
5d12b3dc9c | ||
|
|
169a4b66db | ||
|
|
fbd6329db9 | ||
|
|
69c2e56857 | ||
|
|
18f7d1edd3 | ||
|
|
3f7cd5ff92 | ||
|
|
785e1dbf83 | ||
|
|
bc6acf8d14 | ||
|
|
3a099d0b2e | ||
|
|
f9ad5e4144 | ||
|
|
ce9f6650a0 | ||
|
|
fdeef04343 | ||
|
|
fe72ec82e1 | ||
|
|
fd0f308273 | ||
|
|
f4e9ab43cb | ||
|
|
3a141b523c | ||
|
|
2d731532be | ||
|
|
d545cd5be0 | ||
|
|
261d05d67e | ||
|
|
639995785a | ||
|
|
817e076cae | ||
|
|
713370f343 | ||
|
|
5594503a56 | ||
|
|
d57e5d46fb | ||
|
|
ee2db5fabd | ||
|
|
0c4cd6f378 | ||
|
|
8c32b9665c | ||
|
|
7405a01654 | ||
|
|
5d27691b4b | ||
|
|
19bbcfbf4c | ||
|
|
fa1064db87 | ||
|
|
850ac69ca1 | ||
|
|
943edeb30c | ||
|
|
01815a354b | ||
|
|
2f4412aca1 | ||
|
|
2782bb7594 | ||
|
|
074c1298d5 | ||
|
|
55a7911611 | ||
|
|
013ad3044d | ||
|
|
dcf4217b9d | ||
|
|
876dfc31a9 | ||
|
|
fd03bdbe00 | ||
|
|
83612649d5 | ||
|
|
3c4db7e97e | ||
|
|
088c70efdc | ||
|
|
2b19029dd0 | ||
|
|
4fb5a84378 | ||
|
|
b3107d9a25 | ||
|
|
bf32988f3e | ||
|
|
1bf3dd7bf4 | ||
|
|
07fd84f89f | ||
|
|
3a8db4a97a | ||
|
|
aea30a26f5 | ||
|
|
8f5d1cdae7 | ||
|
|
53913357e0 | ||
|
|
098416f444 | ||
|
|
c98cb09c7c | ||
|
|
bb1ef28d69 | ||
|
|
1d5b05265d | ||
|
|
d9fef3c30e | ||
|
|
e5dfb9efc3 | ||
|
|
02bab15e86 | ||
|
|
6f4ddead09 | ||
|
|
b361248ff6 | ||
|
|
e9c42ceaa5 | ||
|
|
5d7029744a | ||
|
|
1084a3afa8 | ||
|
|
ed254bffee | ||
|
|
733784d7dd | ||
|
|
cb5b26bcb4 | ||
|
|
0065152bb1 | ||
|
|
03266203fd | ||
|
|
4a5f68f9d8 | ||
|
|
83e31a1c27 | ||
|
|
0efed5ef9c | ||
|
|
cdfef1281d | ||
|
|
e00907e142 | ||
|
|
6dcbcf39e3 | ||
|
|
044579a8e0 | ||
|
|
d2b52b4663 | ||
|
|
7f75b2c02c | ||
|
|
24a3f671e5 | ||
|
|
875100e3c8 | ||
|
|
34bc7c0cfd | ||
|
|
b39a10ff7c | ||
|
|
02331904de |
@@ -32,3 +32,14 @@ f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
|
||||
@@ -14,3 +14,6 @@ Cal Leeming, Simplicity Media Ltd
|
||||
Luigi Scarso
|
||||
Corey Farwell
|
||||
Charles Duffy
|
||||
Lukas Lalinsky
|
||||
Steven Fernandez
|
||||
Łukasz Mierzwa
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
*** december 2011 ***
|
||||
|
||||
* 1.0 [20111230]
|
||||
|
||||
- adaptive process spawning (--cheaper option)
|
||||
- new control options --stop, --reload, --suspend, --resume, --pause
|
||||
- stats framework
|
||||
- new subscription system
|
||||
- support for mime types in static file serving
|
||||
- posix capablities support
|
||||
- uWSGI mules and farms
|
||||
- support for multiple --touch-reload options
|
||||
- new logging subsystem
|
||||
- new custom locking subsystem
|
||||
- process name handling
|
||||
- better (and faster) HTTP parser
|
||||
- perl and python threading improvements
|
||||
- new plugins: rrdtool, carbon, cgi, php
|
||||
- various improvements in the Rack/ruby plugin
|
||||
- Linux KSM support
|
||||
- refactored ping and nagios plugins
|
||||
- support for signals in lazy mode
|
||||
- optimized static-file serving
|
||||
- support for linux unshare()
|
||||
|
||||
*** august 2011 ***
|
||||
|
||||
* 0.9.9 [20110829]
|
||||
|
||||
+39
-4
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2011 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
|
||||
@@ -73,6 +73,7 @@ typedef struct {
|
||||
char scheme[9];
|
||||
int cgi_mode ;
|
||||
int max_vars;
|
||||
int empty_remote_user;
|
||||
} uwsgi_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
@@ -162,6 +163,7 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->script_name[0] = 0;
|
||||
c->empty_remote_user = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -177,6 +179,7 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->empty_remote_user = 1;
|
||||
c->script_name[0] = 0;
|
||||
if (dir) {
|
||||
if (strcmp(dir, "/")) {
|
||||
@@ -344,7 +347,15 @@ static int uwsgi_handler(request_rec *r) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
|
||||
//
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
|
||||
}
|
||||
else if (c->empty_remote_user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
|
||||
}
|
||||
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
|
||||
}
|
||||
@@ -354,7 +365,8 @@ static int uwsgi_handler(request_rec *r) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
|
||||
}
|
||||
|
||||
if (c->script_name[0] != 0) {
|
||||
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
|
||||
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
|
||||
}
|
||||
@@ -621,7 +633,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
|
||||
c->cgi_mode = 1 ;
|
||||
}
|
||||
|
||||
@@ -722,6 +734,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
|
||||
|
||||
uwsgi_cfg *c ;
|
||||
|
||||
if (cfg) {
|
||||
c = cfg ;
|
||||
}
|
||||
else {
|
||||
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
|
||||
c->empty_remote_user = 1;
|
||||
}
|
||||
else {
|
||||
c->empty_remote_user = 0;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
|
||||
}
|
||||
|
||||
static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
|
||||
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
|
||||
@@ -730,6 +764,7 @@ static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
|
||||
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
|
||||
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
|
||||
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
|
||||
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
print("i am the bootstrap for uwsgi.SymbolsImporter")
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
|
||||
|
||||
@@ -27,7 +27,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, ugreen
|
||||
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = true
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
|
||||
@@ -6,12 +6,7 @@ void uwsgi_init_cache() {
|
||||
int i;
|
||||
|
||||
if (!uwsgi.cache_blocksize)
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uwsgi.cache_hashtable) {
|
||||
@@ -91,158 +86,8 @@ void uwsgi_init_cache() {
|
||||
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
|
||||
uwsgi_rwlock_init(uwsgi.cache_lock);
|
||||
|
||||
uwsgi_log("*** Cache subsystem initialized: %dMB preallocated ***\n", ((sizeof(uint64_t) * UMAX16) + (sizeof(uint64_t) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024));
|
||||
}
|
||||
|
||||
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint64_t ovl;
|
||||
struct uwsgi_subscriber *usub;
|
||||
struct uwsgi_subscriber_name *ret = NULL;
|
||||
|
||||
usub = (struct uwsgi_subscriber *) uwsgi_dict_get(udict, key, keylen, &ovl);
|
||||
|
||||
if (usub == NULL || !ovl) return NULL;
|
||||
|
||||
if (!usub->nodes) return NULL;
|
||||
|
||||
if (usub && ovl) {
|
||||
ret = &usub->names[usub->current];
|
||||
// dead node
|
||||
if (ret->len == 0) {
|
||||
if (usub->current == usub->nodes-1) {
|
||||
usub->nodes--;
|
||||
}
|
||||
// retry with another node (if available)
|
||||
if (usub->nodes > 0) {
|
||||
usub->current++;
|
||||
if (usub->current >= usub->nodes) usub->current = 0;
|
||||
return uwsgi_get_subscriber(udict, key, keylen);
|
||||
}
|
||||
}
|
||||
|
||||
if (usub->nodes > 1) {
|
||||
usub->current++;
|
||||
if (usub->current >= usub->nodes) usub->current = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_add_subscriber(struct uwsgi_dict *udict, struct uwsgi_subscribe_req *usr) {
|
||||
|
||||
char *ptr;
|
||||
uint64_t vallen = 0;
|
||||
struct uwsgi_subscriber *usub, nusub;
|
||||
int found = 0;
|
||||
int i;
|
||||
|
||||
ptr = uwsgi_dict_get(udict, usr->key, usr->keylen, &vallen);
|
||||
if (ptr && vallen) {
|
||||
usub = (struct uwsgi_subscriber *) ptr;
|
||||
for(i=0;i<(int)usub->nodes;i++) {
|
||||
if (!uwsgi_strncmp(usub->names[i].name, usub->names[i].len, usr->address, usr->address_len)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
found = usub->nodes;
|
||||
// check for unallocated slot
|
||||
for(i=0;i<(int)usub->nodes;i++) {
|
||||
if (usub->names[i].len == 0) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
usub->names[found].len = usr->address_len;
|
||||
usub->names[found].modifier1 = usr->modifier1;
|
||||
usub->names[found].modifier2 = usr->modifier2;
|
||||
memcpy(usub->names[found].name, usr->address, usr->address_len);
|
||||
if (found == (int) usub->nodes) {
|
||||
usub->nodes++;
|
||||
}
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
udict->count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
nusub.nodes = 1;
|
||||
nusub.current = 0;
|
||||
memcpy(nusub.names[0].name, usr->address, usr->address_len);
|
||||
nusub.names[0].len = usr->address_len;
|
||||
nusub.names[0].modifier1 = usr->modifier1;
|
||||
nusub.names[0].modifier2 = usr->modifier2;
|
||||
uwsgi_dict_set(udict, usr->key, usr->keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
|
||||
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
udict->count++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
|
||||
|
||||
int i;
|
||||
|
||||
struct uwsgi_dict *udict = (struct uwsgi_dict *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!blocksize) blocksize = 4096;
|
||||
|
||||
if (blocksize % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid shared dictionary blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) udict->blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
udict->blocksize = blocksize;
|
||||
udict->max_items = items;
|
||||
|
||||
udict->hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->hashtable) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
|
||||
udict->unused_stack = (uint64_t *) mmap(NULL, sizeof(uint64_t) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->unused_stack) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
|
||||
|
||||
udict->items = (struct uwsgi_dict_item *) mmap(NULL, sizeof(struct uwsgi_dict_item) * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->items) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
udict->data = mmap(NULL, udict->blocksize * udict->max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!udict->data) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0;i< (int) udict->max_items;i++) {
|
||||
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
|
||||
}
|
||||
|
||||
udict->first_available_item = 1;
|
||||
udict->unused_stack_ptr = 0;
|
||||
|
||||
udict->lock = uwsgi_mmap_shared_lock();
|
||||
uwsgi_lock_init(udict->lock);
|
||||
|
||||
return udict;
|
||||
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
|
||||
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
|
||||
}
|
||||
|
||||
uint32_t djb33x_hash(char *key, int keylen) {
|
||||
@@ -258,89 +103,6 @@ uint32_t djb33x_hash(char *key, int keylen) {
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t uwsgi_dict_get_index(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = djb33x_hash(key, keylen);
|
||||
|
||||
int hash_key = hash % 0xffff;
|
||||
|
||||
uint64_t slot = udict->hashtable[hash_key];
|
||||
|
||||
struct uwsgi_dict_item *udi;
|
||||
|
||||
udi = &udict->items[slot];
|
||||
|
||||
// first round
|
||||
if (udi->djbhash != hash) goto cycle;
|
||||
if (udi->keysize != keylen) goto cycle;
|
||||
if (memcmp(udi->key, key, keylen)) goto cycle;
|
||||
|
||||
return slot;
|
||||
|
||||
cycle:
|
||||
while(udi->next) {
|
||||
slot = udi->next;
|
||||
udi = &udict->items[slot];
|
||||
if (udi->djbhash != hash) continue;
|
||||
if (udi->keysize != keylen) continue;
|
||||
if (!memcmp(udi->key, key, keylen)) return slot;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_dict_get(struct uwsgi_dict *udict, char *key, uint16_t keylen, uint64_t *valsize) {
|
||||
|
||||
uint64_t index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
|
||||
if (index) {
|
||||
*valsize = udict->items[index].valsize;
|
||||
udict->items[index].hits++;
|
||||
return udict->data+(index*udict->blocksize);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_dict_del(struct uwsgi_dict *udict, char *key, uint16_t keylen) {
|
||||
|
||||
uint64_t index = 0;
|
||||
struct uwsgi_dict_item *udi;
|
||||
int ret = -1;
|
||||
|
||||
index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
if (index) {
|
||||
udi = &udict->items[index] ;
|
||||
udi->keysize = 0;
|
||||
udi->valsize = 0;
|
||||
udict->unused_stack_ptr++;
|
||||
udict->unused_stack[udict->unused_stack_ptr] = index;
|
||||
// try to return to initial condition...
|
||||
if (index == udict->first_available_item-1) {
|
||||
udict->first_available_item--;
|
||||
}
|
||||
ret = 0;
|
||||
// relink collisioned entry
|
||||
if (udi->prev) {
|
||||
udict->items[udi->prev].next = udi->next;
|
||||
}
|
||||
if (udi->next) {
|
||||
udict->items[udi->next].prev = udi->prev;
|
||||
}
|
||||
if (!udi->prev && !udi->next) {
|
||||
// reset hashtable entry
|
||||
udict->hashtable[udi->djbhash % 0xffff] = 0;
|
||||
}
|
||||
udi->djbhash = 0;
|
||||
udi->prev = 0;
|
||||
udi->next = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
|
||||
uint32_t hash = djb33x_hash(key, keylen);
|
||||
@@ -534,71 +296,6 @@ end:
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
|
||||
|
||||
uint64_t index = 0, last_index = 0 ;
|
||||
|
||||
struct uwsgi_dict_item *udi, *udii;
|
||||
|
||||
int ret = -1;
|
||||
int slot;
|
||||
|
||||
if (!keylen || !vallen) return -1;
|
||||
|
||||
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
|
||||
|
||||
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
|
||||
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
|
||||
goto end;
|
||||
}
|
||||
|
||||
index = uwsgi_dict_get_index(udict, key, keylen);
|
||||
if (!index) {
|
||||
if (udict->unused_stack_ptr) {
|
||||
index = udict->unused_stack[udict->unused_stack_ptr];
|
||||
udict->unused_stack_ptr--;
|
||||
}
|
||||
else {
|
||||
index = udict->first_available_item;
|
||||
if (udict->first_available_item < udict->max_items) {
|
||||
udict->first_available_item++;
|
||||
}
|
||||
}
|
||||
udi = &udict->items[index] ;
|
||||
udi->djbhash = djb33x_hash(key, keylen);
|
||||
udi->hits = 0;
|
||||
memcpy(udi->key, key, keylen);
|
||||
memcpy(udict->data+(index*udict->blocksize), val, vallen);
|
||||
|
||||
// set this as late as possibile (to reduce races risk)
|
||||
|
||||
udi->valsize = vallen;
|
||||
udi->keysize = keylen;
|
||||
ret = 0;
|
||||
// now put the value in the 16bit hashtable
|
||||
slot = udi->djbhash % 0xffff;
|
||||
|
||||
if (udict->hashtable[slot] == 0) {
|
||||
udict->hashtable[slot] = index;
|
||||
}
|
||||
else {
|
||||
// append to first available next
|
||||
last_index = udict->hashtable[slot];
|
||||
udii = &udict->items[ last_index ];
|
||||
while(udii->next) {
|
||||
last_index = udii->next;
|
||||
udii = &udict->items[ last_index ];
|
||||
}
|
||||
udii->next = index;
|
||||
udi->prev = last_index;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
|
||||
|
||||
void *cache_thread_loop(void *fd_ptr) {
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
void cluster_setup() {
|
||||
|
||||
int rlen;
|
||||
// get cluster configuration
|
||||
if (uwsgi.cluster != NULL) {
|
||||
// get multicast socket
|
||||
|
||||
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
|
||||
|
||||
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
|
||||
|
||||
// ask for cluster options only if bot pre-existent options are set
|
||||
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
|
||||
// now wait max 60 seconds and resend multicast request every 10 seconds
|
||||
for (;;) {
|
||||
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
|
||||
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
|
||||
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
|
||||
continue;
|
||||
}
|
||||
waitfd:
|
||||
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
|
||||
uwsgi_configure();
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
goto waitfd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
options_parsed:
|
||||
|
||||
if (!uwsgi.cluster_nodes)
|
||||
uwsgi_cluster_add_me();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
char *tcp_port;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("adding node\n");
|
||||
#endif
|
||||
|
||||
tcp_port = strchr(nucn->name, ':');
|
||||
#ifndef UWSGI_ZEROMQ
|
||||
if (tcp_port == NULL) {
|
||||
#else
|
||||
char *zmq_dash = strchr(nucn->name, '-');
|
||||
if (tcp_port == NULL && zmq_dash == NULL) {
|
||||
#endif
|
||||
|
||||
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// first check for already present node
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0) {
|
||||
if (!strcmp(ucn->name, nucn->name)) {
|
||||
ucn->status = UWSGI_NODE_OK;
|
||||
ucn->last_seen = time(NULL);
|
||||
// update requests
|
||||
ucn->requests = nucn->requests;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
|
||||
if (ucn->name[0] == 0) {
|
||||
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
|
||||
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
|
||||
ucn->workers = nucn->workers;
|
||||
ucn->ucn_addr.sin_family = AF_INET;
|
||||
if (tcp_port) {
|
||||
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
|
||||
tcp_port[0] = 0;
|
||||
}
|
||||
if (nucn->name[0] == 0) {
|
||||
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", nucn->name);
|
||||
#endif
|
||||
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
|
||||
}
|
||||
|
||||
ucn->type = type;
|
||||
// here memory can be freed, as it is allocated by uwsgi_concat2n
|
||||
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
|
||||
tcp_port[0] = ':';
|
||||
}
|
||||
ucn->last_seen = time(NULL);
|
||||
ucn->requests = nucn->requests;
|
||||
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("unable to add node %s\n", nucn->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_cluster_add_me() {
|
||||
|
||||
const char *key1 = "hostname";
|
||||
const char *key2 = "address";
|
||||
const char *key3 = "workers";
|
||||
const char *key4 = "requests";
|
||||
|
||||
char *ptrbuf;
|
||||
uint16_t ustrlen;
|
||||
char numproc[6];
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
char uuid_zmq_str[37];
|
||||
uuid_t uuid_zmq;
|
||||
if (!uwsgi.sockets && !uwsgi.zeromq) {
|
||||
#else
|
||||
if (!uwsgi.sockets) {
|
||||
#endif
|
||||
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(numproc, 6, "%d", uwsgi.numproc);
|
||||
|
||||
size_t len;
|
||||
|
||||
if (uwsgi.sockets) {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uuid_zmq_str);
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
|
||||
}
|
||||
char *buf = uwsgi_malloc(len);
|
||||
|
||||
ptrbuf = buf;
|
||||
|
||||
ustrlen = strlen(key1);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key1, strlen(key1));
|
||||
ptrbuf += strlen(key1);
|
||||
|
||||
ustrlen = strlen(uwsgi.hostname);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
ptrbuf += strlen(uwsgi.hostname);
|
||||
|
||||
|
||||
if (uwsgi.sockets && uwsgi.sockets->name) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uwsgi.sockets->name);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
|
||||
ptrbuf += strlen(uwsgi.sockets->name);
|
||||
}
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (uwsgi.zeromq) {
|
||||
ustrlen = strlen(key2);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key2, strlen(key2));
|
||||
ptrbuf += strlen(key2);
|
||||
|
||||
ustrlen = strlen(uuid_zmq_str);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
|
||||
ptrbuf += strlen(uuid_zmq_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ustrlen = strlen(key3);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key3, strlen(key3));
|
||||
ptrbuf += strlen(key3);
|
||||
|
||||
ustrlen = strlen(numproc);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, numproc, strlen(numproc));
|
||||
ptrbuf += strlen(numproc);
|
||||
|
||||
ustrlen = strlen(key4);
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, key4, strlen(key4));
|
||||
ptrbuf += strlen(key4);
|
||||
|
||||
ustrlen = 1;
|
||||
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
|
||||
memcpy(ptrbuf, "0", 1);
|
||||
ptrbuf += 1;
|
||||
|
||||
|
||||
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
|
||||
|
||||
free(buf);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("add_me() successfull\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cluster_join(char *name) {
|
||||
|
||||
int fd;
|
||||
char *cp;
|
||||
int broadcast = 0;
|
||||
|
||||
|
||||
|
||||
if (name[0] == ':') {
|
||||
fd = bind_to_udp(name, 0, 1);
|
||||
broadcast = 1;
|
||||
}
|
||||
else {
|
||||
fd = bind_to_udp(name, 1, 0);
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
cp = strchr(name, ':');
|
||||
cp[0] = 0;
|
||||
uwsgi.mc_cluster_addr.sin_family = AF_INET;
|
||||
if (broadcast) {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else {
|
||||
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
|
||||
}
|
||||
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
|
||||
cp[0] = ':';
|
||||
|
||||
|
||||
// announce my presence to all the nodes
|
||||
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_cluster_best_node() {
|
||||
|
||||
int i;
|
||||
int best_node = -1;
|
||||
struct uwsgi_cluster_node *ucn;
|
||||
|
||||
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
|
||||
ucn = &uwsgi.shared->nodes[i];
|
||||
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
|
||||
if (best_node == -1) {
|
||||
best_node = i;
|
||||
}
|
||||
else {
|
||||
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
|
||||
best_node = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best_node == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
|
||||
return uwsgi.shared->nodes[best_node].name;
|
||||
}
|
||||
|
||||
|
||||
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
char *tmpstr;
|
||||
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
#endif
|
||||
|
||||
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
|
||||
strncpy(ucn->nodename, val, UMIN(vallen, 255));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("address", 7, key, keylen)) {
|
||||
strncpy(ucn->name, val, UMIN(vallen, 100));
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->workers = atoi(tmpstr);
|
||||
free(tmpstr);
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
|
||||
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
|
||||
ucn->requests = strtoul(tmpstr, NULL, 0);
|
||||
free(tmpstr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
require 'stringio'
|
||||
require 'uwsgidsl'
|
||||
|
||||
|
||||
|
||||
signal 17,'mule5' do |signum|
|
||||
end
|
||||
|
||||
puts UWSGI::VERSION
|
||||
puts UWSGI::NUMPROC
|
||||
puts UWSGI::HOSTNAME
|
||||
|
||||
puts UWSGI::OPT.inspect
|
||||
|
||||
timer 2 do |signum|
|
||||
puts "ciao sono un dsl ruby: #{signum} #{UWSGI::OPT.inspect}"
|
||||
end
|
||||
|
||||
timer 1,'mule1' do |signum|
|
||||
puts "1 second elapsed (signum #{signum})"
|
||||
end
|
||||
|
||||
filemon '/tmp' do |signum|
|
||||
puts "/tmp has been modified"
|
||||
end
|
||||
|
||||
cron 5,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
cron 58,-1,-1,-1,-1 do |signum|
|
||||
puts "cron ready #{signum}"
|
||||
end
|
||||
|
||||
postfork do
|
||||
puts "fork() called"
|
||||
end
|
||||
|
||||
rpc 'pippo' do
|
||||
"i am an rpc function"
|
||||
end
|
||||
|
||||
rpc 'pluto' do |x,y|
|
||||
"i am another rpc function #{x} #{y}"
|
||||
end
|
||||
|
||||
begin
|
||||
foo_func
|
||||
rescue
|
||||
end
|
||||
|
||||
puts UWSGI.cache_exists('nilkey')
|
||||
puts UWSGI.cache_exists?('nilkey')
|
||||
|
||||
UWSGI.cache_set!('foobar_key?a=1', UWSGI::OPT.inspect)
|
||||
begin
|
||||
puts UWSGI.cache_get(nil)
|
||||
rescue
|
||||
end
|
||||
puts UWSGI.cache_get('foobar_key?a=1')
|
||||
|
||||
|
||||
run lambda { |env|
|
||||
puts env.inspect
|
||||
UWSGI.setprocname("i am the uWSGI rack plugin")
|
||||
UWSGI.signal(17)
|
||||
[200, {'Content-Type'=>'text/plain'}, StringIO.new("Hello World! #{UWSGI.mem.inspect}\n")]
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
# uwsgi - Use uwsgi to run python and wsgi web apps.
|
||||
#
|
||||
# chkconfig: - 85 15
|
||||
# description: Use uwsgi to run python and wsgi web apps.
|
||||
# processname: uwsgi
|
||||
|
||||
# author: Roman Vasilyev
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
PATH=/opt/uwsgi:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
prog=/usr/sbin/uwsgi
|
||||
|
||||
OWNER=nginx
|
||||
|
||||
NAME=uwsgi
|
||||
DESC=uwsgi
|
||||
|
||||
#DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/$NAME.pid --pythonpath $PYTHONPATH --module $MODULE"
|
||||
DAEMON_OPTS="-s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 16 -b 32768 -d /var/log/$NAME.log --pidfile /var/run/$NAME.pid --uid $OWNER"
|
||||
|
||||
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
|
||||
|
||||
lockfile=/var/lock/subsys/uwsgi
|
||||
|
||||
start () {
|
||||
echo -n "Starting $DESC: "
|
||||
daemon $prog $DAEMON_OPTS
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
stop () {
|
||||
echo -n "Stopping $DESC: "
|
||||
killproc $prog
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
reload () {
|
||||
echo "Reloading $NAME"
|
||||
killproc $prog -HUP
|
||||
RETVAL=$?
|
||||
echo
|
||||
}
|
||||
|
||||
force-reload () {
|
||||
echo "Reloading $NAME"
|
||||
killproc $prog -TERM
|
||||
RETVAL=$?
|
||||
echo
|
||||
}
|
||||
|
||||
restart () {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
rh_status () {
|
||||
status $prog
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status >/dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
rh_status_q && exit 0
|
||||
$1
|
||||
;;
|
||||
stop)
|
||||
rh_status_q || exit 0
|
||||
$1
|
||||
;;
|
||||
restart|force-reload)
|
||||
$1
|
||||
;;
|
||||
reload)
|
||||
rh_status_q || exit 7
|
||||
$1
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <Python.h>
|
||||
|
||||
void uwsgi_cgi_load_python() {
|
||||
|
||||
Py_Initialize();
|
||||
}
|
||||
|
||||
void uwsgi_cgi_run_python(char *filename) {
|
||||
|
||||
char **e, *p;
|
||||
PyObject *k, *env_value;
|
||||
|
||||
FILE *fp = fopen(filename, "r");
|
||||
|
||||
PySys_SetArgv(1, &filename);
|
||||
|
||||
PyObject *os_module = PyImport_ImportModule("os");
|
||||
if (os_module) {
|
||||
PyObject *os_module_dict = PyModule_GetDict(os_module);
|
||||
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
|
||||
if (py_environ) {
|
||||
for (e = environ; *e != NULL; e++) {
|
||||
p = strchr(*e, '=');
|
||||
if (p == NULL) continue;
|
||||
|
||||
k = PyString_FromStringAndSize(*e, (int)(p-*e));
|
||||
if (k == NULL) {
|
||||
PyErr_Print();
|
||||
continue;
|
||||
}
|
||||
|
||||
env_value = PyString_FromString(p+1);
|
||||
if (env_value == NULL) {
|
||||
PyErr_Print();
|
||||
Py_DECREF(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PyObject_SetItem(py_environ, k, env_value)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
Py_DECREF(k);
|
||||
Py_DECREF(env_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyRun_AnyFileEx(fp, filename, 1);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import mmap
|
||||
import os
|
||||
import struct
|
||||
import array
|
||||
import time
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
class Cache:
|
||||
|
||||
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
|
||||
|
||||
self.block_size = block_size
|
||||
self.cache_slots = cache_slots
|
||||
|
||||
self.key_size = 2048
|
||||
self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
|
||||
self.block_size_start = self.item_size * self.cache_slots
|
||||
|
||||
fd = os.open(filename, os.O_RDONLY)
|
||||
self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
|
||||
|
||||
self.sample_sleep = sample_sleep
|
||||
self.samples = 0
|
||||
self.history = []
|
||||
self.cache_full = 0
|
||||
self.cache_empty = 0
|
||||
self.cache_items = 0
|
||||
self.block_sizes = 0
|
||||
|
||||
def store_read_item_block(self, position):
|
||||
pos = self.cache_store.tell()
|
||||
# uwsgi cache stores cache entries first and then the blocks
|
||||
self.cache_store.seek(self.block_size_start + (position * self.block_size))
|
||||
buf = self.cache_store.read(self.block_size)
|
||||
self.cache_store.seek(pos)
|
||||
return buf
|
||||
|
||||
def store_read_item(self, position):
|
||||
buf = self.cache_store.read(self.item_size)
|
||||
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
|
||||
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
|
||||
|
||||
if [x for x in key if x!= '\x00']:
|
||||
buf = self.store_read_item_block(position)
|
||||
value = array.array('c', buf).tostring().rstrip('\x00')
|
||||
else:
|
||||
value = ''
|
||||
return (position, key, value, len(value))
|
||||
|
||||
def read(self):
|
||||
data = [self.store_read_item(i) for i in range(self.cache_slots)]
|
||||
self.cache_store.seek(0)
|
||||
self.update_stats(data)
|
||||
if self.sample_sleep:
|
||||
time.sleep(self.sample_sleep)
|
||||
return data
|
||||
|
||||
def update_stats(self, data):
|
||||
# data is a list of (position, key, value, len(value)) tuples
|
||||
items = len([1 for x in data if x[3] > 0])
|
||||
self.cache_items += items
|
||||
full, empty = items == self.cache_slots, items == 0
|
||||
if full:
|
||||
self.cache_full += 1
|
||||
if empty:
|
||||
self.cache_empty += 1
|
||||
self.samples += 1
|
||||
block_sizes = sum([x[3] for x in data])
|
||||
self.block_sizes += block_sizes
|
||||
self.history.append({'full': full, 'empty': empty, 'data': data, \
|
||||
'items': items, 'block_sizes': block_sizes})
|
||||
|
||||
def dump(self):
|
||||
return {
|
||||
'samples': self.samples,
|
||||
'history': self.history,
|
||||
'cache_slots': self.cache_slots,
|
||||
'sample_sleep': self.sample_sleep,
|
||||
'cache_empty': self.cache_empty,
|
||||
'cache_full': self.cache_full,
|
||||
'cache_items': self.cache_items,
|
||||
'block_sizes': self.block_sizes,
|
||||
}
|
||||
|
||||
def show_dump(self):
|
||||
d = self.dump()
|
||||
print
|
||||
print "Recorded %d samples (%d second(s) sleep between samples)" % \
|
||||
(d['samples'], d['sample_sleep'])
|
||||
print "Cache empty %d times, full %d times, %.2f items on average" % \
|
||||
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
|
||||
print "Block size average size: %d bytes" % \
|
||||
(d['block_sizes'] / d['cache_items'] * 8)
|
||||
print "Data in cache average: %d bytes" % \
|
||||
(d['block_sizes'] / d['samples'] * 8)
|
||||
|
||||
def main(options):
|
||||
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
|
||||
options.sleep_time)
|
||||
print "Recording..."
|
||||
while True:
|
||||
try:
|
||||
data = cache.read()
|
||||
except KeyboardInterrupt:
|
||||
cache.show_dump()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser()
|
||||
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
|
||||
help="Slots available in the cache, uwsgi cache option")
|
||||
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
|
||||
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
|
||||
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
|
||||
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
|
||||
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
|
||||
help="The time to sleep between each sample. Default: 1")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if not options.cache_slots:
|
||||
parser.error('Option -s / --cache-slots is mandatory')
|
||||
main(options)
|
||||
@@ -171,7 +171,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
|
||||
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
|
||||
@@ -179,7 +179,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid;
|
||||
char **argv;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
@@ -314,7 +314,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
|
||||
if (putenv(ne)) {
|
||||
uwsgi_error("putenv()");
|
||||
@@ -340,9 +342,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
argv[0] = uwsgi.binary_path;
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
@@ -351,29 +353,31 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
}
|
||||
}
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
argv[1] = "--xml";
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
argv[1] = "--ini";
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
argv[1] = "--json";
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
argv[2] = name;
|
||||
vassal_argv[2] = name;
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
argv[counter] = "--inherit";
|
||||
argv[counter+1] = uct->filename;
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->filename;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
argv[counter] = NULL;
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
|
||||
@@ -392,7 +396,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
}
|
||||
|
||||
// start !!!
|
||||
if (execvp(argv[0], argv)) {
|
||||
if (execvp(vassal_argv[0], vassal_argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("is the uwsgi binary in your system PATH ?\n");
|
||||
@@ -510,6 +514,7 @@ reconnect:
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
}
|
||||
globfree(&g);
|
||||
emperor_absolute_dir = realpath(".", NULL);
|
||||
}
|
||||
|
||||
@@ -612,10 +617,8 @@ reconnect:
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.emperor_stats_fd) {
|
||||
emperor_send_stats(uwsgi.emperor_stats_fd);
|
||||
}
|
||||
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1 && interesting_fd == uwsgi.emperor_stats_fd) {
|
||||
emperor_send_stats(uwsgi.emperor_stats_fd);
|
||||
}
|
||||
else {
|
||||
ui_current = emperor_get_by_fd(interesting_fd);
|
||||
@@ -645,7 +648,7 @@ reconnect:
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
|
||||
close(interesting_fd);
|
||||
}
|
||||
@@ -660,7 +663,8 @@ reconnect:
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".ini") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 4), ".yml") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".yaml") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js")
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 3), ".js") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
|
||||
) {
|
||||
|
||||
|
||||
@@ -707,6 +711,7 @@ reconnect:
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".ini") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 4), ".yml") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 3), ".js") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".json") ||
|
||||
!strcmp(g.gl_pathv[i] + (strlen(g.gl_pathv[i]) - 5), ".yaml")
|
||||
) {
|
||||
|
||||
@@ -742,6 +747,7 @@ reconnect:
|
||||
}
|
||||
|
||||
}
|
||||
globfree(&g);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -843,6 +849,7 @@ void emperor_send_stats(int fd) {
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
|
||||
@@ -567,6 +567,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
|
||||
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
return -1;
|
||||
}
|
||||
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#include <sys/inotify.h>
|
||||
|
||||
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
@@ -659,6 +669,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
|
||||
@@ -693,6 +705,8 @@ static int timerfd_create (clockid_t __clock_id, int __flags) {
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
}
|
||||
}
|
||||
|
||||
gw_pid = fork();
|
||||
gw_pid = uwsgi_fork(name);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return NULL;
|
||||
@@ -90,7 +90,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
|
||||
ug->loop = loop;
|
||||
ug->num = num;
|
||||
|
||||
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
|
||||
|
||||
uwsgi.gateways_cnt++;
|
||||
|
||||
@@ -103,7 +103,7 @@ void gateway_respawn(int id) {
|
||||
pid_t gw_pid;
|
||||
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
|
||||
|
||||
gw_pid = fork();
|
||||
gw_pid = uwsgi_fork(ug->name);
|
||||
if (gw_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
@@ -124,10 +124,10 @@ void gateway_respawn(int id) {
|
||||
ug->pid = gw_pid;
|
||||
ug->respawns++;
|
||||
if (ug->respawns == 1) {
|
||||
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
uwsgi_log( "respawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,10 +77,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
|
||||
}
|
||||
else if (json_is_true(config_value)) {
|
||||
add_exported_option((char *)key, (char *) "1", 0);
|
||||
add_exported_option((char *)key, strdup("1"), 0);
|
||||
}
|
||||
else if (json_is_false(config_value) || json_is_null(config_value)) {
|
||||
add_exported_option((char *)key, (char *) "0", 0);
|
||||
add_exported_option((char *)key, strdup("0"), 0);
|
||||
}
|
||||
else if (json_is_integer(config_value)) {
|
||||
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_value)), 0);
|
||||
@@ -92,10 +92,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
add_exported_option((char *)key, (char *) json_string_value(config_array_item), 0);
|
||||
}
|
||||
else if (json_is_true(config_array_item)) {
|
||||
add_exported_option((char *)key, (char *) "1", 0);
|
||||
add_exported_option((char *)key, strdup("1"), 0);
|
||||
}
|
||||
else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
|
||||
add_exported_option((char *)key, (char *) "0", 0);
|
||||
add_exported_option((char *)key, strdup("0"), 0);
|
||||
}
|
||||
else if (json_is_integer(config_array_item)) {
|
||||
add_exported_option((char *)key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#ifndef __u16
|
||||
#define __u16 u_int16_t
|
||||
#endif
|
||||
#ifndef __u32
|
||||
#define __u32 u_int32_t
|
||||
#endif
|
||||
#ifndef __s32
|
||||
#define __s32 int32_t
|
||||
#endif
|
||||
#ifndef __u8
|
||||
#define __u8 u_int8_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
#ifdef UWSGI_LOCK_USE_MUTEX
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
#else
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
|
||||
#endif
|
||||
|
||||
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
@@ -27,15 +32,27 @@ void uwsgi_lock_init(void *lock) {
|
||||
}
|
||||
|
||||
void uwsgi_rlock(void *lock) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock(lock);
|
||||
#else
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_wlock(void *lock) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock(lock);
|
||||
#else
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock(void *lock) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_unlock(lock);
|
||||
#else
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
@@ -51,6 +68,9 @@ void uwsgi_unlock(void *lock) {
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) {
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_init(lock);
|
||||
#else
|
||||
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
|
||||
uwsgi_log("unable to allocate rwlock structure\n");
|
||||
exit(1);
|
||||
@@ -64,6 +84,7 @@ void uwsgi_rwlock_init(void *lock) {
|
||||
uwsgi_log("unable to initialize rwlock\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
@@ -62,6 +63,11 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
@@ -129,22 +135,22 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
rlen = writev(2, logvec, logvecpos+1);
|
||||
}
|
||||
|
||||
void get_memusage() {
|
||||
void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
|
||||
*vsz = syscall(356);
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
@@ -152,8 +158,8 @@ void get_memusage() {
|
||||
procfd = open("/proc/self/psinfo", O_RDONLY);
|
||||
if (procfd >= 0) {
|
||||
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024;
|
||||
*rss = (uint64_t) info.pr_rssize * 1024;
|
||||
*vsz = (uint64_t) info.pr_size * 1024;
|
||||
}
|
||||
close(procfd);
|
||||
}
|
||||
@@ -164,8 +170,8 @@ void get_memusage() {
|
||||
mach_msg_type_number_t t_size = sizeof(struct task_basic_info);
|
||||
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
|
||||
*rss = t_info.resident_size;
|
||||
*vsz = t_info.virtual_size;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
kvm_t *kv;
|
||||
@@ -184,8 +190,8 @@ void get_memusage() {
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kinfo_proc2 *kproc2;
|
||||
@@ -193,11 +199,11 @@ void get_memusage() {
|
||||
kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
|
||||
if (kproc2 && cnt > 0) {
|
||||
#ifdef __OpenBSD__
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
|
||||
#else
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
*vsz = kproc2->p_vm_msize * uwsgi.page_size;
|
||||
#endif
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
*rss = kproc2->p_vm_rssize * uwsgi.page_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -207,13 +213,58 @@ void get_memusage() {
|
||||
area_info ai;
|
||||
int32 cookie;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
*vsz = 0;
|
||||
*rss = 0;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
|
||||
*vsz += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
|
||||
*rss += ai.ram_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_register_logger(char *name, ssize_t (*func)(struct uwsgi_logger *, char *, size_t)) {
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
|
||||
|
||||
if (!ul) {
|
||||
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
ul = uwsgi.loggers;
|
||||
}
|
||||
else {
|
||||
while(ul) {
|
||||
old_ul = ul;
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
old_ul->next = ul;
|
||||
}
|
||||
|
||||
ul->name = name;
|
||||
ul->func = func;
|
||||
ul->next = NULL;
|
||||
ul->configured = 0;
|
||||
ul->fd = -1;
|
||||
ul->data = NULL;
|
||||
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-logger] registered \"%s\"\n", ul->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_logger *uwsgi_get_logger(char *name) {
|
||||
struct uwsgi_logger *ul = uwsgi.loggers;
|
||||
|
||||
while(ul) {
|
||||
if (!strcmp(ul->name, name)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+74
-43
@@ -59,8 +59,10 @@ void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
|
||||
if (uwsgi.shared->mule_queue_pipe[1] != -1) close(uwsgi.shared->mule_queue_pipe[1]);
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
@@ -71,6 +73,15 @@ void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
|
||||
|
||||
if (muleid == 0) {
|
||||
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
|
||||
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -81,22 +92,30 @@ int uwsgi_respawn_worker(int wid) {
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
int i;
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
|
||||
|
||||
if (pid == 0) {
|
||||
signal(SIGWINCH, worker_wakeup);
|
||||
signal(SIGTSTP, worker_wakeup);
|
||||
uwsgi.mywid = wid;
|
||||
uwsgi.mypid = getpid();
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[uwsgi.mywid].requests = 0;
|
||||
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0;
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
|
||||
// do not reset worker counters on reload !!!
|
||||
//uwsgi.workers[uwsgi.mywid].requests = 0;
|
||||
// ...but maintain a delta counter (yes this is racy in multithread)
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
|
||||
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
|
||||
uwsgi.workers[uwsgi.mywid].respawn_count++;
|
||||
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
|
||||
uwsgi.workers[uwsgi.mywid].cheaped = 0;
|
||||
uwsgi.workers[uwsgi.mywid].busy = 0;
|
||||
uwsgi.workers[uwsgi.mywid].suspended = 0;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
|
||||
// reset the apps count with a copy from the master
|
||||
@@ -165,32 +184,26 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (ucron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (ucron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day == -1 && ucron->week == -1) {
|
||||
if (ucron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (ucron->day == -1) {
|
||||
ucron->day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
else if (ucron->week == -1) {
|
||||
ucron->week = uwsgi_cron_delta->tm_wday;
|
||||
if (ucron->day != -1 && ucron->week != -1) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ucron->day == uwsgi_cron_delta->tm_mday) {
|
||||
ucron->week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
|
||||
ucron->day = uwsgi_cron_delta->tm_mday;
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (uwsgi.current_time - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
@@ -238,31 +251,26 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
if (current_cron->month == -1)
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
if (current_cron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day == -1 && current_cron->week == -1) {
|
||||
if (current_cron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (current_cron->day == -1) {
|
||||
current_cron->day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
else if (current_cron->week == -1) {
|
||||
current_cron->week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else {
|
||||
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
|
||||
current_cron->week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
|
||||
current_cron->day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day != -1 && current_cron->week != -1) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (uwsgi.current_time - current_cron->last_job > 60) {
|
||||
@@ -312,6 +320,9 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
|
||||
#endif
|
||||
|
||||
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
|
||||
|
||||
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
@@ -319,6 +330,22 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
if (uwsgi.daemons) {
|
||||
fprintf(output, "\"daemons\": [\n");
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while(ud) {
|
||||
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }",
|
||||
ud->command, (int) ud->pid, (unsigned long long) ud->respawns-1);
|
||||
if (ud->next)
|
||||
fprintf(output, ",\n");
|
||||
else {
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
fprintf(output, "],\n");
|
||||
}
|
||||
|
||||
fprintf(output, "\"workers\": [\n");
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
@@ -327,12 +354,16 @@ void uwsgi_send_stats(int fd) {
|
||||
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
|
||||
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
|
||||
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
|
||||
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i+1].delta_requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
|
||||
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output,"\"status\": \"cheap\", ");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended) {
|
||||
fprintf(output,"\"status\": \"pause\", ");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
|
||||
@@ -12,11 +12,29 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_mule_handler(void);
|
||||
|
||||
void mule_send_msg(int fd, char *message, size_t len) {
|
||||
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
int so_bufsize = 0;
|
||||
|
||||
if (write(fd, message, len) != (ssize_t) len) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("getsockopt()");
|
||||
}
|
||||
uwsgi_log("*** MULE MSG QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("mule_send_msg()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t pid = uwsgi_fork(uwsgi.mules[id-1].name);
|
||||
if (pid == 0) {
|
||||
uwsgi.muleid = id;
|
||||
// avoid race conditions
|
||||
@@ -44,10 +62,10 @@ void uwsgi_mule(int id) {
|
||||
|
||||
|
||||
if (uwsgi.mules[id-1].patch) {
|
||||
uwsgi_log("loading patch %s\n", uwsgi.mules[id-1].patch);
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
|
||||
// never here
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +81,64 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
|
||||
|
||||
struct uwsgi_mule_farm *umf = farm->mules;
|
||||
|
||||
while(umf) {
|
||||
if (umf->mule->id == muleid) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_signaled(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].signal_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int farm_has_msg(int fd) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
struct uwsgi_mule_farm *umf = uwsgi.farms[i].mules;
|
||||
while(umf) {
|
||||
if (umf->mule->id == uwsgi.muleid && uwsgi.farms[i].queue_pipe[1] == fd) {
|
||||
return 1;
|
||||
}
|
||||
umf = umf->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_mule_add_farm_to_queue(int queue) {
|
||||
|
||||
int i;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].signal_pipe[1]);
|
||||
event_queue_add_fd_read(queue, uwsgi.farms[i].queue_pipe[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_mule_handler() {
|
||||
|
||||
ssize_t len;
|
||||
@@ -78,6 +154,9 @@ void uwsgi_mule_handler() {
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.my_signal_socket);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]);
|
||||
event_queue_add_fd_read(mule_queue, uwsgi.shared->mule_queue_pipe[1]);
|
||||
|
||||
uwsgi_mule_add_farm_to_queue(mule_queue);
|
||||
|
||||
for(;;) {
|
||||
rlen = event_queue_wait(mule_queue, -1, &interesting_fd);
|
||||
@@ -85,7 +164,7 @@ void uwsgi_mule_handler() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket) {
|
||||
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
@@ -95,21 +174,185 @@ void uwsgi_mule_handler() {
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
}
|
||||
}
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1]) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, 65536);
|
||||
else if (interesting_fd == uwsgi.mules[uwsgi.muleid-1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
|
||||
len = read(interesting_fd, message, 65536);
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else if (len == 0) {
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("*** mule %d received a %d bytes message\n", uwsgi.muleid, len);
|
||||
int i,found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
if (uwsgi.p[i]->mule_msg) {
|
||||
if (uwsgi.p[i]->mule_msg(message, len)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_mule *get_mule_by_id(int id) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (uwsgi.mules[i].id == id) {
|
||||
return &uwsgi.mules[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_farm *get_farm_by_name(char *name) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (!strcmp(uwsgi.farms[i].name, name)) {
|
||||
return &uwsgi.farms[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **umf, struct uwsgi_mule *um) {
|
||||
|
||||
struct uwsgi_mule_farm *uwsgi_mf = *umf, *old_umf;
|
||||
|
||||
if (!uwsgi_mf) {
|
||||
*umf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
uwsgi_mf = *umf;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_mf) {
|
||||
old_umf = uwsgi_mf;
|
||||
uwsgi_mf = uwsgi_mf->next;
|
||||
}
|
||||
|
||||
uwsgi_mf = uwsgi_malloc(sizeof(struct uwsgi_mule_farm));
|
||||
old_umf->next = uwsgi_mf;
|
||||
}
|
||||
|
||||
uwsgi_mf->mule = um;
|
||||
uwsgi_mf->next = NULL;
|
||||
|
||||
return uwsgi_mf;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_mule_get_msg(int manage_signals, int manage_farms, char *message, size_t buffer_size, int timeout) {
|
||||
|
||||
ssize_t len = 0;
|
||||
struct pollfd *mulepoll;
|
||||
int count = 4;
|
||||
int farms_count = 0;
|
||||
uint8_t uwsgi_signal;
|
||||
int i;
|
||||
|
||||
if (uwsgi.muleid == 0) return -1;
|
||||
|
||||
if (manage_signals) count = 2;
|
||||
|
||||
if (!manage_farms) goto next;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) farms_count++;
|
||||
}
|
||||
next:
|
||||
|
||||
if (timeout > -1) timeout = timeout*1000;
|
||||
|
||||
mulepoll = uwsgi_malloc(sizeof(struct pollfd) * (count+farms_count));
|
||||
|
||||
mulepoll[0].fd = uwsgi.mules[uwsgi.muleid-1].queue_pipe[1];
|
||||
mulepoll[0].events = POLLIN;
|
||||
mulepoll[1].fd = uwsgi.shared->mule_queue_pipe[1];
|
||||
mulepoll[1].events = POLLIN;
|
||||
if (count > 2) {
|
||||
mulepoll[2].fd = uwsgi.signal_socket;
|
||||
mulepoll[2].events = POLLIN;
|
||||
mulepoll[3].fd = uwsgi.my_signal_socket;
|
||||
mulepoll[3].events = POLLIN;
|
||||
}
|
||||
|
||||
if (farms_count > 0) {
|
||||
int tmp_cnt = 0;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
mulepoll[count+tmp_cnt].fd = uwsgi.farms[i].queue_pipe[1];
|
||||
mulepoll[count+tmp_cnt].events = POLLIN;
|
||||
tmp_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = poll(mulepoll, count+farms_count, timeout);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll");
|
||||
}
|
||||
else {
|
||||
if (mulepoll[0].revents & POLLIN) {
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else if (mulepoll[1].revents & POLLIN) {
|
||||
len = read(uwsgi.shared->mule_queue_pipe[1], message, buffer_size);
|
||||
}
|
||||
else {
|
||||
if (count > 2) {
|
||||
int interesting_fd = -1;
|
||||
if (mulepoll[2].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[2].fd;
|
||||
}
|
||||
else if (mulepoll[3].revents & POLLIN) {
|
||||
interesting_fd = mulepoll[3].fd;
|
||||
}
|
||||
|
||||
if (interesting_fd > -1) {
|
||||
len = read(interesting_fd, &uwsgi_signal, 1);
|
||||
if (len <= 0) {
|
||||
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
|
||||
end_me(0);
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
// set the error condition
|
||||
len = -1;
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
// read messages in the farm
|
||||
for(i=0;i<farms_count;i++) {
|
||||
if (mulepoll[count+i].revents & POLLIN) {
|
||||
len = read(mulepoll[count+i].fd, message, buffer_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
clear:
|
||||
free(mulepoll);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from uwsgidecorators import *
|
||||
|
||||
@timer(3, target='mule1')
|
||||
def hello_timer(signum):
|
||||
print "3 seconds elapsed"
|
||||
|
||||
|
||||
@mulefunc
|
||||
def conto_fino_a_dieci(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_dieci" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc(2)
|
||||
def conto_fino_a_venti(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_venti" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
@mulefunc('topogigio')
|
||||
def conto_fino_a_trenta(uno, due, tre):
|
||||
print "MULE ID %d: conto_fino_a_trenta" % uwsgi.mule_id(),uno,due,tre
|
||||
|
||||
|
||||
|
||||
def application(e, sr):
|
||||
conto_fino_a_dieci(1,2,3)
|
||||
conto_fino_a_venti(4,5,6)
|
||||
conto_fino_a_trenta(7,8,9)
|
||||
sr('200 OK', [('Content-Type','text/html')])
|
||||
return "MULE !!!"
|
||||
@@ -94,7 +94,9 @@ check:
|
||||
linkpath_buf[linkpath_size] = '\0';
|
||||
strcpy(linkpath, linkpath_buf);
|
||||
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s\n", linkpath);
|
||||
#endif
|
||||
free(plugin_entry_symbol);
|
||||
up = dlsym(plugin_handle, plugin_entry_symbol);
|
||||
char *slash = uwsgi_get_last_char(linkpath, '/');
|
||||
@@ -139,6 +141,9 @@ check:
|
||||
}
|
||||
free(plugin_name);
|
||||
free(plugin_entry_symbol);
|
||||
|
||||
if (up->on_load)
|
||||
up->on_load();
|
||||
return plugin_handle;
|
||||
}
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
|
||||
Vendored
+3
-2
@@ -34,6 +34,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
uint64_t vallen = 0;
|
||||
char *value;
|
||||
char *argv[3];
|
||||
uint16_t argvs[3];
|
||||
uint8_t argc = 0;
|
||||
|
||||
switch(wsgi_req->uh.modifier2) {
|
||||
@@ -52,9 +53,9 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
// set
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
argc = 3;
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
|
||||
if (argc > 1) {
|
||||
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
|
||||
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define CARBON_OPT_BASE 178000
|
||||
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
|
||||
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
|
||||
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
|
||||
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
|
||||
|
||||
struct uwsgi_carbon {
|
||||
struct uwsgi_string_list *servers;
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
} u_carbon;
|
||||
|
||||
struct option carbon_options[] = {
|
||||
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
|
||||
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
|
||||
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
|
||||
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
int carbon_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carbon_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case CARBON_OPT_CARBON:
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi_string_new_list(&u_carbon.servers, optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_ID:
|
||||
u_carbon.id = optarg;
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_FREQ:
|
||||
u_carbon.freq = atoi(optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_TIMEOUT:
|
||||
u_carbon.timeout = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void carbon_post_init() {
|
||||
|
||||
int i;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
if (!uwsgi.sockets) return;
|
||||
if (!u_carbon.servers) return;
|
||||
|
||||
while(usl) {
|
||||
uwsgi_log("added carbon server %s\n", usl->value);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (u_carbon.freq < 1) u_carbon.freq = 60;
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
if (u_carbon.id[i] == '.') u_carbon.id[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void carbon_master_cycle() {
|
||||
|
||||
static time_t last_update = 0;
|
||||
char ptr[4096];
|
||||
int rlen, i;
|
||||
int fd;
|
||||
struct uwsgi_string_list *usl = u_carbon.servers;
|
||||
|
||||
if (!u_carbon.servers) return ;
|
||||
|
||||
if (last_update == 0) last_update = time(NULL);
|
||||
|
||||
// update
|
||||
if (uwsgi.current_time - last_update >= u_carbon.freq) {
|
||||
while(usl) {
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
if (fd < 0) goto nxt;
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
clear:
|
||||
close(fd);
|
||||
nxt:
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin carbon_plugin = {
|
||||
|
||||
.options = carbon_options,
|
||||
.manage_opt = carbon_opt,
|
||||
|
||||
.master_cycle = carbon_master_cycle,
|
||||
|
||||
.post_init = carbon_post_init,
|
||||
.init = carbon_init,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='carbon'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['carbon']
|
||||
+790
-29
@@ -1,27 +1,446 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include <wordexp.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *cgi_docroot;
|
||||
struct uwsgi_cgi {
|
||||
struct uwsgi_dyn_dict *mountpoint;
|
||||
struct uwsgi_dyn_dict *helpers;
|
||||
int buffer_size;
|
||||
int timeout;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *unset;
|
||||
struct uwsgi_string_list *loadlib;
|
||||
int optimize;
|
||||
int has_mountpoints;
|
||||
struct uwsgi_dyn_dict *default_cgi;
|
||||
int path_info;
|
||||
} uc ;
|
||||
|
||||
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 100)
|
||||
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
|
||||
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
|
||||
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
|
||||
#define LONG_ARGS_CGI_MAP_HELPER LONG_ARGS_CGI_BASE + 2
|
||||
#define LONG_ARGS_CGI_BUFFER_SIZE LONG_ARGS_CGI_BASE + 3
|
||||
#define LONG_ARGS_CGI_TIMEOUT LONG_ARGS_CGI_BASE + 4
|
||||
#define LONG_ARGS_CGI_INDEX LONG_ARGS_CGI_BASE + 5
|
||||
#define LONG_ARGS_CGI_ALLOWED_EXT LONG_ARGS_CGI_BASE + 6
|
||||
#define LONG_ARGS_CGI_UNSET LONG_ARGS_CGI_BASE + 7
|
||||
#define LONG_ARGS_CGI_LOADLIB LONG_ARGS_CGI_BASE + 8
|
||||
|
||||
struct option uwsgi_cgi_options[] = {
|
||||
|
||||
{"cgi", required_argument, 0, LONG_ARGS_CGI},
|
||||
{"cgi-map-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
|
||||
{"cgi-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
|
||||
{"cgi-buffer-size", required_argument, 0, LONG_ARGS_CGI_BUFFER_SIZE},
|
||||
{"cgi-timeout", required_argument, 0, LONG_ARGS_CGI_TIMEOUT},
|
||||
{"cgi-index", required_argument, 0, LONG_ARGS_CGI_INDEX},
|
||||
{"cgi-allowed-ext", required_argument, 0, LONG_ARGS_CGI_ALLOWED_EXT},
|
||||
{"cgi-unset", required_argument, 0, LONG_ARGS_CGI_UNSET},
|
||||
{"cgi-loadlib", required_argument, 0, LONG_ARGS_CGI_LOADLIB},
|
||||
{"cgi-optimize", no_argument, &uc.optimize, 1},
|
||||
{"cgi-optimized", no_argument, &uc.optimize, 1},
|
||||
{"cgi-path-info", no_argument, &uc.path_info, 1},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_cgi_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
|
||||
}
|
||||
|
||||
void uwsgi_cgi_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_cgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[6];
|
||||
|
||||
wsgi_req->status = 301;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 301 Moved Permanently\r\n";
|
||||
iov[1].iov_len = 24;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
|
||||
iov[0].iov_base = "Location: ";
|
||||
iov[0].iov_len = 10;
|
||||
iov[1].iov_base = wsgi_req->path_info;
|
||||
iov[1].iov_len = wsgi_req->path_info_len;
|
||||
iov[2].iov_base = "/";
|
||||
iov[2].iov_len = 1;
|
||||
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
iov[3].iov_base = "?";
|
||||
iov[3].iov_len = 1;
|
||||
iov[4].iov_base = wsgi_req->query_string;
|
||||
iov[4].iov_len = wsgi_req->query_string_len;
|
||||
iov[5].iov_base = "\r\n\r\n";
|
||||
iov[5].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
else {
|
||||
iov[3].iov_base = "\r\n\r\n";
|
||||
iov[3].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_cgi_apps() {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint;
|
||||
struct stat st;
|
||||
|
||||
while(udd) {
|
||||
if (udd->vallen) {
|
||||
if (uc.optimize) {
|
||||
udd->value = realpath(udd->value, NULL);
|
||||
if (!udd->value) {
|
||||
uwsgi_log("unable to find CGI path %.*s\n", udd->vallen, udd->value);
|
||||
exit(1);
|
||||
}
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1;
|
||||
if (stat(udd->value, &st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("something horrible happened during CGI initialization\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
udd->status = 2;
|
||||
}
|
||||
}
|
||||
uc.has_mountpoints = 1;
|
||||
uwsgi_log("initialized CGI mountpoint: %.*s = %.*s\n", udd->keylen, udd->key, udd->vallen, udd->value);
|
||||
}
|
||||
else {
|
||||
if (uc.optimize) {
|
||||
udd->key = realpath(udd->key, NULL);
|
||||
if (!udd->key) {
|
||||
uwsgi_log("unable to find CGI path %.*s\n", udd->keylen, udd->key);
|
||||
exit(1);
|
||||
}
|
||||
udd->keylen = strlen(udd->key);
|
||||
udd->status = 1;
|
||||
|
||||
if (stat(udd->key, &st)) {
|
||||
uwsgi_error("stat()");
|
||||
uwsgi_log("something horrible happened during CGI initialization\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
udd->status = 2;
|
||||
}
|
||||
|
||||
}
|
||||
uwsgi_log("initialized CGI path: %.*s\n", udd->keylen, udd->key);
|
||||
uc.default_cgi = udd;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_init(){
|
||||
|
||||
void (*cgi_sym)(void);
|
||||
|
||||
uwsgi_log("initialized CGI engine\n");
|
||||
if (!uc.buffer_size) uc.buffer_size = 65536;
|
||||
if (!uc.timeout) uc.timeout = 60;
|
||||
|
||||
struct uwsgi_string_list *ll = uc.loadlib;
|
||||
while(ll) {
|
||||
char *colon = strchr(ll->value, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid cgi-loadlib syntax, must be in the form lib:func\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
void *cgi_lib = dlopen(ll->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!cgi_lib) {
|
||||
uwsgi_log( "cgi-loadlib: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cgi_sym = dlsym(cgi_lib, colon+1);
|
||||
if (!cgi_sym) {
|
||||
uwsgi_log("unknown symbol %s in lib %s\n", colon+1, ll->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cgi_sym();
|
||||
uwsgi_log("[cgi-loadlib] loaded symbol %s from %s\n", colon+1, ll->value);
|
||||
|
||||
*colon = ':';
|
||||
ll = ll->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_helper(char *filename) {
|
||||
|
||||
struct uwsgi_dyn_dict *helpers = uc.helpers;
|
||||
size_t len = strlen(filename);
|
||||
|
||||
while(helpers) {
|
||||
if (len >= (size_t) helpers->keylen) {
|
||||
if (!uwsgi_strncmp((filename+len)-helpers->keylen, helpers->keylen, helpers->key, helpers->keylen)) {
|
||||
return helpers->value;
|
||||
}
|
||||
}
|
||||
helpers = helpers->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
size_t i;
|
||||
char *key = buf, *value = NULL;
|
||||
size_t header_size = 0;
|
||||
int status_sent = 0;
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
|
||||
struct iovec iov[4];
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
// end of a line
|
||||
if (buf[i] == '\n') {
|
||||
// end of headers
|
||||
if (key == NULL) {
|
||||
goto send_body;
|
||||
}
|
||||
// invalid header
|
||||
else if (value == NULL) {
|
||||
return -1;
|
||||
}
|
||||
header_size = (buf+i) - key;
|
||||
// security check
|
||||
if (buf+i > buf) {
|
||||
if ((buf[i-1]) == '\r') {
|
||||
header_size--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found CGI header: %.*s\n", header_size, key);
|
||||
#endif
|
||||
|
||||
if (status_sent == 0) {
|
||||
// "Status: NNN"
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Status: ", key, 8)) {
|
||||
wsgi_req->status = uwsgi_str3_num(key+8);
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
iov[2].iov_base = key+8;
|
||||
iov[2].iov_len = header_size - 8;
|
||||
iov[3].iov_base = "\r\n";
|
||||
iov[3].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
status_sent = 1;
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default status
|
||||
if (status_sent == 0) {
|
||||
|
||||
// Location: X
|
||||
if (header_size >= 11) {
|
||||
if (!strncasecmp("Location: ", key, 10)) {
|
||||
|
||||
wsgi_req->status = 302;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 302 Found\r\n";
|
||||
iov[1].iov_len = 12;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (status_sent == 0) {
|
||||
wsgi_req->status = 200;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 200 OK\r\n";
|
||||
iov[1].iov_len = 9;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
status_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
iov[0].iov_base = key;
|
||||
iov[0].iov_len = header_size;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
key = NULL;
|
||||
value = NULL;
|
||||
}
|
||||
else if (buf[i] == ':') {
|
||||
value = buf+i;
|
||||
}
|
||||
else if (buf[i] != '\r') {
|
||||
if (key == NULL) {
|
||||
key = buf + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
send_body:
|
||||
|
||||
while(ah) {
|
||||
iov[0].iov_base = ah->value;
|
||||
iov[0].iov_len = ah->len;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
if (len-i > 0) {
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, buf+i, len-i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
|
||||
int best_found = 0;
|
||||
struct stat st;
|
||||
char *path = NULL;
|
||||
|
||||
if (uc.has_mountpoints) {
|
||||
while(udd) {
|
||||
if (udd->vallen) {
|
||||
if (!uwsgi_starts_with(path_info, path_info_len, udd->key, udd->keylen) && udd->keylen > best_found) {
|
||||
best_found = udd->keylen ;
|
||||
choosen_udd = udd;
|
||||
path = udd->value;
|
||||
*script_name = udd->key;
|
||||
*discard_base = udd->keylen;
|
||||
if (udd->key[udd->keylen-1] == '/') {
|
||||
*discard_base = *discard_base-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (choosen_udd == NULL) {
|
||||
choosen_udd = uc.default_cgi;
|
||||
if (!choosen_udd) return NULL;
|
||||
path = choosen_udd->key;
|
||||
}
|
||||
|
||||
if (choosen_udd->status == 0) {
|
||||
char *tmp_udd = realpath(path, NULL);
|
||||
if (!tmp_udd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stat(tmp_udd, &st)) {
|
||||
uwsgi_error("stat()");
|
||||
free(tmp_udd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
*is_a_file = 1;
|
||||
}
|
||||
|
||||
*need_free = 1;
|
||||
return tmp_udd;
|
||||
}
|
||||
|
||||
if (choosen_udd->status == 2)
|
||||
*is_a_file = 1;
|
||||
return path;
|
||||
}
|
||||
|
||||
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
char *ptr = wsgi_req->path_info+discard_base;
|
||||
char *dst = full_path+docroot_len;
|
||||
char *part = ptr;
|
||||
int part_size = 0;
|
||||
struct stat st;
|
||||
|
||||
if (ptr[0] == '/') part_size++;
|
||||
|
||||
for(i=0;i<wsgi_req->path_info_len-discard_base;i++) {
|
||||
if (ptr[i] == '/') {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
|
||||
if (stat(full_path, &st)) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// not a directory, stop walking
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (i < (wsgi_req->path_info_len-discard_base)-1) {
|
||||
*path_info = ptr + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// check for buffer overflow !!!
|
||||
*(dst+part_size-1) = '/';
|
||||
*(dst+part_size) = 0;
|
||||
|
||||
dst += part_size ;
|
||||
part_size = 0;
|
||||
part = ptr + i + 1;
|
||||
}
|
||||
|
||||
part_size++;
|
||||
}
|
||||
|
||||
if (part < wsgi_req->path_info+wsgi_req->path_info_len) {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +449,21 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
int i;
|
||||
pid_t cgi_pid;
|
||||
int waitpid_status;
|
||||
char *argv[2];
|
||||
char *argv[3];
|
||||
char full_path[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
int cgi_pipe[2];
|
||||
ssize_t len;
|
||||
struct stat cgi_stat;
|
||||
int need_free = 0;
|
||||
int is_a_file = 0;
|
||||
int discard_base = 0;
|
||||
size_t docroot_len = 0;
|
||||
size_t full_path_len = 0;
|
||||
char *helper = NULL;
|
||||
char *command = NULL;
|
||||
char *path_info = NULL;
|
||||
char *script_name = NULL;
|
||||
|
||||
/* Standard CGI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
@@ -41,48 +473,251 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
uwsgi_log("Invalid CGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check for file availability (and 'runnability')
|
||||
|
||||
char *docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
|
||||
if (docroot == NULL) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
docroot_len = strlen(docroot);
|
||||
memcpy(full_path, docroot, docroot_len);
|
||||
|
||||
if (!is_a_file) {
|
||||
|
||||
*(full_path+docroot_len) = '/';
|
||||
*(full_path+docroot_len+1) = 0;
|
||||
|
||||
if (uwsgi_cgi_walk(wsgi_req, full_path, docroot, docroot_len, discard_base, &path_info)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (realpath(full_path, tmp_path) == NULL) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
full_path_len = strlen(tmp_path);
|
||||
// add +1 to copy the null byte
|
||||
memcpy(full_path, tmp_path, full_path_len+1);
|
||||
|
||||
if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
*(full_path+docroot_len) = 0;
|
||||
path_info = wsgi_req->path_info+discard_base;
|
||||
}
|
||||
|
||||
if (stat(full_path, &cgi_stat)) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (S_ISDIR(cgi_stat.st_mode)) {
|
||||
|
||||
// add / to directories
|
||||
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
|
||||
uwsgi_cgi_redirect_to_slash(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
struct uwsgi_string_list *ci = uc.index;
|
||||
full_path[full_path_len] = '/';
|
||||
full_path_len++;
|
||||
int found = 0;
|
||||
while(ci) {
|
||||
if (full_path_len + ci->len + 1 < PATH_MAX) {
|
||||
// add + 1 to ensure null byte
|
||||
memcpy(full_path+full_path_len, ci->value, ci->len + 1);
|
||||
if (!access(full_path, R_OK)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ci = ci->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_cgi_404(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
full_path_len = strlen(full_path);
|
||||
}
|
||||
|
||||
int cgi_allowed = 1;
|
||||
struct uwsgi_string_list *allowed = uc.allowed_ext;
|
||||
while(allowed) {
|
||||
cgi_allowed = 0;
|
||||
if (full_path_len >= allowed->len) {
|
||||
if (!uwsgi_strncmp(full_path+(full_path_len-allowed->len), allowed->len, allowed->value, allowed->len)) {
|
||||
cgi_allowed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
allowed = allowed->next;
|
||||
}
|
||||
|
||||
if (!cgi_allowed) {
|
||||
uwsgi_cgi_403(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
command = docroot;
|
||||
}
|
||||
else {
|
||||
command = full_path;
|
||||
helper = uwsgi_cgi_get_helper(full_path);
|
||||
|
||||
if (helper == NULL) {
|
||||
if (access(full_path, X_OK)) {
|
||||
uwsgi_error("access()");
|
||||
uwsgi_cgi_403(wsgi_req);
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pipe(cgi_pipe)) {
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
uwsgi_error("pipe()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
cgi_pid = fork();
|
||||
|
||||
if (cgi_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cgi_pid > 0) {
|
||||
// close input
|
||||
close(wsgi_req->poll.fd);
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
// now wait for fd
|
||||
if (waitpid(cgi_pid, &waitpid_status ,0) > 0) {
|
||||
uwsgi_log("CGI FINISHED\n");
|
||||
if (need_free)
|
||||
free(docroot);
|
||||
|
||||
close(cgi_pipe[1]);
|
||||
// wait for data
|
||||
char *headers_buf = uwsgi_malloc(uc.buffer_size);
|
||||
char *ptr = headers_buf;
|
||||
size_t remains = uc.buffer_size;
|
||||
int completed = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], ptr, remains);
|
||||
if (len > 0) {
|
||||
ptr+=len;
|
||||
remains -= len;
|
||||
}
|
||||
else if (len == 0) {
|
||||
completed = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
uwsgi_log("CGI timeout !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (uwsgi_cgi_parse(wsgi_req, headers_buf, uc.buffer_size-remains)) {
|
||||
uwsgi_log("invalid CGI output !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
while (!completed) {
|
||||
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
|
||||
if (ret > 0) {
|
||||
len = read(cgi_pipe[0], headers_buf, uc.buffer_size);
|
||||
if (len > 0) {
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, headers_buf, len);
|
||||
}
|
||||
// end of output
|
||||
else if (len == 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
uwsgi_log("CGI timeout !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
clear:
|
||||
free(headers_buf);
|
||||
close(cgi_pipe[0]);
|
||||
|
||||
// now wait for process exit/death
|
||||
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// close all the fd except wsgi_req->poll.fd and 2;
|
||||
|
||||
for(i=0;i< (int)uwsgi.max_fd;i++) {
|
||||
if (i != wsgi_req->poll.fd && i != 2) {
|
||||
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[1]) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
|
||||
// now map wsgi_req->poll.fd to 0 && 1
|
||||
// now map wsgi_req->poll.fd to 0 & cgi_pipe[1] to 1
|
||||
if (wsgi_req->poll.fd != 0) {
|
||||
dup2(wsgi_req->poll.fd, 0);
|
||||
close(wsgi_req->poll.fd);
|
||||
}
|
||||
|
||||
dup2(0,1);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
|
||||
#endif
|
||||
|
||||
dup2(cgi_pipe[1],1);
|
||||
|
||||
// fill cgi env
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
// no need to free the putenv() memory
|
||||
@@ -92,19 +727,110 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
i++;
|
||||
}
|
||||
|
||||
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
|
||||
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
|
||||
|
||||
argv[0] = full_path;
|
||||
argv[1] = NULL;
|
||||
if (execv(argv[0], argv)) {
|
||||
uwsgi_error("execv()");
|
||||
if (setenv("GATEWAY_INTERFACE", "CGI/1.1", 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("SERVER_SOFTWARE", uwsgi_concat2("uWSGI/", UWSGI_VERSION), 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
// for newer php
|
||||
if (setenv("REDIRECT_STATUS", "200", 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (path_info && wsgi_req->path_info_len-discard_base > 0) {
|
||||
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, wsgi_req->path_info_len-discard_base, "", 0), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("PATH_TRANSLATED", uwsgi_concat4n(docroot, docroot_len, "/", 1, path_info, wsgi_req->path_info_len-discard_base, "", 0) , 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsetenv("PATH_INFO");
|
||||
unsetenv("PATH_TRANSLATED");
|
||||
}
|
||||
|
||||
if (is_a_file) {
|
||||
if (setenv("DOCUMENT_ROOT", uwsgi.cwd, 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("SCRIPT_FILENAME", docroot, 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (script_name && discard_base > 1) {
|
||||
if (setenv("SCRIPT_NAME", uwsgi_concat2n(script_name, discard_base, "", 0), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (setenv("DOCUMENT_ROOT", docroot, 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("SCRIPT_FILENAME", full_path, 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
if (setenv("SCRIPT_NAME", full_path+(docroot_len-discard_base), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
char *base = uwsgi_get_last_char(full_path, '/');
|
||||
if (base) {
|
||||
// a little trick :P
|
||||
*base = 0;
|
||||
if (chdir(full_path)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
*base = '/';
|
||||
}
|
||||
else {
|
||||
if (chdir(docroot)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *drop_env = uc.unset;
|
||||
while(drop_env) {
|
||||
unsetenv(drop_env->value);
|
||||
drop_env = drop_env->next;
|
||||
}
|
||||
|
||||
if (helper) {
|
||||
if (!uwsgi_starts_with(helper, strlen(helper), "sym://", 6)) {
|
||||
void (*cgi_func)(char *) = dlsym(RTLD_DEFAULT, helper+6);
|
||||
if (cgi_func) {
|
||||
cgi_func(command);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unable to find symbol %s\n", helper+6);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
argv[0] = helper;
|
||||
argv[1] = command;
|
||||
argv[2] = NULL;
|
||||
}
|
||||
else {
|
||||
argv[0] = command;
|
||||
argv[1] = NULL;
|
||||
}
|
||||
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
|
||||
// never here
|
||||
exit(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,10 +842,44 @@ void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int uwsgi_cgi_manage_options(int i, char *optarg) {
|
||||
|
||||
char *value;
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_CGI:
|
||||
cgi_docroot = optarg;
|
||||
value = strchr(optarg, '=');
|
||||
if (!value) {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, strlen(optarg), NULL, 0);
|
||||
}
|
||||
else {
|
||||
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, value-optarg, value+1, strlen(value+1));
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_BUFFER_SIZE:
|
||||
uc.buffer_size = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_TIMEOUT:
|
||||
uc.timeout = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_INDEX:
|
||||
uwsgi_string_new_list(&uc.index, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_ALLOWED_EXT:
|
||||
uwsgi_string_new_list(&uc.allowed_ext, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_LOADLIB:
|
||||
uwsgi_string_new_list(&uc.loadlib, uwsgi_str(optarg));
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_UNSET:
|
||||
uwsgi_string_new_list(&uc.unset, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_CGI_MAP_HELPER:
|
||||
value = strchr(optarg, '=');
|
||||
if (!value) {
|
||||
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_dyn_dict_new(&uc.helpers, optarg, value-optarg, value+1, strlen(value+1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -131,6 +891,7 @@ struct uwsgi_plugin cgi_plugin = {
|
||||
.name = "cgi",
|
||||
.modifier1 = 9,
|
||||
.init = uwsgi_cgi_init,
|
||||
.init_apps = uwsgi_cgi_apps,
|
||||
.options = uwsgi_cgi_options,
|
||||
.manage_opt = uwsgi_cgi_manage_options,
|
||||
.request = uwsgi_cgi_request,
|
||||
|
||||
@@ -40,7 +40,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
fc = new FakeClass();
|
||||
// get PATH_INFO
|
||||
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", &fc->foobar_len);
|
||||
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", 9, &fc->foobar_len);
|
||||
|
||||
if (fc->foobar) {
|
||||
// send output
|
||||
|
||||
+31
-28
@@ -94,8 +94,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
char *call;
|
||||
char buffer[0xffff];
|
||||
|
||||
char *argv[0xff] ;
|
||||
int argc;
|
||||
char *argv[256] ;
|
||||
uint16_t argvs[256] ;
|
||||
int argc = 0;
|
||||
uint16_t ret;
|
||||
ei_x_buff xr;
|
||||
|
||||
@@ -103,19 +104,20 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
|
||||
#endif
|
||||
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
|
||||
|
||||
uwsgi_log("decode tuple\n");
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("rpc arity %d\n", arity);
|
||||
#endif
|
||||
if (arity != 3) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
gen_call = uwsgi_malloc(esize);
|
||||
@@ -127,7 +129,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
ei_decode_string(x->buff, &x->index, gen_call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("gen call = %s\n", gen_call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
@@ -138,13 +142,10 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
uwsgi_log("skip0 %d %c\n", etype, etype);
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("skip1 %d %c\n", etype, etype);
|
||||
ei_decode_ref(x->buff, &x->index, &eref);
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
@@ -157,17 +158,16 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arity: %d\n", arity);
|
||||
#endif
|
||||
if (arity != 5) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
char *method = uwsgi_malloc(esize);
|
||||
|
||||
@@ -181,7 +181,6 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
if (strcmp(method, "call")) return;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
@@ -207,7 +206,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
ei_decode_string(x->buff, &x->index, call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("RPC %s %s\n", module, call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
@@ -215,16 +216,20 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
else if (etype == ERL_STRING_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
|
||||
ret = uwsgi_rpc(call, argc, argv, buffer);
|
||||
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("buffer: %.*s\n", ret, buffer);
|
||||
#endif
|
||||
|
||||
ei_x_new_with_version(&xr);
|
||||
|
||||
@@ -247,7 +252,6 @@ void erlang_loop() {
|
||||
int fd;
|
||||
|
||||
int eversion;
|
||||
int i;
|
||||
|
||||
ei_x_buff x, xr;
|
||||
|
||||
@@ -286,7 +290,7 @@ void erlang_loop() {
|
||||
if (em.msgtype == ERL_TICK)
|
||||
continue;
|
||||
|
||||
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
|
||||
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
|
||||
|
||||
|
||||
|
||||
@@ -300,20 +304,18 @@ void erlang_loop() {
|
||||
uwsgi_erlang_rpc(fd, &em.from, &x);
|
||||
}
|
||||
else {
|
||||
int uep = -1;
|
||||
for(i=0;i<uerl.uep_cnt;i++) {
|
||||
if (!strcmp(uerl.uep[i].name, em.toname)) {
|
||||
uep = i;
|
||||
struct uwsgi_erlang_process *uep = uerl.uep;
|
||||
while(uep) {
|
||||
if (!strcmp(uep->name, em.toname)) {
|
||||
if (uep->plugin) {
|
||||
uep->plugin(uep->func, &x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
if (uep > -1) {
|
||||
if (uerl.uep[uep].plugin) {
|
||||
uerl.uep[uep].plugin( uerl.uep[uep].func, &x );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uep) {
|
||||
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
|
||||
dump_eterm(&x);
|
||||
}
|
||||
@@ -366,7 +368,6 @@ int erlang_init() {
|
||||
|
||||
if (uerl.name) {
|
||||
|
||||
uwsgi.master_process = 1;
|
||||
|
||||
host = strchr(uerl.name, '@');
|
||||
|
||||
@@ -422,10 +423,11 @@ int erlang_init() {
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
|
||||
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -435,7 +437,8 @@ int erlang_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_ERLANG:
|
||||
uerl.name = optarg;
|
||||
uwsgi.master_process = 1;
|
||||
uerl.name = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_ERLANG_COOKIE:
|
||||
uerl.cookie = optarg;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <ei.h>
|
||||
|
||||
#define MAX_UWSGI_ERLANG_PROCESSES 64
|
||||
|
||||
#define LONG_ARGS_ERLANG 17012
|
||||
#define LONG_ARGS_ERLANG_COOKIE 17013
|
||||
|
||||
@@ -12,6 +10,8 @@ struct uwsgi_erlang_process {
|
||||
char name[0xff];
|
||||
void (*plugin)(void *, ei_x_buff *);
|
||||
void *func;
|
||||
|
||||
struct uwsgi_erlang_process *next;
|
||||
};
|
||||
|
||||
struct uwsgi_erlang {
|
||||
@@ -24,7 +24,6 @@ struct uwsgi_erlang {
|
||||
|
||||
void *lock;
|
||||
|
||||
struct uwsgi_erlang_process uep[MAX_UWSGI_ERLANG_PROCESSES];
|
||||
int uep_cnt;
|
||||
struct uwsgi_erlang_process *uep;
|
||||
};
|
||||
|
||||
|
||||
+261
-61
@@ -20,6 +20,9 @@
|
||||
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
|
||||
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
|
||||
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
|
||||
#define LONG_ARGS_FASTROUTER_TOLERANCE 150009
|
||||
#define LONG_ARGS_FASTROUTER_STATS 150010
|
||||
#define LONG_ARGS_FASTROUTER_ZERG 150011
|
||||
|
||||
#define FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
@@ -28,11 +31,16 @@
|
||||
#define FASTROUTER_STATUS_RESPONSE 4
|
||||
|
||||
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
|
||||
#define add_check_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+x, NULL)
|
||||
#define del_check_timeout(x) rb_erase(&x->rbt, ufr.timeouts);
|
||||
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
|
||||
|
||||
void fastrouter_send_stats(int);
|
||||
|
||||
struct uwsgi_fastrouter_socket {
|
||||
char *name;
|
||||
int fd;
|
||||
char *zerg;
|
||||
struct uwsgi_fastrouter_socket *next;
|
||||
};
|
||||
|
||||
@@ -53,8 +61,11 @@ struct uwsgi_fastrouter {
|
||||
char *base;
|
||||
int base_len;
|
||||
|
||||
char *stats_server;
|
||||
|
||||
char *subscription_server;
|
||||
struct uwsgi_dict *subscription_dict;
|
||||
struct uwsgi_subscribe_slot *subscriptions;
|
||||
int subscription_regexp;
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
@@ -64,12 +75,27 @@ struct uwsgi_fastrouter {
|
||||
|
||||
struct rb_root *timeouts;
|
||||
|
||||
struct uwsgi_rb_timer *subscriptions_check;
|
||||
|
||||
int cheap;
|
||||
int i_am_cheap;
|
||||
|
||||
int tolerance;
|
||||
} ufr;
|
||||
|
||||
static void fastrouter_go_cheap(void) {
|
||||
|
||||
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
|
||||
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 1;
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name, int fd) {
|
||||
|
||||
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets, *old_uwsgi_sock;
|
||||
|
||||
@@ -89,6 +115,12 @@ static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
|
||||
|
||||
memset(uwsgi_sock, 0, sizeof(struct uwsgi_fastrouter_socket));
|
||||
uwsgi_sock->name = name;
|
||||
if (name) {
|
||||
uwsgi_sock->fd = -1;
|
||||
}
|
||||
else {
|
||||
uwsgi_sock->fd = fd;
|
||||
}
|
||||
|
||||
return uwsgi_sock;
|
||||
}
|
||||
@@ -97,6 +129,7 @@ static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
|
||||
|
||||
struct option fastrouter_options[] = {
|
||||
{"fastrouter", required_argument, 0, LONG_ARGS_FASTROUTER},
|
||||
{"fastrouter-zerg", required_argument, 0, LONG_ARGS_FASTROUTER_ZERG},
|
||||
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
|
||||
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
|
||||
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
|
||||
@@ -105,7 +138,11 @@ struct option fastrouter_options[] = {
|
||||
{"fastrouter-cheap", no_argument, &ufr.cheap, 1},
|
||||
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
|
||||
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
|
||||
{"fastrouter-subscription-use-regexp", no_argument, &ufr.subscription_regexp, 1},
|
||||
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
|
||||
{"fastrouter-stats", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
|
||||
{"fastrouter-stats-server", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
|
||||
{"fastrouter-ss", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -123,10 +160,15 @@ void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
|
||||
usr->address = val;
|
||||
usr->address_len = vallen;
|
||||
}
|
||||
|
||||
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
|
||||
usr->modifier1 = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
else if (!uwsgi_strncmp("cores", 5, key, keylen)) {
|
||||
usr->cores = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
else if (!uwsgi_strncmp("load", 4, key, keylen)) {
|
||||
usr->load = uwsgi_str_num(val, vallen);
|
||||
}
|
||||
}
|
||||
|
||||
struct fastrouter_session {
|
||||
@@ -136,7 +178,6 @@ struct fastrouter_session {
|
||||
int status;
|
||||
struct uwsgi_header uh;
|
||||
uint8_t h_pos;
|
||||
char buffer[0xffff];
|
||||
uint16_t pos;
|
||||
|
||||
char *hostname;
|
||||
@@ -147,38 +188,48 @@ struct fastrouter_session {
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
struct uwsgi_subscriber_name *un;
|
||||
struct uwsgi_subscribe_node *un;
|
||||
int pass_fd;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
|
||||
uint8_t modifier1;
|
||||
|
||||
char buffer[0xffff];
|
||||
};
|
||||
|
||||
static void close_session(struct fastrouter_session **fr_table, struct fastrouter_session *fr_session) {
|
||||
|
||||
close(fr_session->fd);
|
||||
fr_table[fr_session->fd] = NULL;
|
||||
if (fr_session->instance_fd != -1) {
|
||||
if (ufr.subscription_server && (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING)) {
|
||||
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
if (fr_session->un->len > 0) {
|
||||
if (ufr.subscription_dict->count > 0) {
|
||||
ufr.subscription_dict->count--;
|
||||
}
|
||||
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
|
||||
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 1;
|
||||
|
||||
if (ufr.subscriptions && fr_session->un && fr_session->un->len > 0) {
|
||||
// decrease reference count
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[1] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
fr_session->un->reference--;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[2] node %.*s refcnt: %llu\n", fr_session->un->len, fr_session->un->name, fr_session->un->reference);
|
||||
#endif
|
||||
if (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING) {
|
||||
if (fr_session->un->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
fr_session->un->failcnt++;
|
||||
fr_session->un->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (fr_session->un->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);
|
||||
}
|
||||
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
|
||||
fastrouter_go_cheap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (fr_session->instance_fd != -1) {
|
||||
close(fr_session->instance_fd);
|
||||
fr_table[fr_session->instance_fd] = NULL;
|
||||
}
|
||||
@@ -202,7 +253,6 @@ static void expire_timeouts(struct fastrouter_session **fr_table) {
|
||||
|
||||
if (urbt->key <= current) {
|
||||
close_session(fr_table, (struct fastrouter_session *)urbt->data);
|
||||
uwsgi_log("timeout !!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -283,6 +333,7 @@ void fastrouter_loop() {
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
int ufr_subserver = -1;
|
||||
int ufr_stats_server = -1;
|
||||
|
||||
for(i=0;i<2048;i++) {
|
||||
fr_table[i] = NULL;
|
||||
@@ -293,7 +344,10 @@ void fastrouter_loop() {
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
|
||||
while(ufr_sock) {
|
||||
if (ufr_sock->name[0] == '=') {
|
||||
if (ufr_sock->fd > -1) {
|
||||
ufr_sock->name = uwsgi_getsockname(ufr_sock->fd);
|
||||
}
|
||||
else if (ufr_sock->name[0] == '=') {
|
||||
int shared_socket = atoi(ufr_sock->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
ufr_sock->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
@@ -312,7 +366,12 @@ void fastrouter_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
|
||||
if (ufr_sock->zerg) {
|
||||
uwsgi_log("uwsgi fastrouter/proxy bound on %s (from zerg server %s)\n", ufr_sock->name, ufr_sock->zerg);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
|
||||
}
|
||||
|
||||
if (!ufr.cheap) {
|
||||
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
|
||||
@@ -327,20 +386,39 @@ void fastrouter_loop() {
|
||||
|
||||
events = event_queue_alloc(ufr.nevents);
|
||||
|
||||
ufr.timeouts = uwsgi_init_rb_timer();
|
||||
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
|
||||
|
||||
|
||||
if (ufr.subscription_server) {
|
||||
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
|
||||
event_queue_add_fd_read(ufr.queue, ufr_subserver);
|
||||
if (!ufr.subscription_slot) ufr.subscription_slot = 30;
|
||||
ufr.subscription_dict = uwsgi_dict_create(ufr.subscription_slot, 0);
|
||||
// check for node status every 10 seconds
|
||||
//ufr.subscriptions_check = add_check_timeout(10);
|
||||
}
|
||||
|
||||
if (ufr.stats_server) {
|
||||
char *tcp_port = strchr(ufr.stats_server, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
ufr_stats_server = bind_to_tcp(ufr.stats_server, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
ufr_stats_server = bind_to_unix(ufr.stats_server, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(ufr.queue, ufr_stats_server);
|
||||
uwsgi_log("*** FastRouter stats server enabled on %s fd: %d ***\n", ufr.stats_server, ufr_stats_server);
|
||||
}
|
||||
|
||||
if (ufr.pattern) {
|
||||
init_magic_table(magic_table);
|
||||
}
|
||||
|
||||
ufr.timeouts = uwsgi_init_rb_timer();
|
||||
if (!ufr.socket_timeout) ufr.socket_timeout = 30;
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -386,6 +464,8 @@ void fastrouter_loop() {
|
||||
fr_table[new_connection]->un = NULL;
|
||||
fr_table[new_connection]->instance_failed = 0;
|
||||
fr_table[new_connection]->instance_address_len = 0;
|
||||
fr_table[new_connection]->hostname_len = 0;
|
||||
fr_table[new_connection]->hostname = NULL;
|
||||
|
||||
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
|
||||
|
||||
@@ -401,7 +481,10 @@ void fastrouter_loop() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == ufr_subserver) {
|
||||
if (interesting_fd == ufr_stats_server) {
|
||||
fastrouter_send_stats(ufr_stats_server);
|
||||
}
|
||||
else if (interesting_fd == ufr_subserver) {
|
||||
len = recv(ufr_subserver, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ufr.queue, ufr_subserver);
|
||||
@@ -409,16 +492,35 @@ void fastrouter_loop() {
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
|
||||
uwsgi_add_subscriber(ufr.subscription_dict, &usr);
|
||||
if (ufr.i_am_cheap) {
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 0;
|
||||
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(&ufr.subscriptions, &usr, ufr.subscription_regexp) && ufr.i_am_cheap) {
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 0;
|
||||
uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");
|
||||
}
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(&ufr.subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ufr.subscription_regexp);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
// check if i can remove the node
|
||||
if (node->reference == 0) {
|
||||
uwsgi_remove_subscribe_node(&ufr.subscriptions, node);
|
||||
}
|
||||
if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
|
||||
fastrouter_go_cheap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -439,7 +541,8 @@ void fastrouter_loop() {
|
||||
case FASTROUTER_STATUS_RECV_HDR:
|
||||
len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
@@ -473,7 +576,7 @@ void fastrouter_loop() {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
|
||||
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
|
||||
#endif
|
||||
if (ufr.use_cache) {
|
||||
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
|
||||
@@ -491,12 +594,15 @@ void fastrouter_loop() {
|
||||
fr_session->instance_address = tmp_socket_name;
|
||||
}
|
||||
else if (ufr.subscription_server) {
|
||||
fr_session->un = uwsgi_get_subscriber(ufr.subscription_dict, fr_session->hostname, fr_session->hostname_len);
|
||||
fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
|
||||
if (fr_session->un && fr_session->un->len) {
|
||||
fr_session->instance_address = fr_session->un->name;
|
||||
fr_session->instance_address_len = fr_session->un->len;
|
||||
fr_session->modifier1 = fr_session->un->modifier1;
|
||||
}
|
||||
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
|
||||
fastrouter_go_cheap();
|
||||
}
|
||||
}
|
||||
else if (ufr.base) {
|
||||
tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
|
||||
@@ -531,24 +637,7 @@ void fastrouter_loop() {
|
||||
if (tmp_socket_name) free(tmp_socket_name);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
if (ufr.subscription_server) {
|
||||
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
|
||||
if (fr_session->un->len > 0) {
|
||||
fr_session->un->len = 0;
|
||||
if (ufr.subscription_dict->count > 0) {
|
||||
ufr.subscription_dict->count--;
|
||||
}
|
||||
if (ufr.subscription_dict->count == 0 && ufr.cheap && !ufr.i_am_cheap) {
|
||||
uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
|
||||
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
|
||||
while(ufr_sock) {
|
||||
event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());
|
||||
ufr_sock = ufr_sock->next;
|
||||
}
|
||||
ufr.i_am_cheap = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
}
|
||||
@@ -678,7 +767,7 @@ void fastrouter_loop() {
|
||||
|
||||
// fallback to destroy !!!
|
||||
default:
|
||||
uwsgi_log("default action\n");
|
||||
uwsgi_log("unknown event: closing session\n");
|
||||
close_session(fr_table, fr_session);
|
||||
break;
|
||||
|
||||
@@ -701,13 +790,13 @@ int fastrouter_init() {
|
||||
if (!ufr.nevents) ufr.nevents = 64;
|
||||
|
||||
if (ufr.code_string_code && ufr.code_string_function) {
|
||||
if (register_fat_gateway("fastrouter", fastrouter_loop) == NULL) {
|
||||
if (register_fat_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
|
||||
uwsgi_log("unable to register the fastrouter gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (register_gateway("fastrouter", fastrouter_loop) == NULL) {
|
||||
if (register_gateway("uWSGI fastrouter", fastrouter_loop) == NULL) {
|
||||
uwsgi_log("unable to register the fastrouter gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -722,14 +811,39 @@ int fastrouter_opt(int i, char *optarg) {
|
||||
char *cs;
|
||||
char *cs_code;
|
||||
char *cs_func;
|
||||
int zerg_fd;
|
||||
int *zerg;
|
||||
int j;
|
||||
struct uwsgi_fastrouter_socket *fr_sock;
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_FASTROUTER:
|
||||
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
|
||||
uwsgi_fastrouter_new_socket(generate_socket_name(optarg), -1);
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_ZERG:
|
||||
zerg_fd = uwsgi_connect(optarg, 30, 0);
|
||||
if (zerg_fd < 0) {
|
||||
uwsgi_log("--- unable to connect to zerg server ---\n");
|
||||
exit(1);
|
||||
}
|
||||
zerg = uwsgi_attach_fd(zerg_fd, 8, "uwsgi-zerg", 11);
|
||||
if (zerg == NULL) {
|
||||
uwsgi_log("--- invalid data received from zerg-server ---\n");
|
||||
exit(1);
|
||||
}
|
||||
close(zerg_fd);
|
||||
for(j=0;j<8;j++) {
|
||||
if (zerg[j] == -1) break;
|
||||
fr_sock = uwsgi_fastrouter_new_socket(NULL, zerg[j]);
|
||||
fr_sock->zerg = optarg;
|
||||
}
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
|
||||
ufr.subscription_server = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_STATS:
|
||||
ufr.stats_server = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_FASTROUTER_EVENTS:
|
||||
ufr.nevents = atoi(optarg);
|
||||
return 1;
|
||||
@@ -780,3 +894,89 @@ struct uwsgi_plugin fastrouter_plugin = {
|
||||
.init = fastrouter_init,
|
||||
};
|
||||
|
||||
|
||||
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
|
||||
#define stats_send(x, y) fprintf(output, x, y)
|
||||
|
||||
void fastrouter_send_stats(int fd) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *output = fdopen(client_fd, "w");
|
||||
if (!output) {
|
||||
uwsgi_error("fdopen()");
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
|
||||
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
|
||||
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
stats_send("\"cwd\": \"%s\",\n", cwd);
|
||||
free(cwd);
|
||||
|
||||
fprintf(output, "\"fastrouter\": [");
|
||||
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_sock->next) {
|
||||
stats_send("\"%s\",", uwsgi_sock->name);
|
||||
}
|
||||
else {
|
||||
stats_send("\"%s\"", uwsgi_sock->name);
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
fprintf(output, "],\n");
|
||||
|
||||
if (ufr.subscription_server) {
|
||||
fprintf(output, "\"subscriptions\": [\n");
|
||||
struct uwsgi_subscribe_slot *s_slot = ufr.subscriptions;
|
||||
while(s_slot) {
|
||||
fprintf(output, "\t{ \"key\": \"%.*s\",\n", s_slot->keylen, s_slot->key);
|
||||
fprintf(output, "\t\t\"hits\": %llu,\n", (unsigned long long) s_slot->hits);
|
||||
fprintf(output, "\t\t\"nodes\": [\n");
|
||||
struct uwsgi_subscribe_node *s_node = s_slot->nodes;
|
||||
while(s_node) {
|
||||
fprintf(output, "\t\t\t{\"name\": \"%.*s\", \"modifier1\": %d, \"modifier2\": %d, \"last_check\": %llu, \"requests\": %llu, \"tx\": %llu, \"cores\": %llu, \"load\": %llu, \"ref\": %llu, \"failcnt\": %llu, \"death_mark\": %d}", s_node->len, s_node->name, s_node->modifier1, s_node->modifier2,
|
||||
(unsigned long long) s_node->last_check, (unsigned long long) s_node->requests, (unsigned long long) s_node->transferred,
|
||||
(unsigned long long) s_node->cores, (unsigned long long) s_node->load, (unsigned long long) s_node->reference,
|
||||
(unsigned long long) s_node->failcnt, s_node->death_mark);
|
||||
if (s_node->next) {
|
||||
fprintf(output, ",\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
s_node = s_node->next;
|
||||
}
|
||||
fprintf(output, "\t\t]\n");
|
||||
if (s_slot->next) {
|
||||
fprintf(output, "\t},\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output, "\t}\n");
|
||||
}
|
||||
s_slot = s_slot->next;
|
||||
// check for loopy optimization
|
||||
if (s_slot == ufr.subscriptions) break;
|
||||
}
|
||||
fprintf(output, "],\n");
|
||||
}
|
||||
|
||||
fprintf(output,"\"cheap\": %d\n", ufr.i_am_cheap);
|
||||
|
||||
fprintf(output,"}\n");
|
||||
fclose(output);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -58,14 +58,13 @@ void fiber_loop() {
|
||||
uwsgi.schedule_to_main = fiber_schedule_to_main;
|
||||
uwsgi.schedule_to_req = fiber_schedule_to_req;
|
||||
|
||||
// must run all the rack/ruby plugins without protection
|
||||
ur.unprotected = 1;
|
||||
|
||||
rb_protect(protected_async_loop, 0, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// never here
|
||||
|
||||
@@ -9,6 +9,7 @@ NAME='fiber'
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-DRUBY19')
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <zlib.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define MAX_GELF 8192
|
||||
|
||||
struct graylog2_config {
|
||||
char *host;
|
||||
char json_buf[MAX_GELF];
|
||||
char escaped_buf[MAX_GELF];
|
||||
size_t escaped_len;
|
||||
char buffer[MAX_GELF];
|
||||
} g2c;
|
||||
|
||||
ssize_t uwsgi_graylog2_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
size_t i;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!uwsgi.choosen_logger_arg) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ul->fd);
|
||||
|
||||
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (!comma) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g2c.host = comma + 1;
|
||||
|
||||
*comma = 0;
|
||||
|
||||
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
|
||||
|
||||
*comma = ',';
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
g2c.escaped_len = 0;
|
||||
|
||||
int truncated = 0;
|
||||
char *ptr = g2c.escaped_buf;
|
||||
uLongf destLen = MAX_GELF;
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
if (message[i] == '\\') {
|
||||
*ptr ++= '\\';
|
||||
g2c.escaped_len++;
|
||||
}
|
||||
else if (message[i] == '"') {
|
||||
*ptr ++= '\\';
|
||||
g2c.escaped_len++;
|
||||
}
|
||||
*ptr ++= message[i];
|
||||
g2c.escaped_len++;
|
||||
|
||||
if (!truncated) {
|
||||
if (g2c.escaped_len == 128) {
|
||||
truncated = 1;
|
||||
}
|
||||
else if (g2c.escaped_len > 128) {
|
||||
truncated = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (truncated) truncated = 128 - (truncated-1);
|
||||
else (truncated = g2c.escaped_len);
|
||||
|
||||
int rlen = snprintf(g2c.json_buf, MAX_GELF, "{ \"version\": \"1.0\", \"host\": \"%s\", \"short_message\": \"%.*s\", \"full_message\": \"%.*s\", \"timestamp\": %d, \"level\": 5, \"facility\": \"uWSGI-%s\" }",
|
||||
g2c.host, truncated, g2c.escaped_buf, (int)g2c.escaped_len, g2c.escaped_buf, (int) time(NULL), UWSGI_VERSION);
|
||||
|
||||
if (rlen > 0) {
|
||||
if (compressBound((uLong) rlen) <= MAX_GELF) {
|
||||
if (compress((Bytef *) g2c.buffer, &destLen, (Bytef *) g2c.json_buf, (uLong) rlen) == Z_OK) {
|
||||
return sendto(ul->fd, g2c.buffer, destLen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_graylog2_register() {
|
||||
uwsgi_register_logger("graylog2", uwsgi_graylog2_logger);
|
||||
}
|
||||
|
||||
int uwsgi_graylog2_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin graylog2_plugin = {
|
||||
|
||||
.name = "graylog2",
|
||||
.on_load = uwsgi_graylog2_register,
|
||||
.init = uwsgi_graylog2_init
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='graylog2'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lz']
|
||||
GCC_LIST = ['graylog2_plugin']
|
||||
+22
-15
@@ -39,6 +39,7 @@ struct uwsgi_http {
|
||||
int server;
|
||||
|
||||
char *subscription_server;
|
||||
int subscription_regexp;
|
||||
|
||||
char *pattern;
|
||||
int pattern_len;
|
||||
@@ -60,7 +61,7 @@ struct uwsgi_http {
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
struct uwsgi_dict *subscription_dict;
|
||||
struct uwsgi_subscribe_slot *subscriptions;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
} uhttp;
|
||||
@@ -76,6 +77,7 @@ struct option http_options[] = {
|
||||
{"http-use-cluster", no_argument, &uhttp.use_cluster, 1},
|
||||
{"http-events", required_argument, 0, LONG_ARGS_HTTP_EVENTS},
|
||||
{"http-subscription-server", required_argument, 0, LONG_ARGS_HTTP_SUBSCRIPTION_SERVER},
|
||||
{"http-subscription-use-regexp", no_argument, &uhttp.subscription_regexp, 1},
|
||||
{"http-timeout", required_argument, 0, LONG_ARGS_HTTP_TIMEOUT},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
@@ -136,8 +138,10 @@ struct http_session {
|
||||
char uss[MAX_HTTP_VEC*2];
|
||||
|
||||
char buffer[UMAX16];
|
||||
char path_info[UMAX16];
|
||||
uint16_t path_info_len;
|
||||
|
||||
struct uwsgi_subscriber_name *un;
|
||||
struct uwsgi_subscribe_node *un;
|
||||
|
||||
in_addr_t ip_addr;
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
@@ -156,9 +160,9 @@ static void close_session(struct http_session **uhttp_table, struct http_session
|
||||
close(uhttp_session->fd);
|
||||
uhttp_table[uhttp_session->fd] = NULL;
|
||||
if (uhttp_session->instance_fd != -1) {
|
||||
if (uhttp.subscription_server && (uhttp_session->instance_failed || uhttp_session->status == HTTP_STATUS_CONNECTING)) {
|
||||
if (uhttp.subscriptions && (uhttp_session->instance_failed || uhttp_session->status == HTTP_STATUS_CONNECTING)) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
|
||||
uhttp_session->un->len = 0;
|
||||
uwsgi_remove_subscribe_node(&uhttp.subscriptions, uhttp_session->un);
|
||||
}
|
||||
close(uhttp_session->instance_fd);
|
||||
uhttp_table[uhttp_session->instance_fd] = NULL;
|
||||
@@ -325,13 +329,19 @@ int http_parse(struct http_session *h_session) {
|
||||
base = ptr;
|
||||
while(ptr < watermark) {
|
||||
if (*ptr == '?' && !query_string) {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
h_session->path_info_len = ptr-base;
|
||||
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
|
||||
query_string = ptr+1;
|
||||
}
|
||||
else if (*ptr == ' ') {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REQUEST_URI", 11, base, ptr-base, &c);
|
||||
if (!query_string) {
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, base, ptr-base, &c);
|
||||
// PATH_INFO must be url-decoded !!!
|
||||
h_session->path_info_len = ptr-base;
|
||||
http_url_decode(base, &h_session->path_info_len, h_session->path_info);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "PATH_INFO", 9, h_session->path_info, h_session->path_info_len, &c);
|
||||
h_session->uh.pktsize += http_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "QUERY_STRING", 12, "", 0, &c);
|
||||
}
|
||||
else {
|
||||
@@ -474,7 +484,6 @@ void http_loop() {
|
||||
if (uhttp.subscription_server) {
|
||||
uhttp_subserver = bind_to_udp(uhttp.subscription_server, 0, 0);
|
||||
event_queue_add_fd_read(uhttp_queue, uhttp_subserver);
|
||||
uhttp.subscription_dict = uwsgi_dict_create(100, 0);
|
||||
}
|
||||
|
||||
if (uhttp.pattern) {
|
||||
@@ -550,7 +559,7 @@ void http_loop() {
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf+4, len-4, http_manage_subscription, &usr);
|
||||
uwsgi_add_subscriber(uhttp.subscription_dict, &usr);
|
||||
uwsgi_add_subscribe_node(&uhttp.subscriptions, &usr, uhttp.subscription_regexp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -575,7 +584,8 @@ void http_loop() {
|
||||
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(uhttp_table, uhttp_session);
|
||||
break;
|
||||
}
|
||||
@@ -630,7 +640,7 @@ void http_loop() {
|
||||
uhttp_session->instance_address_len = uhttp.to_len;
|
||||
}
|
||||
else if (uhttp.subscription_server) {
|
||||
uhttp_session->un = uwsgi_get_subscriber(uhttp.subscription_dict, uhttp_session->hostname, uhttp_session->hostname_len);
|
||||
uhttp_session->un = uwsgi_get_subscribe_node(&uhttp.subscriptions, uhttp_session->hostname, uhttp_session->hostname_len, uhttp.subscription_regexp);
|
||||
if (uhttp_session->un && uhttp_session->un->len) {
|
||||
uhttp_session->instance_address = uhttp_session->un->name;
|
||||
uhttp_session->instance_address_len = uhttp_session->un->len;
|
||||
@@ -661,10 +671,7 @@ void http_loop() {
|
||||
}
|
||||
|
||||
if (uhttp_session->instance_fd < 0) {
|
||||
if (uhttp.subscription_server) {
|
||||
uwsgi_log("marking %.*s as failed\n", (int) uhttp_session->instance_address_len,uhttp_session->instance_address);
|
||||
uhttp_session->un->len = 0;
|
||||
}
|
||||
uhttp_session->instance_failed = 1;
|
||||
close_session(uhttp_table, uhttp_session);
|
||||
break;
|
||||
}
|
||||
@@ -883,7 +890,7 @@ int http_init() {
|
||||
|
||||
uhttp.server = bind_to_tcp(uhttp.socket_name, uwsgi.listen_queue, strchr(uhttp.socket_name,':'));
|
||||
|
||||
if (register_gateway("http", http_loop) == NULL) {
|
||||
if (register_gateway("uWSGI http", http_loop) == NULL) {
|
||||
uwsgi_log("unable to register the http gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
ssize_t uwsgi_socket_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
int family = AF_UNIX;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (comma) {
|
||||
ul->data = comma+1;
|
||||
*comma = 0;
|
||||
}
|
||||
|
||||
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
|
||||
if (colon) {
|
||||
family = AF_INET;
|
||||
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
|
||||
}
|
||||
else {
|
||||
ul->addr_len = socket_to_un_addr(uwsgi.choosen_logger_arg, &ul->addr.sa_un);
|
||||
}
|
||||
|
||||
ul->fd = socket(family, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&ul->msg, 0, sizeof(struct msghdr));
|
||||
|
||||
ul->msg.msg_name = &ul->addr;
|
||||
ul->msg.msg_namelen = ul->addr_len;
|
||||
if (ul->data) {
|
||||
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec) * 2);
|
||||
ul->msg.msg_iov[0].iov_base = ul->data;
|
||||
ul->msg.msg_iov[0].iov_len = strlen(ul->data);
|
||||
ul->msg.msg_iovlen = 2;
|
||||
ul->count = 1;
|
||||
}
|
||||
else {
|
||||
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec));
|
||||
ul->msg.msg_iovlen = 1;
|
||||
}
|
||||
|
||||
if (comma) {
|
||||
*comma = ',' ;
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
|
||||
ul->msg.msg_iov[ul->count].iov_base = message;
|
||||
ul->msg.msg_iov[ul->count].iov_len = len;
|
||||
|
||||
return sendmsg(ul->fd, &ul->msg, 0);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_logsocket_register() {
|
||||
uwsgi_register_logger("socket", uwsgi_socket_logger);
|
||||
}
|
||||
|
||||
int uwsgi_logsocket_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logsocket_plugin = {
|
||||
|
||||
.name = "logsocket",
|
||||
.on_load = uwsgi_logsocket_register,
|
||||
.init = uwsgi_logsocket_init
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logsocket'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logsocket_plugin']
|
||||
@@ -682,7 +682,7 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
}
|
||||
|
||||
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
|
||||
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
uint8_t i;
|
||||
const char *sv;
|
||||
@@ -698,7 +698,7 @@ uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
|
||||
|
||||
for(i=0;i<argc;i++) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_pushlstring(L, argv[i], argvs[i]);
|
||||
}
|
||||
|
||||
if (lua_pcall(L, argc, 1, 0) != 0) {
|
||||
|
||||
+18
-19
@@ -15,49 +15,48 @@ struct option nagios_options[] = {
|
||||
|
||||
int nagios() {
|
||||
|
||||
char *tcp_port;
|
||||
struct wsgi_request nagios_req;
|
||||
// connect and send
|
||||
struct uwsgi_header uh;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!use_nagios) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uwsgi.sockets) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
}
|
||||
tcp_port = strchr(uwsgi.sockets->name, ':');
|
||||
if (tcp_port == NULL) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
tcp_port[0] = 0;
|
||||
|
||||
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
|
||||
exit(2);
|
||||
}
|
||||
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
nagios_req.uh.pktsize = 0;
|
||||
nagios_req.uh.modifier2 = 0;
|
||||
if (write(fd, &nagios_req.uh, 4) != 4) {
|
||||
|
||||
uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
nagios_req.poll.fd = fd;
|
||||
nagios_req.poll.events = POLLIN;
|
||||
|
||||
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buf);
|
||||
|
||||
if (ret == -2) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
|
||||
exit(2);
|
||||
}
|
||||
else if (ret == -1) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: error reading response\n");
|
||||
exit(2);
|
||||
}
|
||||
else {
|
||||
if (nagios_req.uh.pktsize > 0) {
|
||||
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
|
||||
if (uh.pktsize > 0 && buf) {
|
||||
fprintf(stdout, "UWSGI WARNING: %.*s\n", uh.pktsize, buf);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
PHP_ARG_WITH(uwsgi,,
|
||||
[ --with-uwsgi=UWSGISRCDIR Build PHP as a uWSGI plugin (UNIX/POSIX only)], no, no)
|
||||
|
||||
AC_MSG_CHECKING([for UWSGI])
|
||||
if test "$PHP_UWSGI" != "no"; then
|
||||
|
||||
INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_UWSGI/php_plugin.so"
|
||||
|
||||
UWSGI_CFLAGS=`cd $PHP_UWSGI ; python uwsgiconfig.py --cflags`
|
||||
UWSGI_CFLAGS="$UWSGI_CFLAGS -I$PHP_UWSGI"
|
||||
|
||||
PHP_SELECT_SAPI(uwsgi, shared, php_plugin.c, $UWSGI_CFLAGS)
|
||||
AC_MSG_RESULT([$PHP_UWSGI])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -0,0 +1,494 @@
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_variables.h"
|
||||
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// http status codes list
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
struct uwsgi_php {
|
||||
struct uwsgi_string_list *allowed_docroot;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
} uphp;
|
||||
|
||||
#define LONG_ARGS_PHP_BASE 17000 + ((14 + 1) * 1000)
|
||||
#define LONG_ARGS_PHP_INI LONG_ARGS_PHP_BASE + 1
|
||||
#define LONG_ARGS_PHP_ALLOWED_DOCROOT LONG_ARGS_PHP_BASE + 2
|
||||
#define LONG_ARGS_PHP_ALLOWED_EXT LONG_ARGS_PHP_BASE + 3
|
||||
|
||||
struct option uwsgi_php_options[] = {
|
||||
|
||||
{"php-ini", required_argument, 0, LONG_ARGS_PHP_INI},
|
||||
{"php-config", required_argument, 0, LONG_ARGS_PHP_INI},
|
||||
{"php-allowed-docroot", required_argument, 0, LONG_ARGS_PHP_ALLOWED_DOCROOT},
|
||||
{"php-allowed-ext", required_argument, 0, LONG_ARGS_PHP_ALLOWED_EXT},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
{
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
|
||||
if (len != str_length) {
|
||||
php_handle_aborted_connection();
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->response_size += len;
|
||||
return str_length;
|
||||
}
|
||||
|
||||
void uwsgi_php_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\nNot Found", 35);
|
||||
}
|
||||
|
||||
void uwsgi_php_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\n\r\nForbidden", 35);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
struct iovec iov[6];
|
||||
char status[4];
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
wsgi_req->status = SG(sapi_headers).http_response_code;
|
||||
if (!wsgi_req->status) wsgi_req->status = 200;
|
||||
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
|
||||
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
|
||||
uwsgi_num2str2n(wsgi_req->status, status, 4);
|
||||
|
||||
iov[2].iov_base = status;
|
||||
iov[2].iov_len = 3;
|
||||
|
||||
iov[3].iov_base = " ";
|
||||
iov[3].iov_len = 1;
|
||||
|
||||
// get the status code
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, status, 3)) {
|
||||
iov[4].iov_base = (char *) http_sc->message;
|
||||
iov[4].iov_len = http_sc->message_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iov[4].iov_len == 0) {
|
||||
iov[4].iov_base = "Unknown";
|
||||
iov[4].iov_len = 7;
|
||||
}
|
||||
|
||||
iov[5].iov_base = "\r\n";
|
||||
iov[5].iov_len = 2;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
while (h) {
|
||||
iov[0].iov_base = h->header;
|
||||
iov[0].iov_len = h->header_len;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
{
|
||||
uint read_bytes = 0;
|
||||
size_t len;
|
||||
int fd = -1;
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
if (wsgi_req->body_as_file) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
else if (uwsgi.post_buffering > 0) {
|
||||
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fd = wsgi_req->poll.fd;
|
||||
}
|
||||
|
||||
|
||||
count_bytes = MIN(count_bytes, wsgi_req->post_cl - SG(read_post_bytes));
|
||||
|
||||
// data in memory
|
||||
if (fd == -1) {
|
||||
if (count_bytes > 0) {
|
||||
memcpy(buffer, wsgi_req->post_buffering_buf + wsgi_req->post_pos, count_bytes);
|
||||
wsgi_req->post_pos += count_bytes;
|
||||
}
|
||||
return count_bytes;
|
||||
}
|
||||
|
||||
while (read_bytes < count_bytes) {
|
||||
len = read(fd, buffer + read_bytes, count_bytes - read_bytes);
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
read_bytes += len;
|
||||
}
|
||||
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
|
||||
static char *sapi_uwsgi_read_cookies(void)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
char *cookie = uwsgi_get_var(wsgi_req, (char *)"HTTP_COOKIE", 11, &len);
|
||||
if (cookie) {
|
||||
return estrndup(cookie, len);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
|
||||
wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len,
|
||||
track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
php_register_variable_safe("PATH_INFO", wsgi_req->path_info, wsgi_req->path_info_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable_safe("SCRIPT_NAME", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
php_register_variable_safe("SCRIPT_FILENAME", wsgi_req->file, wsgi_req->file_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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
php_register_variable_safe("PHP_SELF", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
if (php_module_startup(&uwsgi_sapi_module, NULL, 0)==FAILURE) {
|
||||
return FAILURE;
|
||||
} else {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_log_message(char *message) {
|
||||
|
||||
uwsgi_log(message);
|
||||
}
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module = {
|
||||
"uwsgi",
|
||||
"uWSGI/php",
|
||||
|
||||
php_uwsgi_startup,
|
||||
php_module_shutdown_wrapper,
|
||||
|
||||
NULL, /* activate */
|
||||
NULL, /* deactivate */
|
||||
|
||||
sapi_uwsgi_ub_write,
|
||||
NULL,
|
||||
NULL, /* get uid */
|
||||
NULL, /* getenv */
|
||||
|
||||
php_error,
|
||||
|
||||
NULL,
|
||||
sapi_uwsgi_send_headers,
|
||||
NULL,
|
||||
sapi_uwsgi_read_post,
|
||||
sapi_uwsgi_read_cookies,
|
||||
|
||||
sapi_uwsgi_register_variables,
|
||||
sapi_uwsgi_log_message, /* Log message */
|
||||
NULL, /* Get request time */
|
||||
NULL, /* Child terminate */
|
||||
|
||||
STANDARD_SAPI_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
int uwsgi_php_init(void) {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
char *ptr = wsgi_req->path_info;
|
||||
char *dst = full_path+docroot_len;
|
||||
char *part = ptr;
|
||||
int part_size = 0;
|
||||
struct stat st;
|
||||
|
||||
if (ptr[0] == '/') part_size++;
|
||||
|
||||
for(i=0;i<wsgi_req->path_info_len;i++) {
|
||||
if (ptr[i] == '/') {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
|
||||
if (stat(full_path, &st)) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// not a directory, stop walking
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (i < (wsgi_req->path_info_len)-1) {
|
||||
*path_info = ptr + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// check for buffer overflow !!!
|
||||
*(dst+part_size-1) = '/';
|
||||
*(dst+part_size) = 0;
|
||||
|
||||
dst += part_size ;
|
||||
part_size = 0;
|
||||
part = ptr + i + 1;
|
||||
}
|
||||
|
||||
part_size++;
|
||||
}
|
||||
|
||||
if (part < wsgi_req->path_info+wsgi_req->path_info_len) {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char real_filename[PATH_MAX+1];
|
||||
uint16_t docroot_len = 0;
|
||||
char *path_info = NULL;
|
||||
size_t real_filename_len = 0;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
|
||||
SG(server_context) = (void *) wsgi_req;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *docroot = uwsgi_get_var(wsgi_req, (char *) "DOCUMENT_ROOT", 13, &docroot_len);
|
||||
|
||||
if (!docroot) {
|
||||
docroot = uwsgi.cwd;
|
||||
docroot_len = strlen(uwsgi.cwd);
|
||||
}
|
||||
|
||||
char *filename = uwsgi_concat4n(docroot, docroot_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
|
||||
|
||||
if (uwsgi_php_walk(wsgi_req, filename, docroot, docroot_len, &path_info)) {
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path_info) {
|
||||
wsgi_req->path_info = path_info;
|
||||
wsgi_req->path_info_len = strlen(wsgi_req->path_info);
|
||||
}
|
||||
else {
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!realpath(filename, real_filename)) {
|
||||
free(filename);
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
if (uphp.allowed_docroot) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_docroot;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(real_filename, real_filename_len, usl->value, usl->len)) {
|
||||
goto secure;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_php_403(wsgi_req);
|
||||
uwsgi_log("PHP security error: %s is not under an allowed docroot\n", real_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secure:
|
||||
|
||||
if (uphp.allowed_ext) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_ext;
|
||||
while(usl) {
|
||||
if (real_filename_len >= usl->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len-usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto secure2;
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_php_403(wsgi_req);
|
||||
uwsgi_log("PHP security error: %s does not end with an allowed extension\n", real_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secure2:
|
||||
|
||||
wsgi_req->file = real_filename;
|
||||
wsgi_req->file_len = strlen(wsgi_req->file);
|
||||
|
||||
if (docroot[docroot_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (docroot_len-1);
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name = real_filename + docroot_len;
|
||||
}
|
||||
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("php filename = %s\n", real_filename);
|
||||
#endif
|
||||
|
||||
// now check for allowed paths and extensions
|
||||
|
||||
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
|
||||
SG(request_info).request_method = estrndup(wsgi_req->method, wsgi_req->method_len);
|
||||
SG(request_info).proto_num = 1001;
|
||||
|
||||
SG(request_info).query_string = estrndup(wsgi_req->query_string, wsgi_req->query_string_len);
|
||||
SG(request_info).content_length = wsgi_req->post_cl;
|
||||
SG(request_info).content_type = estrndup(wsgi_req->content_type, wsgi_req->content_type_len);
|
||||
|
||||
SG(request_info).path_translated = wsgi_req->file;
|
||||
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
file_handle.filename = real_filename;
|
||||
file_handle.free_filename = 0;
|
||||
file_handle.opened_path = NULL;
|
||||
|
||||
|
||||
if (php_request_startup(TSRMLS_C) == FAILURE) {
|
||||
internal_server_error(wsgi_req, "unable to start php request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
php_execute_script(&file_handle TSRMLS_CC);
|
||||
|
||||
php_request_shutdown(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_php_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_php_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PHP_INI:
|
||||
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(optarg);
|
||||
uwsgi_sapi_module.php_ini_ignore = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_PHP_ALLOWED_DOCROOT:
|
||||
uwsgi_string_new_list(&uphp.allowed_docroot, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_PHP_ALLOWED_EXT:
|
||||
uwsgi_string_new_list(&uphp.allowed_ext, optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SAPI_API struct uwsgi_plugin php_plugin = {
|
||||
.modifier1 = 14,
|
||||
.init = uwsgi_php_init,
|
||||
.request = uwsgi_php_request,
|
||||
.after_request = uwsgi_php_after_request,
|
||||
.options = uwsgi_php_options,
|
||||
.manage_opt = uwsgi_php_manage_options,
|
||||
};
|
||||
|
||||
+12
-14
@@ -15,8 +15,8 @@ struct option uwsgi_ping_options[] = {
|
||||
|
||||
static void ping() {
|
||||
|
||||
struct wsgi_request ping_req;
|
||||
char *buf = uwsgi_malloc(uwsgi.buffer_size);
|
||||
struct uwsgi_header uh;
|
||||
char *buf = NULL;
|
||||
|
||||
// use a 3 secs timeout by default
|
||||
if (!uping.ping_timeout) uping.ping_timeout = 3;
|
||||
@@ -28,25 +28,22 @@ static void ping() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&ping_req, 0, sizeof(struct wsgi_request));
|
||||
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
ping_req.uh.pktsize = 0;
|
||||
ping_req.uh.modifier2 = 0;
|
||||
if (write(fd, &ping_req.uh, 4) != 4) {
|
||||
uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
exit(2);
|
||||
}
|
||||
ping_req.poll.fd = fd;
|
||||
ping_req.poll.events = POLLIN;
|
||||
|
||||
ping_req.buffer = buf;
|
||||
|
||||
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
|
||||
int ret = uwsgi_read_response(fd, &uh, uping.ping_timeout, &buf);
|
||||
if (ret < 0) {
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (ping_req.uh.pktsize > 0) {
|
||||
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
|
||||
if (uh.pktsize > 0) {
|
||||
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, uh.pktsize, buf);
|
||||
exit(2);
|
||||
}
|
||||
else {
|
||||
@@ -98,6 +95,7 @@ int uwsgi_ping_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PING:
|
||||
uwsgi.no_initial_output = 1;
|
||||
uwsgi.no_server = 1;
|
||||
uping.ping = optarg;
|
||||
return 1;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->fd = uwsgi_connect(up->args, -1, 1);
|
||||
if (up->fd != -1) {
|
||||
// status = CONNECTING
|
||||
up->state = 1;
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// uselsess here (we have only one state), only to show a good practice
|
||||
// check the state
|
||||
if (up->state == 1) {
|
||||
if (uwsgi_is_bad_connection(up->fd)) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// this is a good connection
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probeconnect_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probeconnect_plugin = {
|
||||
|
||||
.init = probeconnect_init,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='probeconnect'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['connectprobe']
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int pg_prober_callback(int, struct uwsgi_signal_probe *);
|
||||
int probepg_init(void);
|
||||
|
||||
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->last_event = event_queue_write();
|
||||
up->data = (void *) PQconnectStart(up->args);
|
||||
if (up->data) {
|
||||
// status = CONNECTING
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD)
|
||||
goto bad;
|
||||
up->fd = PQsocket((PGconn *) up->data);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
bad:
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// check the state
|
||||
up->state = PQstatus((PGconn *) up->data);
|
||||
if (up->state == CONNECTION_BAD) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (up->state == CONNECTION_OK) {
|
||||
up->cycles = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// still wait...
|
||||
else {
|
||||
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
// the connection is good
|
||||
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
|
||||
if (wait_type == PGRES_POLLING_ACTIVE)
|
||||
wait_type = PQconnectPoll((PGconn *) up->data);
|
||||
up->cycles = 0;
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
PQfinish((PGconn *) up->data);
|
||||
if (wait_type == PGRES_POLLING_FAILED) {
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_READING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_read();
|
||||
}
|
||||
else if (wait_type == PGRES_POLLING_WRITING) {
|
||||
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
up->last_event = event_queue_write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probepg_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probepg_plugin = {
|
||||
|
||||
.init = probepg_init,
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import os
|
||||
|
||||
NAME='probepg'
|
||||
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
|
||||
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
|
||||
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
|
||||
|
||||
GCC_LIST = ['pgprobe']
|
||||
+1
-1
@@ -34,7 +34,7 @@ struct uwsgi_perl {
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
void uwsgi_psgi_app(void);
|
||||
int psgi_response(struct wsgi_request *, PerlInterpreter *, AV*);
|
||||
int psgi_response(struct wsgi_request *, AV*);
|
||||
|
||||
#define psgi_xs(func) newXS("uwsgi::" #func, XS_##func, "uwsgi")
|
||||
#define psgi_check_args(x) if (items < x) Perl_croak(aTHX_ "Usage: uwsgi::%s takes %d arguments", __FUNCTION__ + 3, x)
|
||||
|
||||
+10
-15
@@ -41,19 +41,11 @@ XS(XS_stream)
|
||||
AV *response = (AV* ) SvREFCNT_inc(SvRV(ST(0))) ;
|
||||
|
||||
if (av_len(response) == 2) {
|
||||
|
||||
#ifdef my_perl
|
||||
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
|
||||
#else
|
||||
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
|
||||
#endif
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
}
|
||||
else if (av_len(response) == 1) {
|
||||
#ifdef my_perl
|
||||
while (psgi_response(wsgi_req, my_perl, response) != UWSGI_OK);
|
||||
#else
|
||||
while (psgi_response(wsgi_req, uperl.main, response) != UWSGI_OK);
|
||||
#endif
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
|
||||
XSRETURN(1);
|
||||
@@ -95,7 +87,7 @@ XS(XS_input_read) {
|
||||
}
|
||||
else if (uwsgi.post_buffering > 0) {
|
||||
fd = -1;
|
||||
if (wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
|
||||
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
@@ -236,6 +228,7 @@ xs_init(pTHX)
|
||||
void uwsgi_psgi_app() {
|
||||
|
||||
struct stat stat_psgi;
|
||||
int id = uwsgi_apps_cnt;
|
||||
|
||||
if (uperl.psgi) {
|
||||
|
||||
@@ -291,7 +284,6 @@ void uwsgi_psgi_app() {
|
||||
|
||||
uperl.psgibuffer[stat_psgi.st_size] = 0;
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
@@ -303,11 +295,14 @@ void uwsgi_psgi_app() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
free(uperl.psgibuffer);
|
||||
close(uperl.fd);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_add_app(id, 5, "", 0);
|
||||
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
|
||||
|
||||
uwsgi_log("PSGI app (%s) loaded at %p\n", uperl.psgi, uperl.psgi_main);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+41
-62
@@ -23,7 +23,7 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SV *newobj;
|
||||
// set current context ?
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -49,7 +49,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
|
||||
|
||||
SV *ret = NULL;
|
||||
// set current context ?
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -79,7 +79,7 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
int ret;
|
||||
// set current context ? needed for threading
|
||||
//dTHX;
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -107,6 +107,7 @@ SV *uwsgi_perl_obj_call(SV *obj, char *method) {
|
||||
|
||||
SV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -140,6 +141,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
AV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -149,6 +151,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
PUTBACK;
|
||||
|
||||
call_sv(psgi_func, G_SCALAR | G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
@@ -326,51 +329,19 @@ int uwsgi_perl_init(){
|
||||
|
||||
}
|
||||
|
||||
#ifdef my_perl
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_enable_threads() {
|
||||
|
||||
int i;
|
||||
|
||||
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.interp = malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
if (!uperl.interp) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
uperl.interp[0] = uperl.main;
|
||||
|
||||
for(i=1;i<uwsgi.threads;i++) {
|
||||
uperl.interp[i] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
|
||||
|
||||
uperl.psgi_func = malloc( sizeof(SV*) * uwsgi.threads );
|
||||
if (!uperl.psgi_func) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
dTHXa(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main);
|
||||
|
||||
uperl.psgi_main = perl_eval_pv(uperl.psgibuffer, 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -381,12 +352,10 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
SV **harakiri;
|
||||
SV *psgi_func = uperl.psgi_main;
|
||||
// ugly hack
|
||||
register PerlInterpreter *my_perl = uperl.main;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
return psgi_response(wsgi_req, my_perl, wsgi_req->async_placeholder);
|
||||
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -401,19 +370,14 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1 && wsgi_req->async_id > 0) {
|
||||
if (uwsgi.threads > 1) {
|
||||
psgi_func = uperl.psgi_func[wsgi_req->async_id];
|
||||
my_perl = pthread_getspecific(uperl.u_interpreter);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
|
||||
wsgi_req->async_environ = build_psgi_env(wsgi_req);
|
||||
if (!wsgi_req->async_environ) goto clear;
|
||||
|
||||
@@ -431,7 +395,7 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
while (psgi_response(wsgi_req, my_perl, wsgi_req->async_result) != UWSGI_OK) {
|
||||
while (psgi_response(wsgi_req, wsgi_req->async_result) != UWSGI_OK) {
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
FREETMPS;
|
||||
@@ -471,26 +435,41 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
if (core_id > 0) {
|
||||
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[core_id]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
dTHXa(uperl.interp[core_id]);
|
||||
PERL_SET_CONTEXT(uperl.interp[core_id]);
|
||||
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uperl.psgibuffer, 0);
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
uperl.psgi_func[0] = uperl.psgi_main;
|
||||
if (core_id > 0) {
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_perl_manage_options(int i, char *optarg) {
|
||||
|
||||
@@ -531,11 +510,11 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
//.magic = uwsgi_perl_magic,
|
||||
//.help = uwsgi_perl_help,
|
||||
#ifdef my_perl
|
||||
#ifdef USE_ITHREADS
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
#endif
|
||||
.manage_opt = uwsgi_perl_manage_options,
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
.request = uwsgi_perl_request,
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *response) {
|
||||
int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
|
||||
SV **status_code, **hitem ;
|
||||
AV *headers, *body =NULL;
|
||||
@@ -147,6 +147,7 @@ int psgi_response(struct wsgi_request *wsgi_req, PerlInterpreter *my_perl, AV *r
|
||||
wsgi_req->sendfile_fd = SvIV(fn);
|
||||
SvREFCNT_dec(fn);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
// no need to close here as perl GC will do the close()
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -155,26 +155,28 @@ XS(XS_call) {
|
||||
|
||||
dXSARGS;
|
||||
|
||||
char buffer[0xffff];
|
||||
char *func;
|
||||
uint16_t size = 0;
|
||||
int i;
|
||||
char *argv[0xff];
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
STRLEN arg_len;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
func = SvPV_nolen(ST(0));
|
||||
|
||||
for(i=0;i<(items-1);i++) {
|
||||
argv[i] = SvPV_nolen(ST(i+1));
|
||||
argv[i] = SvPV(ST(i+1), arg_len);
|
||||
argvs[i] = arg_len;
|
||||
}
|
||||
|
||||
size = uwsgi_rpc(func, items-1, argv, buffer);
|
||||
char *response = uwsgi_do_rpc(NULL, func, items-1, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
ST(0) = newSVpv(buffer, size);
|
||||
ST(0) = newSVpv(response, size);
|
||||
sv_2mortal(ST(0));
|
||||
|
||||
free(response);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
|
||||
+21
-8
@@ -304,7 +304,7 @@ void pyerl_call_registered(void *func, ei_x_buff *x) {
|
||||
|
||||
PyTuple_SetItem(pyargs, 0, erl_to_py(x));
|
||||
|
||||
python_call((PyObject *) func, pyargs, 0);
|
||||
python_call((PyObject *) func, pyargs, 0, NULL);
|
||||
}
|
||||
|
||||
PyObject *pyerl_register_process(PyObject * self, PyObject * args) {
|
||||
@@ -316,17 +316,30 @@ PyObject *pyerl_register_process(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uerl.uep_cnt >= MAX_UWSGI_ERLANG_PROCESSES)
|
||||
return PyErr_Format(PyExc_ValueError, "You can define max %d erlang registered processes", MAX_UWSGI_ERLANG_PROCESSES);
|
||||
|
||||
if (strlen(name) > 0xff-1)
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid erlang process name");
|
||||
|
||||
strcpy(uerl.uep[uerl.uep_cnt].name, name);
|
||||
uerl.uep[uerl.uep_cnt].plugin = pyerl_call_registered;
|
||||
uerl.uep[uerl.uep_cnt].func = callable;
|
||||
struct uwsgi_erlang_process *uep = uerl.uep, *old_uep;
|
||||
|
||||
if (!uep) {
|
||||
uerl.uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
|
||||
uep = uerl.uep;
|
||||
}
|
||||
else {
|
||||
while(uep) {
|
||||
old_uep = uep;
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
uep = uwsgi_malloc(sizeof(struct uwsgi_erlang_process));
|
||||
old_uep->next = uep;
|
||||
}
|
||||
|
||||
strcpy(uep->name, name);
|
||||
uep->plugin = pyerl_call_registered;
|
||||
uep->func = callable;
|
||||
uep->next = NULL;
|
||||
|
||||
uerl.uep_cnt++;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
@@ -342,12 +342,12 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
uwsgi_log("invalid Pump response.\n");
|
||||
goto clear;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+35
-21
@@ -80,9 +80,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
int id = uwsgi_apps_cnt;
|
||||
int multiapp = 0;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
int i;
|
||||
#endif
|
||||
|
||||
char *mountpoint;
|
||||
|
||||
@@ -320,9 +318,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
// add start_response on WSGI app
|
||||
Py_INCREF((PyObject *)up.wsgi_spitout);
|
||||
wi->wsgi_args = PyTuple_New(wi->argc);
|
||||
wi->args = PyTuple_New(wi->argc);
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
|
||||
if (PyTuple_SetItem(wi->args, 1, up.wsgi_spitout)) {
|
||||
uwsgi_log("unable to set start_response in args tuple\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -370,24 +368,25 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
PyThreadState_Swap(up.main_thread);
|
||||
}
|
||||
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
|
||||
}
|
||||
const char *default_app = "";
|
||||
|
||||
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
|
||||
uwsgi_rawlog(" (default app)");
|
||||
default_app = " (default app)" ;
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
|
||||
uwsgi_rawlog("\n");
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
|
||||
if (multiapp > 1) {
|
||||
for(i=1;i<multiapp;i++) {
|
||||
@@ -540,6 +539,7 @@ PyObject *uwsgi_mount_loader(void *arg1) {
|
||||
|
||||
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
|
||||
callable = uwsgi_file_loader((void *)what);
|
||||
if (!callable) exit(1);
|
||||
}
|
||||
else if (!strcmp(what+strlen(what)-4, ".ini")) {
|
||||
callable = uwsgi_paste_loader((void *)what);
|
||||
@@ -606,30 +606,44 @@ PyObject *uwsgi_file_loader(void *arg1) {
|
||||
char *callable = up.callable;
|
||||
if (!callable) callable = "application";
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
|
||||
char *py_filename = uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename));
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
|
||||
if (!wsgi_file_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
|
||||
if (!wsgi_file_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
|
||||
if (!wsgi_file_callable) {
|
||||
PyErr_Print();
|
||||
Py_DECREF(wsgi_file_dict);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
|
||||
uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
|
||||
exit(1);
|
||||
Py_DECREF(wsgi_file_callable);
|
||||
Py_DECREF(wsgi_file_dict);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(py_filename);
|
||||
|
||||
return wsgi_file_callable;
|
||||
|
||||
}
|
||||
|
||||
+119
-26
@@ -29,6 +29,10 @@ struct option uwsgi_python_options[] = {
|
||||
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
|
||||
{"shared-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-pyimport", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-py-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"shared-python-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
|
||||
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
|
||||
@@ -106,9 +110,9 @@ int uwsgi_python_init() {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
char *pyversion = strchr(Py_GetVersion(), '\n');
|
||||
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
#else
|
||||
uwsgi_log("PyPy version: %s\n", PYPY_VERSION);
|
||||
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
@@ -160,7 +164,7 @@ int uwsgi_python_init() {
|
||||
up.reset_ts = simple_reset_ts;
|
||||
|
||||
|
||||
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
|
||||
uwsgi_log_initial("Python main interpreter initialized at %p\n", up.main_thread);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -253,7 +257,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
|
||||
if (!pyfile) {
|
||||
uwsgi_error_open(real_filename);
|
||||
free(real_filename);
|
||||
fclose(pyfile);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -740,6 +743,9 @@ int uwsgi_python_manage_options(int i, char *optarg) {
|
||||
uwsgi.honour_stdin = 1;
|
||||
up.pyshell = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_SHARED_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.shared_import_list, optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_PYIMPORT:
|
||||
uwsgi_string_new_list(&up.import_list, optarg);
|
||||
return 1;
|
||||
@@ -893,17 +899,8 @@ void uwsgi_python_spooler_init(void) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_init_apps() {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
|
||||
#ifndef UWSGI_PYPY
|
||||
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
|
||||
#endif
|
||||
}
|
||||
// this hook will be executed by master (or worker1 when master is not requested, so COW is in place)
|
||||
void uwsgi_python_preinit_apps() {
|
||||
|
||||
init_pyargv();
|
||||
|
||||
@@ -913,11 +910,12 @@ void uwsgi_python_init_apps() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
#ifndef UWSGI_PYPY
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
uwsgi_init_symbol_import();
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (up.test_module != NULL) {
|
||||
@@ -929,6 +927,34 @@ void uwsgi_python_init_apps() {
|
||||
|
||||
init_uwsgi_vars();
|
||||
|
||||
// load shared imports
|
||||
struct uwsgi_string_list *upli = up.shared_import_list;
|
||||
while(upli) {
|
||||
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
|
||||
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
|
||||
}
|
||||
else {
|
||||
if (PyImport_ImportModule(upli->value) == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
upli = upli->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_python_init_apps() {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
// prepare for stack suspend/resume
|
||||
if (uwsgi.async > 1) {
|
||||
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
|
||||
#ifndef UWSGI_PYPY
|
||||
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
|
||||
#endif
|
||||
}
|
||||
|
||||
// setup app loaders
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
|
||||
@@ -1071,6 +1097,9 @@ void uwsgi_python_enable_threads() {
|
||||
up.gil_get = gil_real_get;
|
||||
up.gil_release = gil_real_release;
|
||||
|
||||
up.swap_ts = simple_threaded_swap_ts;
|
||||
up.reset_ts = simple_threaded_reset_ts;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
up.swap_ts = threaded_swap_ts;
|
||||
up.reset_ts = threaded_reset_ts;
|
||||
@@ -1089,8 +1118,34 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
pthread_setspecific(up.upt_save_key, (void *) pts);
|
||||
pthread_setspecific(up.upt_gil_key, (void *) pts);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("pts %d = %p\n", core_id, pts);
|
||||
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_RELEASE_GIL;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1239,38 +1294,44 @@ clear:
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
|
||||
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
uint8_t i;
|
||||
PyObject *pyargs = PyTuple_New(argc);
|
||||
PyObject *ret;
|
||||
char *rv;
|
||||
size_t rl;
|
||||
|
||||
PyObject *pyargs = PyTuple_New(argc);
|
||||
PyObject *ret;
|
||||
|
||||
if (!pyargs)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
|
||||
PyTuple_SetItem(pyargs, i, PyString_FromStringAndSize(argv[i], argvs[i]));
|
||||
}
|
||||
|
||||
ret = python_call((PyObject *) func, pyargs, 0, NULL);
|
||||
|
||||
Py_DECREF(pyargs);
|
||||
if (ret) {
|
||||
if (PyString_Check(ret)) {
|
||||
rv = PyString_AsString(ret);
|
||||
rl = strlen(rv);
|
||||
if (rl <= 0xffff) {
|
||||
rl = PyString_Size(ret);
|
||||
if (rl <= 65536) {
|
||||
memcpy(buffer, rv, rl);
|
||||
Py_DECREF(ret);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return rl;
|
||||
}
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1398,7 +1459,9 @@ int uwsgi_python_mule(char *opt) {
|
||||
|
||||
if (uwsgi_endswith(opt, ".py")) {
|
||||
UWSGI_GET_GIL;
|
||||
uwsgi_pyimport_by_filename("__main__", opt);
|
||||
if (uwsgi_pyimport_by_filename("__main__", opt) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 1;
|
||||
}
|
||||
@@ -1407,6 +1470,33 @@ int uwsgi_python_mule(char *opt) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_python_mule_msg(char *message, size_t len) {
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
PyObject *mule_msg_hook = PyDict_GetItemString(up.embedded_dict, "mule_msg_hook");
|
||||
if (!mule_msg_hook) {
|
||||
// ignore
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *pyargs = PyTuple_New(1);
|
||||
PyTuple_SetItem(pyargs, 0, PyString_FromStringAndSize(message, len));
|
||||
|
||||
PyObject *ret = python_call(mule_msg_hook, pyargs, 0, NULL);
|
||||
Py_DECREF(pyargs);
|
||||
if (ret) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin python_plugin = {
|
||||
|
||||
.name = "python",
|
||||
@@ -1419,6 +1509,8 @@ struct uwsgi_plugin python_plugin = {
|
||||
.short_options = "w:O:H:J:",
|
||||
.request = uwsgi_request_wsgi,
|
||||
.after_request = uwsgi_after_request_wsgi,
|
||||
|
||||
.preinit_apps = uwsgi_python_preinit_apps,
|
||||
.init_apps = uwsgi_python_init_apps,
|
||||
|
||||
.fixup = uwsgi_python_fixup,
|
||||
@@ -1444,6 +1536,7 @@ struct uwsgi_plugin python_plugin = {
|
||||
.rpc = uwsgi_python_rpc,
|
||||
|
||||
.mule = uwsgi_python_mule,
|
||||
.mule_msg = uwsgi_python_mule_msg,
|
||||
|
||||
.spooler = uwsgi_python_spooler,
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "uwsgi_python.h"
|
||||
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
#ifndef UWSGI_PYPY
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
@@ -201,9 +201,14 @@ static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
|
||||
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
|
||||
free(filename);
|
||||
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit;
|
||||
}
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
shit:
|
||||
Py_DECREF(source);
|
||||
free(modname);
|
||||
return mod;
|
||||
@@ -231,9 +236,14 @@ static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) {
|
||||
PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename);
|
||||
free(filename);
|
||||
PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit2;
|
||||
}
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
shit2:
|
||||
Py_DECREF(source);
|
||||
free(modname);
|
||||
return mod;
|
||||
@@ -306,9 +316,14 @@ static PyObject* symimporter_load_module(PyObject *self, PyObject *args) {
|
||||
modname = uwsgi_concat3("sym://", fullname2, "_py");
|
||||
|
||||
code = Py_CompileString(source, modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit;
|
||||
}
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
shit:
|
||||
free(source);
|
||||
free(modname);
|
||||
free(fullname2);
|
||||
@@ -334,9 +349,14 @@ static PyObject* symimporter_load_module(PyObject *self, PyObject *args) {
|
||||
PyDict_SetItemString(dict, "__loader__", self);
|
||||
|
||||
code = Py_CompileString(source, modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit2;
|
||||
}
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
shit2:
|
||||
free(source);
|
||||
free(modname);
|
||||
free(fullname2);
|
||||
@@ -450,7 +470,10 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
|
||||
PyObject *stringio_dict = PyModule_GetDict(stringio);
|
||||
#ifdef PYTHREE
|
||||
PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(body, len));
|
||||
#else
|
||||
PyObject *stringio_dict = PyModule_GetDict(stringio);
|
||||
if (!stringio_dict) {
|
||||
return -1;
|
||||
}
|
||||
@@ -466,7 +489,9 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(body, len));
|
||||
|
||||
|
||||
|
||||
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
|
||||
#endif
|
||||
if (!source_code) {
|
||||
return -1;
|
||||
}
|
||||
@@ -480,7 +505,10 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
}
|
||||
|
||||
|
||||
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
|
||||
#ifdef PYTHREE
|
||||
self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code);
|
||||
#else
|
||||
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
|
||||
if (!zipfile_dict) {
|
||||
return -1;
|
||||
}
|
||||
@@ -494,7 +522,9 @@ zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds)
|
||||
PyObject *zipfile_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(zipfile_args, 0, source_code);
|
||||
|
||||
|
||||
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
|
||||
#endif
|
||||
if (!self->zip) {
|
||||
return -1;
|
||||
}
|
||||
@@ -556,6 +586,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(code_start, code_end-code_start));
|
||||
#else
|
||||
PyObject *stringio_dict = PyModule_GetDict(stringio);
|
||||
if (!stringio_dict) {
|
||||
return -1;
|
||||
@@ -569,7 +602,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
|
||||
PyObject *stringio_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(code_start, code_end-code_start));
|
||||
|
||||
|
||||
PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL);
|
||||
#endif
|
||||
if (!source_code) {
|
||||
return -1;
|
||||
}
|
||||
@@ -579,6 +614,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code);
|
||||
#else
|
||||
PyObject *zipfile_dict = PyModule_GetDict(zipfile);
|
||||
if (!zipfile_dict) {
|
||||
return -1;
|
||||
@@ -592,7 +630,9 @@ symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds
|
||||
PyObject *zipfile_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(zipfile_args, 0, source_code);
|
||||
|
||||
|
||||
self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL);
|
||||
#endif
|
||||
if (!self->zip) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
+371
-232
@@ -11,8 +11,6 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
int ret;
|
||||
struct pollfd pfd[2];
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
@@ -23,60 +21,18 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
wsgi_req->sigwait = 1;
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
if (wait_for_specific_signal) {
|
||||
received_signal = uwsgi_signal_wait(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
pfd[0].fd = uwsgi.signal_socket;
|
||||
pfd[0].events = POLLIN;
|
||||
pfd[1].fd = uwsgi.my_signal_socket;
|
||||
pfd[1].events = POLLIN;
|
||||
cycle:
|
||||
ret = poll(pfd, 2, -1);
|
||||
if (ret > 0) {
|
||||
if (pfd[0].revents == POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
if (uwsgi_signal_handler(received_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
|
||||
}
|
||||
wsgi_req->signal_received = received_signal;
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents == POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi_signal_handler(received_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", received_signal, uwsgi.mywid);
|
||||
}
|
||||
wsgi_req->signal_received = received_signal;
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
return PyString_FromString("");
|
||||
}
|
||||
@@ -192,24 +148,14 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
|
||||
keysize = PyString_Size(key);
|
||||
valsize = PyString_Size(val);
|
||||
if (bufptr + keysize + 2 + valsize + 2 <= buf + *size) {
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
memcpy(bufptr, &keysize, 2);
|
||||
bufptr += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
|
||||
*bufptr++ = (uint8_t) (keysize & 0xff);
|
||||
*bufptr++ = (uint8_t) ((keysize >> 8) & 0xff);
|
||||
memcpy(bufptr, PyString_AsString(key), keysize);
|
||||
bufptr += keysize;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
memcpy(bufptr, &valsize, 2);
|
||||
bufptr += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
|
||||
*bufptr++ = (uint8_t) (valsize & 0xff);
|
||||
*bufptr++ = (uint8_t) ((valsize >> 8) & 0xff);
|
||||
memcpy(bufptr, PyString_AsString(val), valsize);
|
||||
bufptr += valsize;
|
||||
}
|
||||
@@ -264,6 +210,25 @@ PyObject *py_uwsgi_add_cron(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_probe(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int timeout = 0;
|
||||
int freq = 0;
|
||||
char *probe, *probe_args;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Bss|ii:add_probe", &uwsgi_signal, &probe, &probe_args, &timeout, &freq)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_add_probe(uwsgi_signal, probe, probe_args, timeout, freq))
|
||||
return PyErr_Format(PyExc_ValueError, "unable to add probe");
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_add_timer(PyObject * self, PyObject * args) {
|
||||
@@ -319,13 +284,13 @@ PyObject *py_uwsgi_add_file_monitor(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
|
||||
char buffer[0xffff];
|
||||
char *func;
|
||||
uint16_t size = 0;
|
||||
PyObject *py_func;
|
||||
int argc = PyTuple_Size(args);
|
||||
int i;
|
||||
char *argv[0xff];
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
|
||||
// TODO better error reporting
|
||||
if (argc < 1)
|
||||
@@ -339,19 +304,29 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
func = PyString_AsString(py_func);
|
||||
|
||||
for (i = 0; i < (argc - 1); i++) {
|
||||
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 1));
|
||||
PyObject *py_str = PyTuple_GetItem(args, i + 1);
|
||||
if (!PyString_Check(py_str)) {
|
||||
goto clear;
|
||||
}
|
||||
argv[i] = PyString_AsString(py_str);
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
size = uwsgi_rpc(func, argc - 1, argv, buffer);
|
||||
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
return PyString_FromStringAndSize(buffer, size);
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
free(response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
clear:
|
||||
|
||||
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
|
||||
@@ -371,19 +346,15 @@ PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
|
||||
char buffer[0xffff];
|
||||
char *node, *func;
|
||||
char *node = NULL, *func;
|
||||
uint16_t size = 0;
|
||||
PyObject *py_node, *py_func;
|
||||
struct wsgi_request rpc_req;
|
||||
int argc = PyTuple_Size(args);
|
||||
char *argv[0xff];
|
||||
int i, fd;
|
||||
uint16_t pktsize = 0, ulen;
|
||||
char *bufptr;
|
||||
int rlen;
|
||||
int rpc_args = 0;
|
||||
|
||||
int argc = PyTuple_Size(args);
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
|
||||
int i;
|
||||
|
||||
// TODO better error reporting
|
||||
if (argc < 2)
|
||||
@@ -394,9 +365,6 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
if (PyString_Check(py_node)) {
|
||||
node = PyString_AsString(py_node);
|
||||
}
|
||||
else {
|
||||
node = "";
|
||||
}
|
||||
|
||||
py_func = PyTuple_GetItem(args, 1);
|
||||
|
||||
@@ -406,87 +374,28 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
func = PyString_AsString(py_func);
|
||||
|
||||
for (i = 0; i < (argc - 2); i++) {
|
||||
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 2));
|
||||
rpc_args++;
|
||||
PyObject *py_str = PyTuple_GetItem(args, i + 2);
|
||||
if (!PyString_Check(py_str))
|
||||
goto clear;
|
||||
argv[i] = PyString_AsString(py_str);
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
if (!strcmp(node, "")) {
|
||||
if (!rpc_args) {
|
||||
size = uwsgi_rpc(func, 0, NULL, buffer);
|
||||
}
|
||||
else {
|
||||
size = uwsgi_rpc(func, rpc_args, argv, buffer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
// connect to node
|
||||
fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
|
||||
if (fd < 0)
|
||||
goto clear;
|
||||
// prepare a uwsgi array
|
||||
|
||||
pktsize = 2 + strlen(func);
|
||||
for (i = 0; i < argc - 2; i++) {
|
||||
pktsize += 2 + strlen(argv[i]);
|
||||
}
|
||||
|
||||
memset(&rpc_req, 0, sizeof(struct wsgi_request));
|
||||
|
||||
rpc_req.uh.modifier1 = 173;
|
||||
rpc_req.uh.pktsize = pktsize;
|
||||
rpc_req.uh.modifier2 = 0;
|
||||
|
||||
bufptr = buffer;
|
||||
|
||||
ulen = strlen(func);
|
||||
*bufptr++ = (uint8_t) (ulen & 0xff);
|
||||
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
||||
memcpy(bufptr, func, ulen);
|
||||
bufptr += ulen;
|
||||
|
||||
for (i = 0; i < argc - 2; i++) {
|
||||
ulen = strlen(argv[i]);
|
||||
*bufptr++ = (uint8_t) (ulen & 0xff);
|
||||
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
||||
memcpy(bufptr, argv[i], ulen);
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
if (write(fd, &rpc_req.uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, pktsize) != pktsize) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (rlen > 0) {
|
||||
rpc_req.poll.fd = fd;
|
||||
rpc_req.poll.events = POLLIN;
|
||||
rpc_req.buffer = buffer;
|
||||
if (uwsgi_parse_packet(&rpc_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
size = rpc_req.uh.pktsize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
return PyString_FromStringAndSize(buffer, size);
|
||||
}
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
free(response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
|
||||
@@ -508,23 +417,6 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_attach_daemon(PyObject * self, PyObject * args) {
|
||||
|
||||
char *command = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:attach_daemon", &command)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_attach_daemon(command)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_signal_registered(PyObject * self, PyObject * args) {
|
||||
uint8_t uwsgi_signal;
|
||||
|
||||
@@ -562,22 +454,31 @@ PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
ssize_t rlen;
|
||||
char *remote = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "B:signal", &uwsgi_signal)) {
|
||||
if (!PyArg_ParseTuple(args, "B|s:signal", &uwsgi_signal, &remote)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sending %d to master\n", uwsgi_signal);
|
||||
uwsgi_log("sending signal %d to node %s\n", uwsgi_signal, remote);
|
||||
#endif
|
||||
|
||||
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
|
||||
if (rlen != 1) {
|
||||
uwsgi_error("write()");
|
||||
int ret = uwsgi_remote_signal_send(remote, uwsgi_signal);
|
||||
if (ret == 1) goto clear;
|
||||
if (ret == -1)
|
||||
return PyErr_Format(PyExc_IOError, "unable to deliver signal %d to node %s", uwsgi_signal, remote);
|
||||
if (ret == 0)
|
||||
return PyErr_Format(PyExc_ValueError, "node %s rejected signal %d", remote, uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sending signal %d to master\n", uwsgi_signal);
|
||||
#endif
|
||||
uwsgi_signal_send(uwsgi.signal_socket, uwsgi_signal);
|
||||
}
|
||||
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
@@ -1037,7 +938,7 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock);
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -1072,23 +973,127 @@ PyObject *py_uwsgi_embedded_data(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_setprocname(PyObject * self, PyObject * args) {
|
||||
char *name = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:setprocname", &name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi_set_processname(name);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_in_farm(PyObject * self, PyObject * args) {
|
||||
|
||||
char *farm_name = NULL;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|s:in_farm", &farm_name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.muleid == 0) goto none;
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (!farm_name) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!strcmp(farm_name, uwsgi.farms[i].name)) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
none:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_farm_msg(PyObject * self, PyObject * args) {
|
||||
|
||||
char *message = NULL;
|
||||
Py_ssize_t message_len = 0;
|
||||
char *farm_name = NULL;
|
||||
ssize_t len;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ss#:farm_msg", &farm_name, &message, &message_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
|
||||
if (!strcmp(farm_name, uwsgi.farms[i].name)) {
|
||||
len = write(uwsgi.farms[i].queue_pipe[0], message, message_len);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
|
||||
char *message = NULL;
|
||||
Py_ssize_t message_len = 0;
|
||||
int mule_id = 0;
|
||||
ssize_t len;
|
||||
PyObject *mule_obj = NULL;
|
||||
int fd = -1;
|
||||
int mule_id = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#|i:mule_msg", &message, &message_len, &mule_id)) {
|
||||
if (!PyArg_ParseTuple(args, "s#|O:mule_msg", &message, &message_len, &mule_obj)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mule_id == 0) {
|
||||
if (uwsgi.mules_cnt < 1)
|
||||
return PyErr_Format(PyExc_ValueError, "no mule configured");
|
||||
|
||||
if (mule_obj == NULL) {
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
}
|
||||
else if (mule_id > 0 && mule_id <= uwsgi.mules_cnt) {
|
||||
len = write(uwsgi.mules[mule_id-1].queue_pipe[0], message, message_len);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("write()");
|
||||
else {
|
||||
if (PyString_Check(mule_obj)) {
|
||||
struct uwsgi_farm *uf = get_farm_by_name(PyString_AsString(mule_obj));
|
||||
if (uf == NULL) {
|
||||
return PyErr_Format(PyExc_ValueError, "unknown farm");
|
||||
}
|
||||
fd = uf->queue_pipe[0];
|
||||
}
|
||||
else if (PyInt_Check(mule_obj)) {
|
||||
mule_id = PyInt_AsLong(mule_obj);
|
||||
if (mule_id < 0 && mule_id > uwsgi.mules_cnt) {
|
||||
return PyErr_Format(PyExc_ValueError, "invalid mule number");
|
||||
}
|
||||
if (mule_id == 0) {
|
||||
fd = uwsgi.shared->mule_queue_pipe[0];
|
||||
}
|
||||
else {
|
||||
fd = uwsgi.mules[mule_id-1].queue_pipe[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
return PyErr_Format(PyExc_ValueError, "invalid mule");
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
mule_send_msg(fd, message, message_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,27 +1102,104 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_mule_get_msg(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_mule_get_msg(PyObject * self, PyObject * args, PyObject *kwargs) {
|
||||
|
||||
ssize_t len;
|
||||
// this buffer will be configurable
|
||||
char message[65536];
|
||||
ssize_t len = 0;
|
||||
// this buffer is configurable (default 64k)
|
||||
char *message;
|
||||
PyObject *py_manage_signals = NULL;
|
||||
PyObject *py_manage_farms = NULL;
|
||||
size_t buffer_size = 65536;
|
||||
int timeout = -1;
|
||||
int manage_signals = 1, manage_farms = 1;
|
||||
|
||||
static char *kwlist[] = {"signals", "buffer_size", "timeout", "farms", NULL};
|
||||
|
||||
if (uwsgi.muleid == 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "you can receive mule messages only in a mule !!!");
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii:mule_get_msg", kwlist, &py_manage_signals, &py_manage_farms, &buffer_size, &timeout)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// signals and farms are managed by default
|
||||
if (py_manage_signals == Py_None || py_manage_signals == Py_False) {
|
||||
manage_signals = 0;
|
||||
}
|
||||
|
||||
if (py_manage_farms == Py_None || py_manage_farms == Py_False) {
|
||||
manage_farms = 0;
|
||||
}
|
||||
|
||||
message = uwsgi_malloc(buffer_size);
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
len = read(uwsgi.mules[uwsgi.muleid-1].queue_pipe[1], message, 65536);
|
||||
len = uwsgi_mule_get_msg(manage_signals, manage_farms, message, buffer_size, timeout) ;
|
||||
UWSGI_GET_GIL;
|
||||
if (len <= 0) {
|
||||
uwsgi_error("read()");
|
||||
|
||||
if (len < 0) {
|
||||
free(message);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
return PyString_FromStringAndSize(message, len);
|
||||
PyObject *msg = PyString_FromStringAndSize(message, len);
|
||||
free(message);
|
||||
return msg;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_farm_get_msg(PyObject * self, PyObject * args) {
|
||||
|
||||
ssize_t len = 0;
|
||||
// this buffer will be configurable
|
||||
char message[65536];
|
||||
int i, count = 0, pos = 0, ret;
|
||||
struct pollfd *farmpoll;
|
||||
|
||||
if (uwsgi.muleid == 0) {
|
||||
return PyErr_Format(PyExc_ValueError, "you can receive farm messages only in a mule !!!");
|
||||
}
|
||||
UWSGI_RELEASE_GIL;
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) count++;
|
||||
}
|
||||
farmpoll = uwsgi_malloc( sizeof(struct pollfd) * count);
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
if (uwsgi_farm_has_mule(&uwsgi.farms[i], uwsgi.muleid)) {
|
||||
farmpoll[pos].fd = uwsgi.farms[i].queue_pipe[1];
|
||||
farmpoll[pos].events = POLLIN;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = poll(farmpoll, count, -1);
|
||||
if (ret <= 0) {
|
||||
uwsgi_error("poll()");
|
||||
free(farmpoll);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
for(i=0;i<count;i++) {
|
||||
if (farmpoll[i].revents & POLLIN) {
|
||||
len = read(farmpoll[i].fd, message, 65536);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
if (len <= 0) {
|
||||
uwsgi_error("read()");
|
||||
free(farmpoll);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
free(farmpoll);
|
||||
return PyString_FromStringAndSize(message, len);
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_extract(PyObject * self, PyObject * args) {
|
||||
|
||||
char *name;
|
||||
@@ -1508,24 +1590,15 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
valsize = PyString_Size(val);
|
||||
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + UMAX16) {
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
memcpy(cur_buf, &keysize, 2);
|
||||
cur_buf += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
*cur_buf++ = (uint8_t) (keysize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((keysize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(key), keysize);
|
||||
cur_buf += keysize;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
memcpy(cur_buf, &valsize, 2);
|
||||
cur_buf += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
|
||||
*cur_buf++ = (uint8_t) (valsize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((valsize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(val), valsize);
|
||||
cur_buf += valsize;
|
||||
}
|
||||
@@ -1796,13 +1869,18 @@ PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
|
||||
char *host, *message;
|
||||
Py_ssize_t message_len;
|
||||
ssize_t ret;
|
||||
char *uwsgi_message;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ss:send_multicast_message", &host, &message)) {
|
||||
if (!PyArg_ParseTuple(args, "ss#:send_multicast_message", &host, &message, &message_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, host, message, strlen(message));
|
||||
uwsgi_message = uwsgi_malloc(message_len+4);
|
||||
memcpy(uwsgi_message+4, message, message_len);
|
||||
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, 0, host, uwsgi_message, message_len);
|
||||
free(uwsgi_message);
|
||||
|
||||
if (ret <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
@@ -2152,6 +2230,51 @@ PyObject *py_uwsgi_fcgi(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
|
||||
|
||||
char *addr = NULL;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:route", &addr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
|
||||
int uwsgi_fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (uwsgi_fd < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to connect to host %s", addr);
|
||||
}
|
||||
|
||||
if (uwsgi_send_message(uwsgi_fd, wsgi_req->uh.modifier1, wsgi_req->uh.modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, wsgi_req->poll.fd, wsgi_req->post_cl, 0) < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to send uwsgi request to host %s", addr);
|
||||
}
|
||||
|
||||
// request sent, return the iterator response
|
||||
uwsgi_Iter *ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
|
||||
if (!ui) {
|
||||
uwsgi_log("unable to create uwsgi response object, better to reap the process\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ui->fd = uwsgi_fd;
|
||||
ui->timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
ui->close = 1;
|
||||
ui->started = 0;
|
||||
ui->has_cl = 0;
|
||||
ui->sent = 0;
|
||||
ui->size = 0;
|
||||
ui->func = NULL;
|
||||
|
||||
// mark a route request
|
||||
wsgi_req->status = -17;
|
||||
|
||||
return (PyObject *) ui;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *destination = NULL, *pyobj = NULL;
|
||||
@@ -2294,6 +2417,12 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].delta_requests);
|
||||
if (PyDict_SetItemString(worker_dict, "delta_requests", zero)) {
|
||||
goto clear;
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
|
||||
zero = PyLong_FromUnsignedLongLong(uwsgi.workers[i + 1].signals);
|
||||
if (PyDict_SetItemString(worker_dict, "signals", zero)) {
|
||||
goto clear;
|
||||
@@ -2309,6 +2438,9 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
zero = PyString_FromString("cheap");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended) {
|
||||
zero = PyString_FromString("pause");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
zero = PyString_FromFormat("sig%d",uwsgi.workers[i + 1].signum);
|
||||
@@ -2479,12 +2611,13 @@ PyObject *py_uwsgi_logsize(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_mem(PyObject * self, PyObject * args) {
|
||||
|
||||
uint64_t rss=0, vsz = 0;
|
||||
PyObject *ml = PyTuple_New(2);
|
||||
|
||||
get_memusage();
|
||||
get_memusage(&rss, &vsz);
|
||||
|
||||
PyTuple_SetItem(ml, 0, PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].rss_size));
|
||||
PyTuple_SetItem(ml, 1, PyLong_FromUnsignedLongLong(uwsgi.workers[uwsgi.mywid].vsz_size));
|
||||
PyTuple_SetItem(ml, 0, PyLong_FromUnsignedLongLong(rss));
|
||||
PyTuple_SetItem(ml, 1, PyLong_FromUnsignedLongLong(vsz));
|
||||
|
||||
return ml;
|
||||
|
||||
@@ -2636,6 +2769,7 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// use a normal fork here
|
||||
grunt_pid = fork();
|
||||
if (grunt_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
@@ -2786,6 +2920,7 @@ PyObject *py_uwsgi_cluster_best_node(PyObject * self, PyObject * args) {
|
||||
|
||||
static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"send_message", py_uwsgi_send_message, METH_VARARGS, ""},
|
||||
{"route", py_uwsgi_route, METH_VARARGS, ""},
|
||||
{"send_multi_message", py_uwsgi_send_multi_message, METH_VARARGS, ""},
|
||||
{"reload", py_uwsgi_reload, METH_VARARGS, ""},
|
||||
{"stop", py_uwsgi_stop, METH_VARARGS, ""},
|
||||
@@ -2809,9 +2944,9 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
|
||||
{"cl", py_uwsgi_cl, METH_VARARGS, ""},
|
||||
|
||||
{"listen_queue", py_uwsgi_listen_queue, METH_VARARGS, ""},
|
||||
{"setprocname", py_uwsgi_setprocname, METH_VARARGS, ""},
|
||||
|
||||
{"attach_daemon", py_uwsgi_attach_daemon, METH_VARARGS, ""},
|
||||
{"listen_queue", py_uwsgi_listen_queue, METH_VARARGS, ""},
|
||||
|
||||
{"register_signal", py_uwsgi_register_signal, METH_VARARGS, ""},
|
||||
{"signal", py_uwsgi_signal, METH_VARARGS, ""},
|
||||
@@ -2820,6 +2955,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"signal_received", py_uwsgi_signal_received, METH_VARARGS, ""},
|
||||
{"add_file_monitor", py_uwsgi_add_file_monitor, METH_VARARGS, ""},
|
||||
{"add_timer", py_uwsgi_add_timer, METH_VARARGS, ""},
|
||||
{"add_probe", py_uwsgi_add_probe, METH_VARARGS, ""},
|
||||
{"add_rb_timer", py_uwsgi_add_rb_timer, METH_VARARGS, ""},
|
||||
{"add_cron", py_uwsgi_add_cron, METH_VARARGS, ""},
|
||||
|
||||
@@ -2868,7 +3004,10 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"extract", py_uwsgi_extract, METH_VARARGS, ""},
|
||||
|
||||
{"mule_msg", py_uwsgi_mule_msg, METH_VARARGS, ""},
|
||||
{"mule_get_msg", py_uwsgi_mule_get_msg, METH_VARARGS, ""},
|
||||
{"farm_msg", py_uwsgi_farm_msg, METH_VARARGS, ""},
|
||||
{"mule_get_msg", (PyCFunction) py_uwsgi_mule_get_msg, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"farm_get_msg", py_uwsgi_farm_get_msg, METH_VARARGS, ""},
|
||||
{"in_farm", py_uwsgi_in_farm, METH_VARARGS, ""},
|
||||
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
|
||||
|
||||
{NULL, NULL},
|
||||
@@ -2901,7 +3040,7 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, strlen(key))) {
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -2930,7 +3069,7 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %d bytes", (unsigned long long)uwsgi.cache_blocksize, (int) vallen);
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
@@ -2966,7 +3105,7 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %d bytes", (unsigned long long)uwsgi.cache_blocksize, (int) vallen);
|
||||
return PyErr_Format(PyExc_ValueError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
@@ -3010,7 +3149,7 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
else if (uwsgi_cache_exists(key, strlen(key))) {
|
||||
else if (uwsgi_cache_exists(key, keylen)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
|
||||
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
|
||||
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
|
||||
#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
|
||||
|
||||
#define PYTHON_APP_TYPE_WSGI 0
|
||||
#define PYTHON_APP_TYPE_WEB3 1
|
||||
@@ -133,6 +134,7 @@ struct uwsgi_python {
|
||||
|
||||
struct uwsgi_string_list *python_path;
|
||||
struct uwsgi_string_list *import_list;
|
||||
struct uwsgi_string_list *shared_import_list;
|
||||
struct uwsgi_string_list *spooler_import_list;
|
||||
struct uwsgi_string_list *post_pymodule_alias;
|
||||
|
||||
@@ -210,8 +212,6 @@ PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
|
||||
ssize_t uwsgi_sendfile(struct wsgi_request *);
|
||||
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_write(PyObject *, PyObject *);
|
||||
@@ -259,8 +259,10 @@ PyObject *uwsgi_pyimport_by_filename(char *, char *);
|
||||
|
||||
void threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
|
||||
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
|
||||
@@ -275,7 +277,5 @@ char *uwsgi_pythonize(char *);
|
||||
#define uwsgi_pyexit {PyErr_Print();exit(1);}
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef PYTHREE
|
||||
int uwsgi_init_symbol_import(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -192,12 +192,12 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
uwsgi_log("invalid Web3 response.\n");
|
||||
goto clear;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -599,3 +599,23 @@ void simple_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
void simple_threaded_reset_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
|
||||
// restoring main interpreter
|
||||
UWSGI_GET_GIL
|
||||
PyThreadState_Swap(up.main_thread);
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simple_threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
|
||||
// set the interpreter
|
||||
UWSGI_GET_GIL
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,974 @@
|
||||
#include "uwsgi_rack.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
extern struct uwsgi_rack ur;
|
||||
|
||||
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
|
||||
|
||||
VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
|
||||
|
||||
Check_Type(rbmessage, T_STRING);
|
||||
char *message = RSTRING_PTR(rbmessage);
|
||||
size_t len = RSTRING_LEN(rbmessage);
|
||||
|
||||
if (len > 80) {
|
||||
uwsgi_log("- warning message must be max 80 chars, it will be truncated -");
|
||||
memcpy(uwsgi.shared->warning_message, message, 80);
|
||||
uwsgi.shared->warning_message[80] = 0;
|
||||
}
|
||||
else {
|
||||
memcpy(uwsgi.shared->warning_message, message, len);
|
||||
uwsgi.shared->warning_message[len] = 0;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
|
||||
|
||||
Check_Type(msg, T_STRING);
|
||||
|
||||
uwsgi_log("%s\n", RSTRING_PTR(msg));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
return Qtrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
|
||||
|
||||
Check_Type(rbname, T_STRING);
|
||||
char *name = RSTRING_PTR(rbname);
|
||||
uwsgi_set_processname(name);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mem(VALUE *class) {
|
||||
|
||||
uint64_t rss=0, vsz = 0;
|
||||
VALUE ml = rb_ary_new2(2);
|
||||
|
||||
get_memusage(&rss, &vsz);
|
||||
|
||||
rb_ary_store(ml, 0, LONG2NUM(rss));
|
||||
rb_ary_store(ml, 1, LONG2NUM(vsz));
|
||||
|
||||
return ml;
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_request_id(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.workers[uwsgi.mywid].requests);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_worker_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.mywid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_id(VALUE *class) {
|
||||
return INT2NUM(uwsgi.muleid);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_logsize(VALUE *class) {
|
||||
return ULONG2NUM(uwsgi.shared->logsize);
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int fd = -1;
|
||||
int mule_id = -1;
|
||||
|
||||
if (argc == 0) return Qnil;
|
||||
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
char *message = RSTRING_PTR(argv[0]);
|
||||
size_t message_len = RSTRING_LEN(argv[0]);
|
||||
|
||||
if (uwsgi.mules_cnt < 1) {
|
||||
rb_raise(rb_eRuntimeError, "no mule configured");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
}
|
||||
else {
|
||||
if (TYPE(argv[1]) == T_STRING) {
|
||||
struct uwsgi_farm *uf = get_farm_by_name(RSTRING_PTR(argv[1]));
|
||||
if (uf == NULL) {
|
||||
rb_raise(rb_eRuntimeError, "unknown farm");
|
||||
return Qnil;
|
||||
}
|
||||
fd = uf->queue_pipe[0];
|
||||
}
|
||||
else if (TYPE(argv[1]) == T_FIXNUM) {
|
||||
mule_id = NUM2INT(argv[1]);
|
||||
if (mule_id < 0 && mule_id > uwsgi.mules_cnt) {
|
||||
rb_raise(rb_eRuntimeError, "invalid mule number");
|
||||
return Qnil;
|
||||
}
|
||||
if (mule_id == 0) {
|
||||
fd = uwsgi.shared->mule_queue_pipe[0];
|
||||
}
|
||||
else {
|
||||
fd = uwsgi.mules[mule_id-1].queue_pipe[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eRuntimeError, "invalid mule");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
mule_send_msg(fd, message, message_len);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_ruby_hash_mule_callback(VALUE key, VALUE val, VALUE arg_array) {
|
||||
Check_Type(key, T_SYMBOL);
|
||||
ID key_id = SYM2ID(key);
|
||||
const char *key_name = rb_id2name(key_id);
|
||||
|
||||
if (!strcmp(key_name, "signals")) {
|
||||
rb_ary_store(arg_array, 0, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "farms")) {
|
||||
rb_ary_store(arg_array, 1, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "timeout")) {
|
||||
rb_ary_store(arg_array, 2, val);
|
||||
}
|
||||
else if (!strcmp(key_name, "buffer_size")) {
|
||||
rb_ary_store(arg_array, 3, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_mule_get_msg(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int manage_signals = 1;
|
||||
int manage_farms = 1;
|
||||
int timeout = -1;
|
||||
size_t buffer_size = 65536;
|
||||
ssize_t len = 0;
|
||||
char *message;
|
||||
|
||||
if (uwsgi.muleid == 0) {
|
||||
rb_raise(rb_eRuntimeError, "you can receive mule messages only in a mule !!!");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
// 0 = manage_signals
|
||||
// 1 = manage_farms
|
||||
// 2 = timeout
|
||||
// 3 = buffer_size
|
||||
VALUE arg_array = rb_ary_new2(4);
|
||||
Check_Type(argv[0], T_HASH);
|
||||
rb_hash_foreach(argv[0], uwsgi_ruby_hash_mule_callback, arg_array);
|
||||
|
||||
if (rb_ary_entry(arg_array, 0) == Qfalse) {
|
||||
manage_signals = 0;
|
||||
}
|
||||
|
||||
if (rb_ary_entry(arg_array, 1) == Qfalse) {
|
||||
manage_farms = 0;
|
||||
}
|
||||
|
||||
if (TYPE(rb_ary_entry(arg_array,2)) == T_FIXNUM) {
|
||||
timeout = NUM2INT(rb_ary_entry(arg_array,2));
|
||||
}
|
||||
|
||||
if (TYPE(rb_ary_entry(arg_array,3)) == T_FIXNUM || TYPE(rb_ary_entry(arg_array,3)) == T_BIGNUM) {
|
||||
buffer_size = NUM2ULONG(rb_ary_entry(arg_array,3));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message = uwsgi_malloc(buffer_size);
|
||||
|
||||
len = uwsgi_mule_get_msg(manage_signals, manage_farms, message, buffer_size, timeout) ;
|
||||
|
||||
if (len < 0) {
|
||||
free(message);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE msg = rb_str_new(message, len);
|
||||
free(message);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_lock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
lock_num = NUM2INT(argv[0]);
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
rb_raise(rb_eRuntimeError, "Invalid lock number");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_unlock(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
lock_num = NUM2INT(argv[0]);
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
rb_raise(rb_eRuntimeError, "Invalid lock number");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_set(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
Check_Type(rbvalue, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
uint64_t keylen = RSTRING_LEN(rbkey);
|
||||
char *value = RSTRING_PTR(rbvalue);
|
||||
uint64_t vallen = RSTRING_LEN(rbvalue);
|
||||
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (vallen > uwsgi.cache_blocksize) {
|
||||
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
VALUE rack_uwsgi_cache_update(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
Check_Type(rbvalue, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
uint64_t keylen = RSTRING_LEN(rbkey);
|
||||
char *value = RSTRING_PTR(rbvalue);
|
||||
uint64_t vallen = RSTRING_LEN(rbvalue);
|
||||
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (vallen > uwsgi.cache_blocksize) {
|
||||
rb_raise(rb_eRuntimeError, "uWSGI cache items size must be < %llu, requested %llu bytes", (unsigned long long)uwsgi.cache_blocksize, (unsigned long long) vallen);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_set_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_set(class, rbkey, rbvalue);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to set value in uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_cache_update_exc(VALUE *class, VALUE rbkey, VALUE rbvalue) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_update(class, rbkey, rbvalue);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to update value in uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_del(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_exists(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
if (uwsgi_cache_exists(key, keylen)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_cache_get(VALUE *class, VALUE rbkey) {
|
||||
|
||||
Check_Type(rbkey, T_STRING);
|
||||
|
||||
char *key = RSTRING_PTR(rbkey);
|
||||
size_t keylen = RSTRING_LEN(rbkey);
|
||||
|
||||
uint64_t valsize;
|
||||
char *value = NULL;
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return Qnil;
|
||||
}
|
||||
VALUE res = rb_str_new(value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return res;
|
||||
|
||||
}
|
||||
VALUE rack_uwsgi_cache_get_exc(VALUE *class, VALUE rbkey) {
|
||||
VALUE ret;
|
||||
ret = rack_uwsgi_cache_get(class, rbkey);
|
||||
if (ret == Qnil) {
|
||||
rb_raise(rb_eRuntimeError, "unable to get value from uWSGI cache");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbmin, T_FIXNUM);
|
||||
Check_Type(rbhour, T_FIXNUM);
|
||||
Check_Type(rbday, T_FIXNUM);
|
||||
Check_Type(rbmon, T_FIXNUM);
|
||||
Check_Type(rbweek, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int minute = NUM2INT(rbmin);
|
||||
int hour = NUM2INT(rbhour);
|
||||
int day = NUM2INT(rbday);
|
||||
int month = NUM2INT(rbmon);
|
||||
int week = NUM2INT(rbweek);
|
||||
|
||||
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add cron");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(secs, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
|
||||
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
Check_Type(rbsignum, T_FIXNUM);
|
||||
Check_Type(rbfilename, T_STRING);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
char *filename = RSTRING_PTR(rbfilename);
|
||||
|
||||
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add file monitor");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_read(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
Check_Type(arg2, T_FIXNUM);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_write(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_STRING);
|
||||
|
||||
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
|
||||
|
||||
return INT2FIX(fd);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_FIXNUM);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int timeout = NUM2INT(arg);
|
||||
|
||||
if (timeout >= 0) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
return INT2NUM(uwsgi.workers[0].pid);
|
||||
}
|
||||
return INT2NUM(0);
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
if (argc > 0) {
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
uwsgi_signal = NUM2INT(argv[0]);
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
if (wait_for_specific_signal) {
|
||||
received_signal = uwsgi_signal_wait(uwsgi_signal);
|
||||
}
|
||||
else {
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_signal_received(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
return INT2NUM(wsgi_req->signal_received);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
|
||||
if (uwsgi_signal_registered(uwsgi_signal)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
|
||||
|
||||
char *node = NULL, *func;
|
||||
uint16_t size = 0;
|
||||
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
// TODO better error reporting
|
||||
if (argc < 2)
|
||||
goto clear;
|
||||
|
||||
|
||||
VALUE rpc_node = rpc_argv[0];
|
||||
|
||||
if (TYPE(rpc_node) == T_STRING) {
|
||||
node = RSTRING_PTR(rpc_node);
|
||||
}
|
||||
|
||||
|
||||
VALUE rpc_func = rpc_argv[1];
|
||||
|
||||
if (TYPE(rpc_func) != T_STRING)
|
||||
goto clear;
|
||||
|
||||
func = RSTRING_PTR(rpc_func);
|
||||
|
||||
for (i = 0; i < (argc - 2); i++) {
|
||||
VALUE rpc_str = rpc_argv[i + 2];
|
||||
if (TYPE(rpc_str) != T_STRING)
|
||||
goto clear;
|
||||
argv[i] = RSTRING_PTR(rpc_str);
|
||||
argvs[i] = RSTRING_LEN(rpc_str);
|
||||
}
|
||||
|
||||
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
VALUE ret = rb_str_new(response, size);
|
||||
free(response);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
clear:
|
||||
|
||||
rb_raise(rb_eRuntimeError, "unable to call rpc function");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
int rb_argc = 0;
|
||||
|
||||
if (argc < 2) goto clear;
|
||||
if (argc > 2) {
|
||||
Check_Type(argv[2], T_FIXNUM);
|
||||
rb_argc = NUM2INT(argv[2]);
|
||||
}
|
||||
|
||||
Check_Type(argv[0], T_STRING);
|
||||
char *name = RSTRING_PTR(argv[0]);
|
||||
void *func = (void *) argv[1];
|
||||
|
||||
|
||||
if (uwsgi_register_rpc(name, 7, rb_argc, func)) {
|
||||
clear:
|
||||
rb_raise(rb_eRuntimeError, "unable to register rpc function");
|
||||
return Qnil;
|
||||
}
|
||||
rb_gc_register_address(&argv[1]);
|
||||
rb_ary_push(ur.rpc_protector, argv[1]);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
Check_Type(signum, T_FIXNUM);
|
||||
Check_Type(sigkind, T_STRING);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
char *signal_kind = RSTRING_PTR(sigkind);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_gc_register_address(&rbhandler);
|
||||
rb_ary_push(ur.signals_protector, rbhandler);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
|
||||
|
||||
if (argc < 1) {
|
||||
rb_raise(rb_eRuntimeError, "you have to specify a signum");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
Check_Type(argv[0], T_FIXNUM);
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(argv[0]);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_STRING);
|
||||
char *remote = RSTRING_PTR(argv[1]);
|
||||
|
||||
int ret = uwsgi_remote_signal_send(remote, uwsgi_signal);
|
||||
if (ret == 1) return Qtrue;
|
||||
if (ret == -1) {
|
||||
rb_raise(rb_eRuntimeError, "unable to deliver signal %d to node %s", uwsgi_signal, remote);
|
||||
return Qnil;
|
||||
}
|
||||
if (ret == 0) {
|
||||
rb_raise(rb_eRuntimeError, "node %s rejected signal %d", remote, uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_signal_send(uwsgi.signal_socket, uwsgi_signal);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
|
||||
char **sa = (char **) argv;
|
||||
|
||||
char *cur_buf = sa[0];
|
||||
char *watermark = sa[1];
|
||||
|
||||
if (TYPE(rbkey) != T_STRING || TYPE(rbval) != T_STRING) {
|
||||
rb_raise(rb_eRuntimeError, "spool hash must contains only strings");
|
||||
return ST_STOP;
|
||||
}
|
||||
|
||||
char *key = RSTRING_PTR(rbkey); uint16_t keylen = RSTRING_LEN(rbkey);
|
||||
char *val = RSTRING_PTR(rbval); uint16_t vallen = RSTRING_LEN(rbval);
|
||||
|
||||
if (cur_buf + (2+keylen+2+vallen) > watermark) {
|
||||
rb_raise(rb_eRuntimeError, "spool hash size can be no more than 64K");
|
||||
return ST_STOP;
|
||||
}
|
||||
|
||||
*cur_buf++ = (uint8_t) (keylen & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((keylen >> 8) & 0xff);
|
||||
memcpy(cur_buf, key, keylen); cur_buf += keylen;
|
||||
|
||||
*cur_buf++ = (uint8_t) (vallen & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((vallen >> 8) & 0xff);
|
||||
memcpy(cur_buf, val, vallen); cur_buf += vallen;
|
||||
|
||||
// fix the ptr
|
||||
sa[0] = cur_buf;
|
||||
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
|
||||
|
||||
char spool_filename[1024];
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *priority = NULL;
|
||||
long numprio = 0;
|
||||
time_t at = 0;
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
Check_Type(args, T_HASH);
|
||||
|
||||
// priority
|
||||
#ifdef RUBY19
|
||||
VALUE rbprio = rb_hash_lookup(args, rb_str_new2("priority"));
|
||||
#else
|
||||
VALUE rbprio = rb_hash_aref(args, rb_str_new2("priority"));
|
||||
#endif
|
||||
if (TYPE(rbprio) == T_FIXNUM) {
|
||||
numprio = NUM2INT(rbprio);
|
||||
rb_hash_delete(args, rb_str_new2("priority"));
|
||||
}
|
||||
|
||||
// at
|
||||
#ifdef RUBY19
|
||||
VALUE rbat = rb_hash_lookup(args, rb_str_new2("at"));
|
||||
#else
|
||||
VALUE rbat = rb_hash_aref(args, rb_str_new2("at"));
|
||||
#endif
|
||||
if (TYPE(rbat) == T_FIXNUM) {
|
||||
at = NUM2INT(rbat);
|
||||
rb_hash_delete(args, rb_str_new2("at"));
|
||||
}
|
||||
|
||||
// body
|
||||
#ifdef RUBY19
|
||||
VALUE rbbody = rb_hash_lookup(args, rb_str_new2("body"));
|
||||
#else
|
||||
VALUE rbbody = rb_hash_aref(args, rb_str_new2("body"));
|
||||
#endif
|
||||
if (TYPE(rbbody) == T_STRING) {
|
||||
body = RSTRING_PTR(rbbody);
|
||||
body_len = RSTRING_LEN(rbbody);
|
||||
rb_hash_delete(args, rb_str_new2("body"));
|
||||
}
|
||||
|
||||
char *spool_buffer = uwsgi_malloc(UMAX16);
|
||||
char *argv[2];
|
||||
argv[0] = spool_buffer;
|
||||
argv[1] = spool_buffer + UMAX16 ;
|
||||
|
||||
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
|
||||
int ret = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
|
||||
|
||||
if (priority) {
|
||||
free(priority);
|
||||
}
|
||||
|
||||
free(spool_buffer);
|
||||
|
||||
if (ret > 0) {
|
||||
char *slash = uwsgi_get_last_char(spool_filename, '/');
|
||||
if (slash) {
|
||||
return rb_str_new2(slash+1);
|
||||
}
|
||||
return rb_str_new2(spool_filename);
|
||||
}
|
||||
|
||||
rb_raise(rb_eRuntimeError, "unable to spool job");
|
||||
return Qnil;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_rack_init_api() {
|
||||
|
||||
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
|
||||
uwsgi_rack_api("suspend", uwsgi_ruby_suspend, 0);
|
||||
uwsgi_rack_api("masterpid", uwsgi_ruby_masterpid, 0);
|
||||
uwsgi_rack_api("async_sleep", uwsgi_ruby_async_sleep, 1);
|
||||
uwsgi_rack_api("wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
|
||||
uwsgi_rack_api("wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
|
||||
uwsgi_rack_api("async_connect", uwsgi_ruby_async_connect, 1);
|
||||
uwsgi_rack_api("signal", uwsgi_ruby_signal, -1);
|
||||
uwsgi_rack_api("register_signal", uwsgi_ruby_register_signal, 3);
|
||||
uwsgi_rack_api("register_rpc", uwsgi_ruby_register_rpc, -1);
|
||||
uwsgi_rack_api("signal_registered", uwsgi_ruby_signal_registered, 1);
|
||||
uwsgi_rack_api("signal_wait", uwsgi_ruby_signal_wait, -1);
|
||||
uwsgi_rack_api("signal_received", uwsgi_ruby_signal_received, 0);
|
||||
uwsgi_rack_api("add_cron", rack_uwsgi_add_cron, 6);
|
||||
uwsgi_rack_api("add_timer", rack_uwsgi_add_timer, 2);
|
||||
uwsgi_rack_api("add_rb_timer", rack_uwsgi_add_rb_timer, 2);
|
||||
uwsgi_rack_api("add_file_monitor", rack_uwsgi_add_file_monitor, 2);
|
||||
|
||||
uwsgi_rack_api("setprocname", rack_uwsgi_setprocname, 1);
|
||||
uwsgi_rack_api("mem", rack_uwsgi_mem, 0);
|
||||
|
||||
uwsgi_rack_api("lock", rack_uwsgi_lock, -1);
|
||||
uwsgi_rack_api("unlock", rack_uwsgi_unlock, -1);
|
||||
|
||||
uwsgi_rack_api("mule_get_msg", rack_uwsgi_mule_get_msg, -1);
|
||||
uwsgi_rack_api("mule_msg", rack_uwsgi_mule_msg, -1);
|
||||
|
||||
uwsgi_rack_api("request_id", rack_uwsgi_request_id, 0);
|
||||
uwsgi_rack_api("worker_id", rack_uwsgi_worker_id, 0);
|
||||
uwsgi_rack_api("mule_id", rack_uwsgi_mule_id, 0);
|
||||
|
||||
uwsgi_rack_api("i_am_the_spooler", rack_uwsgi_i_am_the_spooler, 0);
|
||||
uwsgi_rack_api("send_to_spooler", rack_uwsgi_send_spool, 1);
|
||||
uwsgi_rack_api("spool", rack_uwsgi_send_spool, 1);
|
||||
|
||||
uwsgi_rack_api("log", rack_uwsgi_log, 1);
|
||||
uwsgi_rack_api("logsize", rack_uwsgi_logsize, 0);
|
||||
|
||||
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
|
||||
|
||||
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
|
||||
|
||||
|
||||
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, 1);
|
||||
uwsgi_rack_api("cache_get!", rack_uwsgi_cache_get_exc, 1);
|
||||
uwsgi_rack_api("cache_exists", rack_uwsgi_cache_exists, 1);
|
||||
uwsgi_rack_api("cache_exists?", rack_uwsgi_cache_exists, 1);
|
||||
uwsgi_rack_api("cache_del", rack_uwsgi_cache_del, 1);
|
||||
uwsgi_rack_api("cache_set", rack_uwsgi_cache_set, 2);
|
||||
uwsgi_rack_api("cache_set!", rack_uwsgi_cache_set_exc, 2);
|
||||
uwsgi_rack_api("cache_update", rack_uwsgi_cache_update, 2);
|
||||
uwsgi_rack_api("cache_update!", rack_uwsgi_cache_update_exc, 2);
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_opt_hash = rb_hash_new();
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
VALUE rb_uwsgi_opt_key = rb_str_new2(uwsgi.exported_opts[i]->key);
|
||||
if ( rb_funcall(uwsgi_rb_opt_hash, rb_intern("has_key?"), 1, rb_uwsgi_opt_key) == Qtrue) {
|
||||
VALUE rb_uwsgi_opt_item = rb_hash_aref(uwsgi_rb_opt_hash, rb_uwsgi_opt_key);
|
||||
if (TYPE(rb_uwsgi_opt_item) == T_ARRAY) {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_ary_push(rb_uwsgi_opt_item, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(rb_uwsgi_opt_item, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
VALUE rb_uwsgi_opt_list = rb_ary_new();
|
||||
rb_ary_push(rb_uwsgi_opt_list, rb_uwsgi_opt_item);
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_ary_push(rb_uwsgi_opt_list, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(rb_uwsgi_opt_list, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_uwsgi_opt_list);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.exported_opts[i]->value == NULL) {
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, Qtrue);
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(uwsgi_rb_opt_hash, rb_uwsgi_opt_key, rb_str_new2(uwsgi.exported_opts[i]->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("OPT"), uwsgi_rb_opt_hash);
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_OK"), INT2NUM(-2));
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_IGNORE"), INT2NUM(0));
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_RETRY"), INT2NUM(-1));
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("VERSION"), rb_str_new2(UWSGI_VERSION));
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("HOSTNAME"), rb_str_new(uwsgi.hostname, uwsgi.hostname_len));
|
||||
if (uwsgi.pidfile) {
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("PIDFILE"), rb_str_new2(uwsgi.pidfile));
|
||||
}
|
||||
|
||||
rb_const_set(rb_uwsgi_embedded, rb_intern("NUMPROC"), INT2NUM(uwsgi.numproc));
|
||||
|
||||
|
||||
}
|
||||
+404
-305
@@ -9,6 +9,12 @@ struct option uwsgi_rack_options[] = {
|
||||
{"rails", required_argument, 0, LONG_ARGS_RAILS},
|
||||
{"rack", required_argument, 0, LONG_ARGS_RACK},
|
||||
{"ruby-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
|
||||
{"rb-gc-freq", required_argument, 0, LONG_ARGS_RUBY_GC_FREQ},
|
||||
{"rb-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"ruby-require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rbrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rubyrequire", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"require", required_argument, 0, LONG_ARGS_RUBY_REQUIRE},
|
||||
{"rbshell", optional_argument, 0, LONG_ARGS_RUBY_SHELL},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
@@ -60,7 +66,7 @@ VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
|
||||
|
||||
// return the whole body as string
|
||||
|
||||
uwsgi_log("rack.input gets is not implemented (req %p)\n", wsgi_req);
|
||||
rb_raise(rb_eRuntimeError, "rack.input::gets is not implemented (req %p)\n", wsgi_req);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -70,7 +76,7 @@ VALUE rb_uwsgi_io_each(VALUE obj, VALUE args) {
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
// yield strings chunks
|
||||
uwsgi_log("rack.input each is not implemented (req %p)\n", wsgi_req);
|
||||
rb_raise(rb_eRuntimeError, "rack.input::each is not implemented (req %p)\n", wsgi_req);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
@@ -82,7 +88,6 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
VALUE chunk;
|
||||
int chunk_size;
|
||||
|
||||
|
||||
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
|
||||
return Qnil;
|
||||
}
|
||||
@@ -102,8 +107,9 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
wsgi_req->buf_pos+=chunk_size;
|
||||
return RARRAY_PTR(args)[1];
|
||||
}
|
||||
chunk = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
|
||||
wsgi_req->buf_pos+=chunk_size;
|
||||
return rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
@@ -127,6 +133,10 @@ VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
|
||||
RUBY_GLOBAL_SETUP
|
||||
#endif
|
||||
|
||||
VALUE uwsgi_require_file(VALUE arg) {
|
||||
return rb_funcall(rb_cObject, rb_intern("require"), 1, arg);
|
||||
}
|
||||
|
||||
VALUE require_rack(VALUE arg) {
|
||||
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("rack"));
|
||||
}
|
||||
@@ -139,202 +149,57 @@ VALUE require_rails(VALUE arg) {
|
||||
#endif
|
||||
}
|
||||
|
||||
VALUE require_thin(VALUE arg) {
|
||||
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("thin"));
|
||||
}
|
||||
|
||||
VALUE init_rack_app(VALUE);
|
||||
|
||||
VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
|
||||
if (uwsgi_signal_registered(uwsgi_signal)) {
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qfalse;
|
||||
VALUE rack_call_rpc_handler(VALUE args) {
|
||||
VALUE rpc_args = rb_ary_entry(args, 1);
|
||||
return rb_funcall2(rb_ary_entry(args, 0), rb_intern("call"), RARRAY_LEN(rpc_args), RARRAY_PTR(rpc_args));
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_register_signal(VALUE *class, VALUE signum, VALUE sigkind, VALUE rbhandler) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
char *signal_kind = RSTRING_PTR(sigkind);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, (void *) rbhandler, 7)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to register signal %d", uwsgi_signal);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
rb_gc_register_address(&rbhandler);
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_signal(VALUE *class, VALUE signum) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(signum);
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = write(uwsgi.signal_socket, &uwsgi_signal, 1);
|
||||
if (rlen != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_call_signal_handler(VALUE args) {
|
||||
|
||||
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
|
||||
}
|
||||
|
||||
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
uint8_t i;
|
||||
VALUE rb_args = rb_ary_new2(2);
|
||||
VALUE rb_rpc_args = rb_ary_new2(argc);
|
||||
VALUE ret;
|
||||
int error = 0;
|
||||
char *rv;
|
||||
size_t rl;
|
||||
|
||||
VALUE rbhandler = (VALUE) handler;
|
||||
VALUE args = rb_ary_new2(2);
|
||||
rb_ary_store(args, 0, rbhandler);
|
||||
VALUE rbsig = INT2NUM(sig);
|
||||
rb_ary_store(args, 1, rbsig);
|
||||
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
return -1;
|
||||
rb_ary_store(rb_args, 0, (VALUE) func);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
rb_ary_store(rb_rpc_args, i, rb_str_new(argv[i], argvs[i]));
|
||||
}
|
||||
rb_ary_store(rb_args, 1, rb_rpc_args);
|
||||
|
||||
|
||||
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// free resources (useless ?)
|
||||
rb_gc_unregister_address(&args);
|
||||
rb_gc_unregister_address(&ret);
|
||||
rb_gc_unregister_address(&rbsig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_cron(VALUE *class, VALUE rbsignum, VALUE rbmin, VALUE rbhour, VALUE rbday, VALUE rbmon, VALUE rbweek) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int minute = NUM2INT(rbmin);
|
||||
int hour = NUM2INT(rbhour);
|
||||
int day = NUM2INT(rbday);
|
||||
int month = NUM2INT(rbmon);
|
||||
int week = NUM2INT(rbweek);
|
||||
|
||||
if (uwsgi_signal_add_cron(uwsgi_signal, minute, hour, day, month, week)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add cron");
|
||||
return Qnil;
|
||||
if (TYPE(ret) == T_STRING) {
|
||||
rv = RSTRING_PTR(ret);
|
||||
rl = RSTRING_LEN(ret);
|
||||
if (rl <= 0xffff) {
|
||||
memcpy(buffer, rv, rl);
|
||||
return rl;
|
||||
}
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) {
|
||||
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
int seconds = NUM2INT(secs);
|
||||
|
||||
|
||||
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add rb_timer");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) {
|
||||
|
||||
uint8_t uwsgi_signal = NUM2INT(rbsignum);
|
||||
char *filename = RSTRING_PTR(rbfilename);
|
||||
|
||||
if (uwsgi_add_file_monitor(uwsgi_signal, filename)) {
|
||||
rb_raise(rb_eRuntimeError, "unable to add file monitor");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_read(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
int fd = NUM2INT(arg1);
|
||||
int timeout = NUM2INT(arg2);
|
||||
|
||||
if (fd >= 0) {
|
||||
async_add_fd_write(wsgi_req, fd, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
|
||||
int fd = uwsgi_connect(RSTRING_PTR(arg), 0, 1);
|
||||
|
||||
return INT2FIX(fd);
|
||||
}
|
||||
|
||||
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int timeout = NUM2INT(arg);
|
||||
|
||||
if (timeout >= 0) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
VALUE uwsgi_ruby_suspend(VALUE *class) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
|
||||
return Qtrue;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
@@ -350,15 +215,12 @@ int uwsgi_rack_init(){
|
||||
http_sc->message_size = (int) strlen(http_sc->message);
|
||||
}
|
||||
|
||||
ur.unprotected = 0;
|
||||
|
||||
#ifdef RUBY19
|
||||
ruby_sysinit(&argc, &argv);
|
||||
RUBY_INIT_STACK
|
||||
ruby_init();
|
||||
ruby_process_options(argc, argv);
|
||||
#else
|
||||
|
||||
ruby_init();
|
||||
ruby_init_loadpath();
|
||||
#endif
|
||||
@@ -366,26 +228,36 @@ int uwsgi_rack_init(){
|
||||
|
||||
ruby_script("uwsgi");
|
||||
|
||||
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
|
||||
rb_define_module_function(rb_uwsgi_embedded, "suspend", uwsgi_ruby_suspend, 0);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "async_sleep", uwsgi_ruby_async_sleep, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "async_connect", uwsgi_ruby_async_connect, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal", uwsgi_ruby_signal, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "register_signal", uwsgi_ruby_register_signal, 3);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "signal_registered", uwsgi_ruby_signal_registered, 1);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_cron", rack_uwsgi_add_cron, 6);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_timer", rack_uwsgi_add_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_rb_timer", rack_uwsgi_add_rb_timer, 2);
|
||||
rb_define_module_function(rb_uwsgi_embedded, "add_file_monitor", rack_uwsgi_add_file_monitor, 2);
|
||||
ur.signals_protector = rb_ary_new();
|
||||
ur.rpc_protector = rb_ary_new();
|
||||
rb_gc_register_address(&ur.signals_protector);
|
||||
rb_gc_register_address(&ur.rpc_protector);
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
uwsgi_rack_init_api();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_call_new(VALUE obj) {
|
||||
return rb_funcall(obj, rb_intern("new"), 0);
|
||||
}
|
||||
|
||||
void uwsgi_rack_init_apps(void) {
|
||||
|
||||
int error;
|
||||
ur.app_id = uwsgi_apps_cnt;
|
||||
struct uwsgi_string_list *usl = ur.rbrequire;
|
||||
|
||||
while(usl) {
|
||||
error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (ur.rack) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
|
||||
@@ -407,6 +279,10 @@ void uwsgi_rack_init_apps(void) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!access("config.ru", R_OK)) {
|
||||
uwsgi_log("!!! a config.ru file has been found in yor rails app, please use --rack <configfile> instead of the old --rails <app> !!!\n");
|
||||
}
|
||||
|
||||
uwsgi_log("loading rails app %s\n", ur.rails);
|
||||
rb_protect( require_rails, 0, &error ) ;
|
||||
if (error) {
|
||||
@@ -416,13 +292,53 @@ void uwsgi_rack_init_apps(void) {
|
||||
uwsgi_log("rails app %s ready\n", ur.rails);
|
||||
VALUE ac = rb_const_get(rb_cObject, rb_intern("ActionController"));
|
||||
|
||||
ur.dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
|
||||
ur.dispatcher = Qnil;
|
||||
if (rb_funcall(ac, rb_intern("const_defined?"), 1, ID2SYM(rb_intern("Dispatcher"))) == Qtrue) {
|
||||
|
||||
VALUE ac_dispatcher = rb_const_get(ac, rb_intern("Dispatcher"));
|
||||
|
||||
VALUE acd_instance_methods = rb_funcall( ac_dispatcher, rb_intern("instance_methods"), 0);
|
||||
|
||||
VALUE acim_call = rb_funcall( acd_instance_methods, rb_intern("include?"), 1, ID2SYM(rb_intern("call")));
|
||||
|
||||
if (acim_call == Qfalse) {
|
||||
acim_call = rb_funcall( acd_instance_methods, rb_intern("include?"), 1, rb_str_new2("call"));
|
||||
}
|
||||
|
||||
if (acim_call == Qtrue) {
|
||||
ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ur.dispatcher == Qnil) {
|
||||
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
|
||||
rb_protect( require_thin, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
exit(1);
|
||||
}
|
||||
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
VALUE thin_rack_adapter = rb_const_get(thin_rack, rb_intern("Adapter"));
|
||||
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
|
||||
ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ur.dispatcher == Qnil) {
|
||||
uwsgi_log("unable to load rails dispatcher\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rb_gc_register_address(&ur.dispatcher);
|
||||
|
||||
goto ready;
|
||||
}
|
||||
|
||||
@@ -448,6 +364,14 @@ ready:
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
|
||||
rb_define_method(ur.rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
|
||||
|
||||
uwsgi_add_app(ur.app_id, 7, (char*)"", 0);
|
||||
if (ur.gc_freq <= 1) {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: AGGRESSIVE)\n", ur.app_id, ur.call);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("RACK app %d loaded at %p (GC frequency: %d)\n", ur.app_id, ur.call, ur.gc_freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VALUE call_dispatch(VALUE env) {
|
||||
@@ -456,7 +380,7 @@ VALUE call_dispatch(VALUE env) {
|
||||
|
||||
}
|
||||
|
||||
VALUE send_body(VALUE obj) {
|
||||
static VALUE send_body(VALUE obj) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
ssize_t len = 0;
|
||||
@@ -474,6 +398,15 @@ VALUE send_body(VALUE obj) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE body_to_path(VALUE body) {
|
||||
return rb_funcall( body, rb_intern("to_path"), 0);
|
||||
}
|
||||
|
||||
|
||||
VALUE close_body(VALUE body) {
|
||||
return rb_funcall( body, rb_intern("close"), 0);
|
||||
}
|
||||
|
||||
VALUE iterate_body(VALUE body) {
|
||||
|
||||
#ifdef RUBY19
|
||||
@@ -481,7 +414,6 @@ VALUE iterate_body(VALUE body) {
|
||||
#else
|
||||
return rb_iterate(rb_each, body, send_body, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
VALUE send_header(VALUE obj, VALUE headers) {
|
||||
@@ -516,63 +448,50 @@ VALUE send_header(VALUE obj, VALUE headers) {
|
||||
}
|
||||
|
||||
if (TYPE(hkey) != T_STRING || TYPE(hval) != T_STRING) {
|
||||
goto clear2;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
//uwsgi_log("header: %.*s: %.*s\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), RSTRING_LEN(hval), RSTRING_PTR(hval));
|
||||
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, ": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
|
||||
char *header_value = RSTRING_PTR(hval);
|
||||
int header_value_len = RSTRING_LEN(hval);
|
||||
size_t header_value_len = RSTRING_LEN(hval);
|
||||
size_t i,cnt=0;
|
||||
char *this_header = header_value;
|
||||
|
||||
char *header_value_splitted = memchr(header_value, '\n', header_value_len);
|
||||
for(i=0;i<header_value_len;i++) {
|
||||
// multiline header, send it !!!
|
||||
if (header_value[i] == '\n') {
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
|
||||
if (!header_value_splitted) {
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_len);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, "\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
//uwsgi_log("(multi) --%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
|
||||
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
this_header += cnt+1;
|
||||
cnt = 0;
|
||||
continue;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
else {
|
||||
header_value_splitted[0] = 0;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_splitted-header_value);
|
||||
|
||||
if (cnt > 0) {
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, "\r\n", 2);
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
header_value = header_value_splitted+1;
|
||||
header_value_len -= header_value_splitted-header_value;
|
||||
|
||||
while(header_value_len && (header_value_splitted = memchr(header_value, '\n', header_value_len))) {
|
||||
header_value_splitted[0] = 0;
|
||||
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, ": ", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, header_value, header_value_splitted-header_value);
|
||||
wsgi_req->headers_size += len;
|
||||
len = wsgi_req->socket->proto_write( wsgi_req, "\r\n", 2);
|
||||
wsgi_req->headers_size += len;
|
||||
wsgi_req->header_cnt++;
|
||||
|
||||
header_value = header_value_splitted+1;
|
||||
header_value_len -= header_value_splitted-header_value;
|
||||
}
|
||||
//uwsgi_log("--%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
|
||||
}
|
||||
|
||||
|
||||
clear2:
|
||||
rb_gc_unregister_address(&hkey);
|
||||
rb_gc_unregister_address(&hval);
|
||||
|
||||
clear:
|
||||
|
||||
return Qnil;
|
||||
@@ -608,6 +527,9 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = ur.app_id;
|
||||
uwsgi_apps[wsgi_req->app_id].requests++;
|
||||
|
||||
|
||||
env = rb_hash_new();
|
||||
|
||||
@@ -625,6 +547,8 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
) {
|
||||
rb_hash_aset(env, rb_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
|
||||
rb_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len));
|
||||
|
||||
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -666,19 +590,13 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
|
||||
|
||||
|
||||
if (ur.unprotected) {
|
||||
ret = rb_funcall(ur.dispatcher, ur.call, 1, env);
|
||||
}
|
||||
else {
|
||||
ret = rb_protect( call_dispatch, env, &error);
|
||||
}
|
||||
|
||||
ret = rb_protect( call_dispatch, env, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
//return -1;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (TYPE(ret) == T_ARRAY) {
|
||||
if (RARRAY_LEN(ret) != 3) {
|
||||
uwsgi_log("Invalid RACK response size: %d\n", RARRAY_LEN(ret));
|
||||
@@ -723,50 +641,40 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
headers = RARRAY_PTR(ret)[1] ;
|
||||
if (rb_respond_to( headers, rb_intern("each") )) {
|
||||
if (ur.unprotected) {
|
||||
#ifdef RUBY19
|
||||
rb_block_call(headers, rb_intern("each"), 0, 0, send_header, headers);
|
||||
#else
|
||||
rb_iterate(rb_each, headers, send_header, headers);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
rb_protect( iterate_headers, headers, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rb_gc_unregister_address(&status);
|
||||
rb_gc_unregister_address(&headers);
|
||||
goto clear;
|
||||
}
|
||||
rb_protect( iterate_headers, headers, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->socket->proto_write(wsgi_req, "\r\n", 2) != 2) {
|
||||
if (wsgi_req->socket->proto_write(wsgi_req, (char *)"\r\n", 2) != 2) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
body = RARRAY_PTR(ret)[2] ;
|
||||
|
||||
if (rb_respond_to( body, rb_intern("to_path") )) {
|
||||
VALUE sendfile_path = rb_funcall( body, rb_intern("to_path"), 0);
|
||||
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
|
||||
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
|
||||
if (wsgi_req->response_size > 0) {
|
||||
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
|
||||
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
VALUE sendfile_path = rb_protect( body_to_path, body, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
else {
|
||||
wsgi_req->sendfile_fd = open(RSTRING_PTR(sendfile_path), O_RDONLY);
|
||||
wsgi_req->response_size = uwsgi_sendfile(wsgi_req);
|
||||
if (wsgi_req->response_size > 0) {
|
||||
while(wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
|
||||
//uwsgi_log("sendfile_fd_size = %d\n", wsgi_req->sendfile_fd_size);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
}
|
||||
}
|
||||
// we need to close it...
|
||||
close(wsgi_req->sendfile_fd);
|
||||
}
|
||||
rb_gc_unregister_address(&sendfile_path);
|
||||
|
||||
}
|
||||
else if (rb_respond_to( body, rb_intern("each") )) {
|
||||
if (ur.unprotected) {
|
||||
#ifdef RUBY19
|
||||
rb_block_call(body, rb_intern("each"), 0, 0, send_body, 0);
|
||||
#else
|
||||
rb_iterate(rb_each, body, send_body, 0);
|
||||
#endif
|
||||
iterate_body(body);
|
||||
}
|
||||
else {
|
||||
rb_protect( iterate_body, body, &error);
|
||||
@@ -778,30 +686,23 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (rb_respond_to( body, rb_intern("close") )) {
|
||||
//uwsgi_log("calling close\n");
|
||||
rb_funcall( body, rb_intern("close"), 0);
|
||||
rb_protect( close_body, body, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
}
|
||||
|
||||
//fine:
|
||||
|
||||
/* unregister all the objects created */
|
||||
|
||||
rb_gc_unregister_address(&status);
|
||||
rb_gc_unregister_address(&headers);
|
||||
rb_gc_unregister_address(&body);
|
||||
|
||||
}
|
||||
else {
|
||||
internal_server_error(wsgi_req, "Invalid RACK response");
|
||||
internal_server_error(wsgi_req, (char *)"Invalid RACK response");
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
rb_gc_unregister_address(&ret);
|
||||
|
||||
rb_gc_unregister_address(&env);
|
||||
|
||||
if (ur.gc_freq <= 1 || ur.cycles%ur.gc_freq == 0) {
|
||||
//uwsgi_log("calling ruby GC\n");
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("calling ruby GC\n");
|
||||
#endif
|
||||
rb_gc();
|
||||
}
|
||||
|
||||
@@ -835,6 +736,9 @@ int uwsgi_rack_manage_options(int i, char *optarg) {
|
||||
case LONG_ARGS_RUBY_GC_FREQ:
|
||||
ur.gc_freq = atoi(optarg);
|
||||
return 1;
|
||||
case LONG_ARGS_RUBY_REQUIRE:
|
||||
uwsgi_string_new_list(&ur.rbrequire, optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -850,6 +754,44 @@ void uwsgi_rack_resume(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("RESUMING RUBY\n");
|
||||
}
|
||||
|
||||
#ifdef RUBY19
|
||||
VALUE uwsgi_call_block(VALUE body, VALUE block) {
|
||||
|
||||
return rb_funcall(block, rb_intern("call"), 1, body );
|
||||
}
|
||||
|
||||
VALUE uwsgi_rack_patch_body_proxy_each(int argc, VALUE *argv, VALUE self) {
|
||||
|
||||
VALUE block = Qnil;
|
||||
rb_scan_args(argc, argv, "0&", &block);
|
||||
|
||||
if(!RTEST(block)) {
|
||||
rb_raise(rb_eArgError, "a block is required");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE original_body = rb_iv_get(self, "@body");
|
||||
if (original_body != Qnil) {
|
||||
return rb_block_call(original_body, rb_intern("each"), 0, 0, uwsgi_call_block, block);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE uwsgi_rack_patch_body_proxy(VALUE foo) {
|
||||
|
||||
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
VALUE rack_body_proxy = rb_const_get(rack, rb_intern("BodyProxy"));
|
||||
|
||||
if (!rb_respond_to(rack_body_proxy, rb_intern("each"))) {
|
||||
rb_define_method(rack_body_proxy, "each", uwsgi_rack_patch_body_proxy_each, -1);
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
#endif
|
||||
|
||||
VALUE init_rack_app( VALUE script ) {
|
||||
|
||||
int error;
|
||||
@@ -864,6 +806,14 @@ VALUE init_rack_app( VALUE script ) {
|
||||
}
|
||||
|
||||
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
|
||||
#ifdef RUBY19
|
||||
VALUE ret = rb_protect(uwsgi_rack_patch_body_proxy, rack, &error);
|
||||
if (!error && ret != Qnil) {
|
||||
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
VALUE rackup = rb_funcall( rb_const_get(rack, rb_intern("Builder")), rb_intern("parse_file"), 1, script);
|
||||
if (TYPE(rackup) != T_ARRAY) {
|
||||
uwsgi_log("unable to parse %s file\n", RSTRING_PTR(script));
|
||||
@@ -924,6 +874,148 @@ int uwsgi_rack_mount_app(char *mountpoint, char *app) {
|
||||
void uwsgi_rack_hijack(void) {
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule(char *opt) {
|
||||
int error = 0;
|
||||
|
||||
if (uwsgi_endswith(opt, (char *)".rb")) {
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_pfh(VALUE args) {
|
||||
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("post_fork_hook"))) {
|
||||
return rb_funcall(uwsgi_rb_embedded, rb_intern("post_fork_hook"), 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void uwsgi_rb_post_fork() {
|
||||
int error = 0;
|
||||
|
||||
// call the post_fork_hook
|
||||
rb_protect(uwsgi_rb_pfh, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_mmh(VALUE args) {
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
return rb_funcall(uwsgi_rb_embedded, rb_intern("mule_msg_hook"), 1, args);
|
||||
}
|
||||
|
||||
int uwsgi_rack_mule_msg(char *message, size_t len) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
if (rb_respond_to(uwsgi_rb_embedded, rb_intern("mule_msg_hook"))) {
|
||||
VALUE arg = rb_str_new(message, len);
|
||||
rb_protect(uwsgi_rb_mmh, arg, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
VALUE rack_call_signal_handler(VALUE args) {
|
||||
|
||||
return rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1, rb_ary_entry(args, 1));
|
||||
}
|
||||
|
||||
int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
|
||||
VALUE rbhandler = (VALUE) handler;
|
||||
VALUE args = rb_ary_new2(2);
|
||||
rb_ary_store(args, 0, rbhandler);
|
||||
VALUE rbsig = INT2NUM(sig);
|
||||
rb_ary_store(args, 1, rbsig);
|
||||
rb_protect(rack_call_signal_handler, args, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
|
||||
rb_gc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_do_spooler(VALUE args) {
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
return rb_funcall(uwsgi_rb_embedded, rb_intern("spooler"), 1, args);
|
||||
}
|
||||
|
||||
void uwsgi_ruby_add_item(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
VALUE *spool_dict = (VALUE*) data;
|
||||
|
||||
rb_hash_aset(*spool_dict, rb_str_new(key, keylen), rb_str_new(val, vallen));
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size_t body_len) {
|
||||
|
||||
int error = 0;
|
||||
|
||||
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
|
||||
if (!rb_respond_to(uwsgi_rb_embedded, rb_intern("spooler"))) {
|
||||
rb_gc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE spool_dict = rb_hash_new();
|
||||
|
||||
if (uwsgi_hooked_parse(buf, len, uwsgi_ruby_add_item, (void *) &spool_dict)) {
|
||||
rb_gc();
|
||||
// malformed packet, destroy it
|
||||
return 0;
|
||||
}
|
||||
|
||||
rb_hash_aset(spool_dict, rb_str_new2("spooler_task_name"), rb_str_new2(filename));
|
||||
|
||||
if (body && body_len > 0) {
|
||||
rb_hash_aset(spool_dict, rb_str_new2("body"), rb_str_new(body, body_len));
|
||||
}
|
||||
|
||||
VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error);
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TYPE(ret) == T_FIXNUM) {
|
||||
rb_gc();
|
||||
return NUM2INT(ret);
|
||||
}
|
||||
|
||||
// error, retry
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.name = "rack",
|
||||
@@ -936,7 +1028,10 @@ struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.signal_handler = uwsgi_rack_signal_handler,
|
||||
|
||||
.hijack = uwsgi_rack_hijack,
|
||||
.hijack_worker = uwsgi_rack_hijack,
|
||||
.post_fork = uwsgi_rb_post_fork,
|
||||
|
||||
.spooler = uwsgi_rack_spooler,
|
||||
|
||||
.init_apps = uwsgi_rack_init_apps,
|
||||
//.mount_app = uwsgi_rack_mount_app,
|
||||
@@ -944,6 +1039,10 @@ struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.magic = uwsgi_rack_magic,
|
||||
|
||||
.mule = uwsgi_rack_mule,
|
||||
.mule_msg = uwsgi_rack_mule_msg,
|
||||
.rpc = uwsgi_ruby_rpc,
|
||||
|
||||
.suspend = uwsgi_rack_suspend,
|
||||
.resume = uwsgi_rack_resume,
|
||||
};
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#define LONG_ARGS_RUBY_GC_FREQ LONG_ARGS_RACK_BASE + 2
|
||||
#define LONG_ARGS_RACK LONG_ARGS_RACK_BASE + 3
|
||||
#define LONG_ARGS_RUBY_SHELL LONG_ARGS_RACK_BASE + 4
|
||||
#define LONG_ARGS_RUBY_REQUIRE LONG_ARGS_RACK_BASE + 5
|
||||
|
||||
#ifndef RUBY19
|
||||
#include <st.h>
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
#define RUBY_GVL_LOCK
|
||||
#define RUBY_GVL_UNLOCK
|
||||
@@ -52,16 +54,26 @@ struct uwsgi_rack {
|
||||
uint64_t cycles;
|
||||
|
||||
int call_gc;
|
||||
|
||||
// why why why !!!!????!!!???
|
||||
VALUE signals_protector;
|
||||
VALUE rpc_protector;
|
||||
|
||||
VALUE dispatcher;
|
||||
VALUE rb_uwsgi_io_class;
|
||||
ID call;
|
||||
VALUE fibers[200];
|
||||
int unprotected;
|
||||
|
||||
pthread_mutex_t gvl;
|
||||
|
||||
int rb_shell;
|
||||
int app_id;
|
||||
|
||||
int unprotected;
|
||||
|
||||
struct uwsgi_string_list *rbrequire;
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_ruby_exception(void);
|
||||
void uwsgi_rack_init_api(void);
|
||||
|
||||
+22
-18
@@ -7,33 +7,37 @@ try:
|
||||
except:
|
||||
RUBYPATH = 'ruby'
|
||||
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
rbconfig = 'Config'
|
||||
|
||||
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
|
||||
v = version.split('.')
|
||||
|
||||
GCC_LIST = ['rack_plugin']
|
||||
GCC_LIST = ['rack_plugin', 'rack_api']
|
||||
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
rbconfig = 'RbConfig'
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip()
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
|
||||
LDFLAGS.append('-L' + libpath )
|
||||
os.environ['LD_RUN_PATH'] = libpath
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ extern struct uwsgi_server uwsgi;
|
||||
int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
uint8_t argc = 0xff;
|
||||
|
||||
/* Standard RPC request */
|
||||
@@ -24,7 +25,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("RPC pktsize %d\n", wsgi_req->uh.pktsize);
|
||||
#endif
|
||||
|
||||
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
|
||||
if (uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
|
||||
uwsgi_log("Invalid RPC request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -33,7 +34,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_log("RPC args %d\n", argc-1);
|
||||
#endif
|
||||
|
||||
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, wsgi_req->buffer);
|
||||
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, wsgi_req->buffer);
|
||||
|
||||
if (wsgi_req->uh.modifier2 == 0) {
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, (char *)&wsgi_req->uh, 4);
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define RRDTOOL_OPT_BASE 177000
|
||||
#define RRDTOOL_OPT_RRDTOOL RRDTOOL_OPT_BASE+1
|
||||
#define RRDTOOL_OPT_RRDTOOL_MAX_DS RRDTOOL_OPT_BASE+2
|
||||
#define RRDTOOL_OPT_RRDTOOL_FREQ RRDTOOL_OPT_BASE+3
|
||||
|
||||
struct uwsgi_rrdtool {
|
||||
void *lib;
|
||||
int (*create)(int, char **);
|
||||
int (*update)(int, char **);
|
||||
struct uwsgi_string_list *rrd;
|
||||
int max_ds;
|
||||
int freq;
|
||||
|
||||
char *update_area;
|
||||
} u_rrd;
|
||||
|
||||
struct option rrdtool_options[] = {
|
||||
{"rrdtool", required_argument, 0, RRDTOOL_OPT_RRDTOOL},
|
||||
{"rrdtool-freq", required_argument, 0, RRDTOOL_OPT_RRDTOOL_FREQ},
|
||||
{"rrdtool-max-ds", required_argument, 0, RRDTOOL_OPT_RRDTOOL_MAX_DS},
|
||||
{0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
int rrdtool_init() {
|
||||
|
||||
u_rrd.lib = dlopen("librrd.so", RTLD_LAZY);
|
||||
if (!u_rrd.lib) return -1;
|
||||
|
||||
u_rrd.create = dlsym(u_rrd.lib, "rrd_create");
|
||||
if (!u_rrd.create) {
|
||||
dlclose(u_rrd.lib);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u_rrd.update = dlsym(u_rrd.lib, "rrd_update");
|
||||
if (!u_rrd.update) {
|
||||
dlclose(u_rrd.lib);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!u_rrd.max_ds) u_rrd.max_ds = 30;
|
||||
|
||||
uwsgi_log_initial("*** RRDtool library available at %p ***\n", u_rrd.lib);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rrdtool_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case RRDTOOL_OPT_RRDTOOL:
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi_string_new_list(&u_rrd.rrd, optarg);
|
||||
return 1;
|
||||
case RRDTOOL_OPT_RRDTOOL_MAX_DS:
|
||||
u_rrd.max_ds = atoi(optarg);
|
||||
return 1;
|
||||
case RRDTOOL_OPT_RRDTOOL_FREQ:
|
||||
u_rrd.freq = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrdtool_post_init() {
|
||||
|
||||
struct uwsgi_string_list *usl = u_rrd.rrd;
|
||||
char **argv;
|
||||
int i;
|
||||
|
||||
if (!u_rrd.lib || !u_rrd.create) return;
|
||||
|
||||
// do not waste time if no --rrdtool option is defiend
|
||||
if (!u_rrd.rrd) return;
|
||||
|
||||
if (uwsgi.numproc > u_rrd.max_ds) {
|
||||
uwsgi_log("!!! NOT ENOUGH SLOTS IN RRDTOOL DS TO HOST WORKERS DATA (increase them with --rrdtool-max-ds) !!!\n");
|
||||
dlclose(u_rrd.lib);
|
||||
return;
|
||||
}
|
||||
|
||||
// alloc space for DS_REQ + DS WORKER + RRA + create + filename
|
||||
argv = uwsgi_malloc( sizeof(char *) * (1 + u_rrd.max_ds + 4 + 1 +1));
|
||||
|
||||
argv[0] = "create";
|
||||
|
||||
argv[2] = "DS:requests:DERIVE:600:0:U";
|
||||
|
||||
// create DS for workers
|
||||
for(i=0;i<u_rrd.max_ds;i++) {
|
||||
int max_size = sizeof("DS:worker65536:DERIVE:600:0:U")+1;
|
||||
argv[3+i] = uwsgi_malloc( max_size );
|
||||
if (snprintf(argv[3+i], max_size, "DS:worker%d:DERIVE:600:0:U", i+1) < 25) {
|
||||
uwsgi_log("unable to create args for rrd_create()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// create RRA
|
||||
argv[3+u_rrd.max_ds] = "RRA:AVERAGE:0.5:1:288" ;
|
||||
argv[3+u_rrd.max_ds+1] = "RRA:AVERAGE:0.5:12:168" ;
|
||||
argv[3+u_rrd.max_ds+2] = "RRA:AVERAGE:0.5:288:31" ;
|
||||
argv[3+u_rrd.max_ds+3] = "RRA:AVERAGE:0.5:2016:52";
|
||||
|
||||
while(usl) {
|
||||
if (!uwsgi_file_exists(usl->value)) {
|
||||
argv[1] = usl->value;
|
||||
if (u_rrd.create((1 + u_rrd.max_ds + 4 + 1 +1), argv)) {
|
||||
uwsgi_error("rrd_create()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
usl->value = realpath(usl->value, NULL);
|
||||
if (!usl->value) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
// free DS
|
||||
for(i=0;i<u_rrd.max_ds;i++) {
|
||||
free(argv[3+i]);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
|
||||
//now allocate memory for updates
|
||||
u_rrd.update_area = uwsgi_malloc( 1+((1+sizeof(UMAX64_STR)) * (u_rrd.max_ds+1))+1 );
|
||||
memset(u_rrd.update_area, 0, 1+((1+sizeof(UMAX64_STR)) * (u_rrd.max_ds+1))+1 );
|
||||
|
||||
u_rrd.update_area[0] = 'N';
|
||||
|
||||
if (u_rrd.freq < 1) u_rrd.freq = 300;
|
||||
|
||||
}
|
||||
|
||||
void rrdtool_master_cycle() {
|
||||
|
||||
static time_t last_update = 0;
|
||||
char *ptr;
|
||||
int rlen, i;
|
||||
char *argv[3];
|
||||
struct uwsgi_string_list *usl = u_rrd.rrd;
|
||||
|
||||
if (!u_rrd.lib || !u_rrd.create || !u_rrd.rrd) return ;
|
||||
|
||||
if (last_update == 0) last_update = time(NULL);
|
||||
|
||||
// update
|
||||
if (uwsgi.current_time - last_update >= u_rrd.freq) {
|
||||
ptr = u_rrd.update_area+1;
|
||||
rlen = snprintf(ptr, 1+sizeof(UMAX64_STR), ":%llu", (unsigned long long )uwsgi.workers[0].requests);
|
||||
if (rlen < 2) return;
|
||||
ptr+=rlen;
|
||||
for(i=0;i<u_rrd.max_ds;i++) {
|
||||
if (i+1 <= uwsgi.numproc) {
|
||||
rlen = snprintf(ptr, 1+sizeof(UMAX64_STR), ":%llu", (unsigned long long )uwsgi.workers[1+i].requests);
|
||||
if (rlen < 2) return;
|
||||
}
|
||||
else {
|
||||
memcpy(ptr, ":U", 2);
|
||||
rlen = 2;
|
||||
}
|
||||
ptr+=rlen;
|
||||
}
|
||||
last_update = uwsgi.current_time;
|
||||
argv[0] = "update";
|
||||
argv[2] = u_rrd.update_area;
|
||||
while(usl) {
|
||||
argv[1] = usl->value;
|
||||
if (u_rrd.update(3, argv)) {
|
||||
uwsgi_log_verbose("ERROR: rrd_update(\"%s\", \"%s\")\n", argv[1], argv[2]);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin rrdtool_plugin = {
|
||||
|
||||
.options = rrdtool_options,
|
||||
.manage_opt = rrdtool_opt,
|
||||
|
||||
.master_cycle = rrdtool_master_cycle,
|
||||
|
||||
.post_init = rrdtool_post_init,
|
||||
.init = rrdtool_init,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='rrdtool'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['rrdtool']
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define MAX_SYSLOG_PKT 1024
|
||||
|
||||
ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
char buf[MAX_SYSLOG_PKT];
|
||||
time_t current_time;
|
||||
int portn = 514;
|
||||
int rlen;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!uwsgi.choosen_logger_arg) {
|
||||
uwsgi_log_safe("invalid rsyslog syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ul->fd);
|
||||
|
||||
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (comma) {
|
||||
ul->data = comma+1;
|
||||
*comma = 0;
|
||||
}
|
||||
else {
|
||||
ul->data = uwsgi_concat2(uwsgi.hostname," uwsgi");
|
||||
}
|
||||
|
||||
|
||||
char *port = strchr(uwsgi.choosen_logger_arg, ':');
|
||||
if (port) {
|
||||
portn = atoi(port+1);
|
||||
*port = 0;
|
||||
}
|
||||
|
||||
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, NULL, portn, &ul->addr.sa_in);
|
||||
|
||||
if (port) *port = ':';
|
||||
if (comma) *comma = ',';
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
|
||||
current_time = time(NULL);
|
||||
|
||||
// drop newline
|
||||
if (message[len-1] == '\n') len--;
|
||||
|
||||
rlen = snprintf(buf, MAX_SYSLOG_PKT, "<29>%.*s %s: %.*s", 15, ctime(¤t_time)+4, (char *) ul->data, (int) len, message);
|
||||
if (rlen > 0) {
|
||||
return sendto(ul->fd, buf, rlen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rsyslog_register() {
|
||||
uwsgi_register_logger("rsyslog", uwsgi_rsyslog_logger);
|
||||
}
|
||||
|
||||
int uwsgi_rsyslog_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin rsyslog_plugin = {
|
||||
|
||||
.name = "rsyslog",
|
||||
.on_load = uwsgi_rsyslog_register,
|
||||
.init = uwsgi_rsyslog_init
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='rsyslog'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['rsyslog_plugin']
|
||||
@@ -3,34 +3,43 @@ import os,sys
|
||||
NAME='ruby19'
|
||||
|
||||
try:
|
||||
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
|
||||
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
|
||||
except:
|
||||
RUBYPATH = 'ruby'
|
||||
RUBYPATH = 'ruby'
|
||||
|
||||
GCC_LIST = ['../rack/rack_plugin']
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
rbconfig = 'Config'
|
||||
|
||||
version = os.popen(RUBYPATH + " -e \"print RUBY_VERSION\"").read().rstrip()
|
||||
v = version.split('.')
|
||||
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS.append('-DRUBY19')
|
||||
GCC_LIST = ['../rack/rack_plugin', '../rack/rack_api']
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
if v[0] == '1' and v[1] == '9':
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
CFLAGS.append('-DRUBY19')
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
rbconfig = 'RbConfig'
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['CFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
|
||||
if includedir == 'nil':
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + includedir)
|
||||
else:
|
||||
CFLAGS.append('-I' + includedir)
|
||||
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
|
||||
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
|
||||
CFLAGS.append('-I' + archdir)
|
||||
CFLAGS.append('-I' + archdir + '/' + arch)
|
||||
CFLAGS.append('-I' + includedir + '/' + arch)
|
||||
|
||||
CFLAGS.append('-Drack_plugin=ruby19_plugin')
|
||||
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['LDFLAGS']\"").read().rstrip().split()
|
||||
LDFLAGS.append('-L' + os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['libdir']\"").read().rstrip() )
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + Config::CONFIG['RUBY_SO_NAME']\"").read().rstrip().split()
|
||||
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
|
||||
LDFLAGS.append('-L' + libpath )
|
||||
os.environ['LD_RUN_PATH'] = libpath
|
||||
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* request 110 */
|
||||
int uwsgi_request_signal(struct wsgi_request *wsgi_req) {
|
||||
|
||||
ssize_t len;
|
||||
uint8_t ret_status = 1;
|
||||
if (uwsgi_signal_send(uwsgi.signal_socket, wsgi_req->uh.modifier2) < 0) {
|
||||
ret_status = 0;
|
||||
}
|
||||
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = ret_status;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin signal_plugin = {
|
||||
|
||||
.name = "signal",
|
||||
.modifier1 = 110,
|
||||
.request = uwsgi_request_signal,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='signal'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['signal_plugin']
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
char *syslog_opts;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
setlinebuf(stderr);
|
||||
|
||||
if (uwsgi.choosen_logger_arg == NULL) {
|
||||
syslog_opts = "uwsgi";
|
||||
}
|
||||
else {
|
||||
syslog_opts = uwsgi.choosen_logger_arg;
|
||||
}
|
||||
|
||||
openlog(syslog_opts, 0, LOG_DAEMON);
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "%.*s", (int) len, message);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_syslog_register() {
|
||||
uwsgi_register_logger("syslog", uwsgi_syslog_logger);
|
||||
}
|
||||
|
||||
int uwsgi_syslog_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin syslog_plugin = {
|
||||
|
||||
.name = "syslog",
|
||||
.on_load = uwsgi_syslog_register,
|
||||
.init = uwsgi_syslog_init
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='syslog'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['syslog_plugin']
|
||||
+33
-8
@@ -124,9 +124,18 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
base = ptr;
|
||||
while (ptr < watermark) {
|
||||
if (*ptr == '?' && !query_string) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
|
||||
wsgi_req->path_info = watermark;
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
wsgi_req->path_info_pos = 3;
|
||||
query_string = ptr + 1;
|
||||
}
|
||||
@@ -136,9 +145,18 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
|
||||
wsgi_req->uri_len = ptr - base;
|
||||
|
||||
if (!query_string) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
if (watermark + (ptr - base) < (char *)(wsgi_req->proto_parser_buf + uwsgi.buffer_size)) {
|
||||
wsgi_req->path_info = watermark;
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
http_url_decode(base, &wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, base, ptr - base);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
wsgi_req->path_info_pos = 5;
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
|
||||
}
|
||||
@@ -238,6 +256,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
ssize_t remains;
|
||||
// make this buffer configurable
|
||||
char post_buf[8192];
|
||||
char *post_tail = NULL;
|
||||
|
||||
// first round ? this memory area will be freed by async_loop
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
@@ -299,6 +318,10 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
else if (*ptr == '\n' && wsgi_req->proto_parser_status == 3) {
|
||||
ptr++;
|
||||
remains = len - (j + 1);
|
||||
if (remains > 0) {
|
||||
post_tail = uwsgi_malloc(remains);
|
||||
memcpy(post_tail, ptr, remains);
|
||||
}
|
||||
http_parse(wsgi_req, ptr);
|
||||
//is there a Content_Length ?
|
||||
if (wsgi_req->post_cl > 0) {
|
||||
@@ -310,13 +333,15 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
wsgi_req->proto_parser_pos = 0;
|
||||
remains = UMIN((size_t) remains, wsgi_req->post_cl);
|
||||
if (remains) {
|
||||
if (!fwrite(ptr, remains, 1, wsgi_req->async_post)) {
|
||||
if (remains && post_tail) {
|
||||
if (!fwrite(post_tail, remains, 1, wsgi_req->async_post)) {
|
||||
free(post_tail);
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
uwsgi_error("fwrite()");
|
||||
fclose(wsgi_req->async_post);
|
||||
return -1;
|
||||
}
|
||||
free(post_tail);
|
||||
wsgi_req->proto_parser_pos += remains;
|
||||
if (wsgi_req->proto_parser_pos >= wsgi_req->post_cl) {
|
||||
free(wsgi_req->proto_parser_buf);
|
||||
|
||||
+261
-85
@@ -123,16 +123,21 @@ time_t parse_http_date(char *date, uint16_t len) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
|
||||
ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
int fd;
|
||||
struct sockaddr_in udp_addr;
|
||||
char *udp_port;
|
||||
ssize_t ret;
|
||||
char udpbuff[1024];
|
||||
|
||||
if (message_size + 4 > 1024)
|
||||
return -1;
|
||||
struct uwsgi_header *uh;
|
||||
|
||||
if (message) {
|
||||
uh = (struct uwsgi_header *) message;
|
||||
}
|
||||
else {
|
||||
uh = (struct uwsgi_header *) uwsgi_malloc(4);
|
||||
}
|
||||
|
||||
udp_port = strchr(host, ':');
|
||||
if (udp_port == NULL) {
|
||||
@@ -152,22 +157,15 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
|
||||
udp_addr.sin_port = htons(atoi(udp_port+1));
|
||||
udp_addr.sin_addr.s_addr = inet_addr(host);
|
||||
|
||||
udpbuff[0] = modifier1;
|
||||
uh->modifier1 = modifier1;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
message_size = uwsgi_swap16(message_size);
|
||||
uh->pktsize = uwsgi_swap16(message_size);
|
||||
#else
|
||||
uh->pktsize = message_size;
|
||||
#endif
|
||||
uh->modifier2 = modifier2;
|
||||
|
||||
memcpy(udpbuff+1, &message_size, 2);
|
||||
|
||||
udpbuff[3] = 0;
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
message_size = uwsgi_swap16(message_size);
|
||||
#endif
|
||||
|
||||
memcpy(udpbuff+4, message, message_size);
|
||||
|
||||
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
ret = sendto(fd, (char *) uh, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
}
|
||||
@@ -175,6 +173,10 @@ ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t
|
||||
|
||||
udp_port[0] = ':';
|
||||
|
||||
if ((char *)uh != message) {
|
||||
free(uh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -280,7 +282,9 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &pfd, sizeof(int));
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("passing fd\n");
|
||||
#endif
|
||||
cnt = sendmsg(fd, &msg, 0);
|
||||
}
|
||||
else {
|
||||
@@ -340,6 +344,59 @@ ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *m
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
|
||||
|
||||
char *ptr = (char *) uh;
|
||||
size_t remains = 4;
|
||||
int ret = -1;
|
||||
int rlen;
|
||||
ssize_t len;
|
||||
|
||||
while(remains > 0) {
|
||||
rlen = uwsgi_waitfd(fd, timeout);
|
||||
if (rlen > 0) {
|
||||
len = read(fd, ptr, remains);
|
||||
if (len <= 0) break;
|
||||
remains -= len;
|
||||
ptr += len;
|
||||
if (remains == 0) {
|
||||
ret = uh->modifier2;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// timed out ?
|
||||
else if (ret == 0) ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf && uh->pktsize > 0) {
|
||||
if (*buf == NULL)
|
||||
*buf = uwsgi_malloc(uh->pktsize);
|
||||
remains = uh->pktsize;
|
||||
ptr = *buf;
|
||||
ret = -1;
|
||||
while(remains > 0) {
|
||||
rlen = uwsgi_waitfd(fd, timeout);
|
||||
if (rlen > 0) {
|
||||
len = read(fd, ptr, remains);
|
||||
if (len <= 0) break;
|
||||
remains -= len;
|
||||
ptr += len;
|
||||
if (remains == 0) {
|
||||
ret = uh->modifier2;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// timed out ?
|
||||
else if (ret == 0) ret = -2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
|
||||
int rlen;
|
||||
@@ -367,9 +424,9 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
|
||||
}
|
||||
if (status < 0) {
|
||||
if (status == -1)
|
||||
uwsgi_log("error parsing request\n");
|
||||
uwsgi_log_verbose("error parsing request\n");
|
||||
else if (status == -2)
|
||||
uwsgi_log("open-close packet (ping/check) received\n");
|
||||
uwsgi_log_verbose("open-close packet (ping/check) received\n");
|
||||
//close(upoll->fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -378,7 +435,7 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
|
||||
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint16_t argvs[], uint8_t *argc) {
|
||||
|
||||
char *ptrbuf, *bufferend;
|
||||
uint16_t strsize = 0;
|
||||
@@ -403,7 +460,10 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
// item
|
||||
argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
|
||||
argvs[*argc] = strsize;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arg %s\n", argv[*argc]);
|
||||
#endif
|
||||
ptrbuf += strsize;
|
||||
*argc = *argc + 1;
|
||||
}
|
||||
@@ -496,6 +556,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
char *ptrbuf, *bufferend;
|
||||
|
||||
uint16_t strsize = 0;
|
||||
struct uwsgi_dyn_dict *udd;
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + wsgi_req->uh.pktsize;
|
||||
@@ -802,26 +863,69 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for static files
|
||||
|
||||
// skip extensions
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
if (wsgi_req->path_info_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(wsgi_req->path_info+(wsgi_req->path_info_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
|
||||
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
|
||||
if (!uwsgi_file_serve(wsgi_req, uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len, uwsgi.check_static, uwsgi.check_static_len)) {
|
||||
udd = uwsgi.check_static;
|
||||
while(udd) {
|
||||
// need to build the path ?
|
||||
if (udd->value == NULL) {
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
|
||||
#endif
|
||||
udd->value = realpath(udd->key, NULL);
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
if (!udd->value) goto nextcs;
|
||||
udd->vallen = strlen(udd->value);
|
||||
}
|
||||
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
return -1;
|
||||
}
|
||||
nextcs:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
// check static-map
|
||||
struct uwsgi_static_map *usm = uwsgi.static_maps;
|
||||
while(usm) {
|
||||
udd = uwsgi.static_maps;
|
||||
while(udd) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, usm->mountpoint_len, usm->mountpoint);
|
||||
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
|
||||
#endif
|
||||
if (udd->status == 0) {
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
|
||||
#endif
|
||||
char *real_docroot = realpath(udd->value, NULL);
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
if (!real_docroot) goto nextsm;
|
||||
udd->value = real_docroot;
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1;
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, usm->mountpoint, usm->mountpoint_len)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, usm->document_root, usm->document_root_len, wsgi_req->path_info+usm->mountpoint_len, wsgi_req->path_info_len-usm->mountpoint_len, usm->orig_document_root, usm->orig_document_root_len)) {
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
usm = usm->next;
|
||||
nextsm:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1379,17 +1483,73 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, char *orig_document_root, uint16_t orig_document_root_len) {
|
||||
int uwsgi_append_static_path(char *dir, char *file, int file_len) {
|
||||
|
||||
size_t len = strlen(dir);
|
||||
|
||||
if (len + 1 + file_len > PATH_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir[len-1] == '/') {
|
||||
memcpy(dir+len, file, file_len);
|
||||
dir[len+file_len] = 0;
|
||||
}
|
||||
else {
|
||||
dir[len] = '/';
|
||||
memcpy(dir+len+1, file, file_len);
|
||||
dir[len+1+file_len] = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_static_stat(char *filename, struct stat *st) {
|
||||
|
||||
int ret = stat(filename, st);
|
||||
// if non-existant return -1
|
||||
if (ret < 0) return -1;
|
||||
|
||||
if (S_ISREG(st->st_mode)) return 0;
|
||||
|
||||
// check for index
|
||||
if (S_ISDIR(st->st_mode)) {
|
||||
struct uwsgi_string_list *usl = uwsgi.static_index;
|
||||
while(usl) {
|
||||
ret = uwsgi_append_static_path(filename, usl->value, usl->len);
|
||||
if (ret >= 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
#endif
|
||||
if (!uwsgi_static_stat(filename, st)) {
|
||||
return 0;
|
||||
}
|
||||
// reset to original name
|
||||
filename[ret] = 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
|
||||
|
||||
struct stat st;
|
||||
char real_filename[PATH_MAX];
|
||||
struct iovec headers_vec[8];
|
||||
char real_filename[PATH_MAX+1];
|
||||
char content_length[sizeof(UMAX64_STR)+1];
|
||||
size_t real_filename_len = 0;
|
||||
|
||||
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("unable to get realpath() of the static file\n");
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
@@ -1398,23 +1558,34 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
if (!stat(real_filename, &st)) {
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &st)) {
|
||||
int mime_type_size = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
|
||||
char http_last_modified[49];
|
||||
real_filename_len = strlen(real_filename);
|
||||
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
|
||||
if (wsgi_req->if_modified_since_len) {
|
||||
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
|
||||
if (st.st_mtime <= ims) {
|
||||
wsgi_req->status = 304;
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 304 Not Modified\r\n", 19);
|
||||
headers_vec[0].iov_base = wsgi_req->protocol;
|
||||
headers_vec[0].iov_len = wsgi_req->protocol_len;
|
||||
headers_vec[1].iov_base = " 304 Not Modified\r\n";
|
||||
headers_vec[1].iov_len = 19;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
while(ah) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
headers_vec[0].iov_base = ah->value;
|
||||
headers_vec[0].iov_len = ah->len;
|
||||
headers_vec[1].iov_base = "\r\n";
|
||||
headers_vec[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
@@ -1422,84 +1593,89 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
|
||||
char http_last_modified[49];
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("file %s found\n", real_filename);
|
||||
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
|
||||
#endif
|
||||
// no need to set content-type/content-length, they will be fixed by the http server/router
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 200 OK\r\n", 9);
|
||||
// HTTP status
|
||||
headers_vec[0].iov_base = wsgi_req->protocol;
|
||||
headers_vec[0].iov_len = wsgi_req->protocol_len;
|
||||
headers_vec[1].iov_base = " 200 OK\r\n";
|
||||
headers_vec[1].iov_len = 9;
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
|
||||
|
||||
// uWSGI additional headers
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
while(ah) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
headers_vec[0].iov_base = ah->value;
|
||||
headers_vec[0].iov_len = ah->len;
|
||||
headers_vec[1].iov_base = "\r\n";
|
||||
headers_vec[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
headers_vec[0].iov_base = "Content-Type: ";
|
||||
headers_vec[0].iov_len = 14;
|
||||
headers_vec[1].iov_base = mime_type;
|
||||
headers_vec[1].iov_len = mime_type_size;
|
||||
headers_vec[2].iov_base = "\r\n";
|
||||
headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
wsgi_req->header_cnt++;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "Content-Type: ", 14);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, mime_type, mime_type_size);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
}
|
||||
|
||||
// nginx
|
||||
if (uwsgi.file_serve_mode == 1) {
|
||||
wsgi_req->header_cnt += 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
|
||||
if (orig_document_root[orig_document_root_len-1] != '/') {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
|
||||
}
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
headers_vec[0].iov_base = "X-Accel-Redirect: "; headers_vec[0].iov_len = 18 ;
|
||||
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
|
||||
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
}
|
||||
// apache
|
||||
else if (uwsgi.file_serve_mode == 2) {
|
||||
headers_vec[0].iov_base = "X-Sendfile: "; headers_vec[0].iov_len = 12 ;
|
||||
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
|
||||
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Sendfile: ", 12);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, orig_document_root, orig_document_root_len);
|
||||
if (orig_document_root[orig_document_root_len-1] != '/') {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
|
||||
}
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
}
|
||||
// raw
|
||||
else {
|
||||
wsgi_req->header_cnt += 1;
|
||||
// set Content-Length
|
||||
headers_vec[0].iov_base = "Content-Length: ";
|
||||
headers_vec[0].iov_len = 16;
|
||||
headers_vec[1].iov_len = uwsgi_long2str2n(st.st_size, content_length, sizeof(UMAX64_STR)+1);
|
||||
headers_vec[1].iov_base = content_length;
|
||||
headers_vec[2].iov_base = "\r\n";
|
||||
headers_vec[2].iov_len = 2;
|
||||
// this is the final header (\r\n added)
|
||||
set_http_date(st.st_mtime, http_last_modified);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
headers_vec[3].iov_base = http_last_modified;
|
||||
headers_vec[3].iov_len = 48;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
|
||||
wsgi_req->header_cnt += 2;
|
||||
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
|
||||
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
|
||||
// here we need to close the sendfile fd (no-GC involved)
|
||||
close(wsgi_req->sendfile_fd);
|
||||
}
|
||||
|
||||
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t *len) {
|
||||
|
||||
int i;
|
||||
*len = 0;
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
if (!uwsgi_strncmp(key, strlen(key), wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
|
||||
*len = wsgi_req->hvec[i + 1].iov_len;
|
||||
return wsgi_req->hvec[i + 1].iov_base;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifdef UWSGI_PCRE
|
||||
#include "uwsgi.h"
|
||||
|
||||
void uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
|
||||
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
|
||||
|
||||
const char *errstr;
|
||||
int erroff;
|
||||
@@ -9,15 +9,17 @@ void uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra) {
|
||||
*pattern = pcre_compile( (const char *)re, 0, &errstr, &erroff, NULL);
|
||||
if (!*pattern) {
|
||||
uwsgi_log("pcre error: %s at offset %d\n", errstr, erroff);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pattern_extra = (pcre_extra *) pcre_study((const pcre*)*pattern, 0, &errstr);
|
||||
if (!*pattern_extra) {
|
||||
pcre_free(*pattern);
|
||||
uwsgi_log("pcre (study) error: %s\n", errstr);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -26,32 +28,4 @@ int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject,
|
||||
return pcre_exec((const pcre*)pattern, (const pcre_extra *)pattern_extra, subject, length, 0, 0, NULL, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
void uwsgi_regexp_match(regexp, what) {
|
||||
|
||||
int ret,i;
|
||||
|
||||
for(i=0;i<uwsgi->nroutes;i++) {
|
||||
|
||||
ret = pcre_exec(ur->pattern, ur->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len, 0, 0, wsgi_req->ovector, (ur->args+1)*3 );
|
||||
|
||||
if (ret >= 0) {
|
||||
if (ur->action) {
|
||||
ur->action(uwsgi, wsgi_req, ur);
|
||||
}
|
||||
else {
|
||||
uwsgi_route_action_wsgi(uwsgi, wsgi_req, ur);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check for errors if < 0 && != NO_MATCH
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
||||
|
||||
struct uwsgi_rpc *urpc = NULL;
|
||||
int i;
|
||||
@@ -50,9 +50,93 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
|
||||
|
||||
if (urpc) {
|
||||
if (uwsgi.p[urpc->modifier1]->rpc) {
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, output);
|
||||
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t *len) {
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
struct uwsgi_header uh;
|
||||
char *buffer = NULL;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(65536);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
// connect to node
|
||||
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
|
||||
if (fd < 0) return NULL;
|
||||
|
||||
// prepare a uwsgi array
|
||||
uint16_t buffer_size = 2 + strlen(func);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
buffer_size += 2 + argvs[i];
|
||||
}
|
||||
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(65536);
|
||||
|
||||
uh.modifier1 = 173;
|
||||
uh.pktsize = buffer_size;
|
||||
uh.modifier2 = 0;
|
||||
|
||||
// add func to the array
|
||||
char *bufptr = buffer;
|
||||
ulen = strlen(func);
|
||||
*bufptr++ = (uint8_t) (ulen & 0xff);
|
||||
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
||||
memcpy(bufptr, func, ulen);
|
||||
bufptr += ulen;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
ulen = argvs[i];
|
||||
*bufptr++ = (uint8_t) (ulen & 0xff);
|
||||
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
||||
memcpy(bufptr, argv[i], ulen);
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (write(fd, buffer, buffer_size) != buffer_size) {
|
||||
uwsgi_error("write()");
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
*len = uh.pktsize;
|
||||
if (*len == 0) {
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
|
||||
}
|
||||
|
||||
+11
-1
@@ -106,6 +106,7 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
|
||||
#else
|
||||
static size_t nosf_buf_size = 0;
|
||||
static char *nosf_buf;
|
||||
char *nosf_buf2;
|
||||
|
||||
ssize_t jlen = 0;
|
||||
ssize_t rlen = 0;
|
||||
@@ -115,7 +116,16 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
|
||||
nosf_buf = malloc(chunk);
|
||||
}
|
||||
else if (chunk != nosf_buf_size) {
|
||||
nosf_buf = realloc(nosf_buf, chunk);
|
||||
nosf_buf2 = realloc(nosf_buf, chunk);
|
||||
if (!nosf_buf2) {
|
||||
free(nosf_buf);
|
||||
}
|
||||
nosf_buf = nosf_buf2;
|
||||
}
|
||||
|
||||
if (!nosf_buf) {
|
||||
uwsgi_error("sendfile malloc()/realloc()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nosf_buf_size = chunk;
|
||||
|
||||
@@ -9,8 +9,16 @@ from setuptools.command.install import install
|
||||
from setuptools.command.install_lib import install_lib
|
||||
from setuptools.command.build_ext import build_ext
|
||||
|
||||
"""
|
||||
This is a hack allowing you installing
|
||||
uWSGI and uwsgidecorators via pip and easy_install
|
||||
"""
|
||||
|
||||
uwsgi_compiled = False
|
||||
|
||||
|
||||
def get_profile():
|
||||
profile = os.environ.get('UWSGI_PROFILE','buildconf/default.ini')
|
||||
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
|
||||
if not profile.endswith('.ini'):
|
||||
profile = "%s.ini" % profile
|
||||
if not '/' in profile:
|
||||
@@ -18,6 +26,7 @@ def get_profile():
|
||||
|
||||
return profile
|
||||
|
||||
|
||||
def patch_bin_path(cmd, conf):
|
||||
|
||||
bin_name = conf.get('bin_name')
|
||||
@@ -27,7 +36,8 @@ def patch_bin_path(cmd, conf):
|
||||
os.makedirs(cmd.install_scripts)
|
||||
if not os.path.isabs(bin_name):
|
||||
print('Patching "bin_name" to properly install_scripts dir')
|
||||
conf.set('bin_name', os.path.join(cmd.install_scripts, conf.get('bin_name')))
|
||||
conf.set('bin_name',
|
||||
os.path.join(cmd.install_scripts, conf.get('bin_name')))
|
||||
except:
|
||||
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
|
||||
|
||||
@@ -35,26 +45,37 @@ def patch_bin_path(cmd, conf):
|
||||
class uWSGIBuilder(build_ext):
|
||||
|
||||
def run(self):
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
global uwsgi_compiled
|
||||
if not uwsgi_compiled:
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi(conf)
|
||||
uwsgi_compiled = True
|
||||
|
||||
|
||||
class uWSGIInstall(install):
|
||||
|
||||
def run(self):
|
||||
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
global uwsgi_compiled
|
||||
if not uwsgi_compiled:
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi(conf)
|
||||
uwsgi_compiled = True
|
||||
install.run(self)
|
||||
|
||||
|
||||
class uWSGIInstallLib(install_lib):
|
||||
|
||||
def run(self):
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi( conf )
|
||||
global uwsgi_compiled
|
||||
if not uwsgi_compiled:
|
||||
conf = uc.uConf(get_profile())
|
||||
patch_bin_path(self, conf)
|
||||
uc.build_uwsgi(conf)
|
||||
uwsgi_compiled = True
|
||||
install_lib.run(self)
|
||||
|
||||
|
||||
class uWSGIDistribution(Distribution):
|
||||
|
||||
@@ -64,6 +85,7 @@ class uWSGIDistribution(Distribution):
|
||||
self.cmdclass['install_lib'] = uWSGIInstallLib
|
||||
self.cmdclass['build_ext'] = uWSGIBuilder
|
||||
|
||||
|
||||
setup(name='uWSGI',
|
||||
version=uc.uwsgi_version,
|
||||
description='The uWSGI server',
|
||||
@@ -71,6 +93,6 @@ setup(name='uWSGI',
|
||||
author_email='info@unbit.it',
|
||||
url='http://projects.unbit.it/uwsgi/',
|
||||
license='GPL2',
|
||||
distclass = uWSGIDistribution,
|
||||
py_modules=['uwsgidecorators'],
|
||||
distclass=uWSGIDistribution,
|
||||
)
|
||||
|
||||
|
||||
@@ -12,6 +12,28 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check for COW
|
||||
if (uwsgi.master_process) {
|
||||
if (use->wid != 0 && use->wid != uwsgi.mywid) {
|
||||
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// in lazy mode (without a master), only the same worker will be able to run handlers
|
||||
else if (uwsgi.lazy) {
|
||||
if (use->wid != uwsgi.mywid) {
|
||||
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// when master is not active, worker1 is the COW-leader
|
||||
if (use->wid != 1 && use->wid != uwsgi.mywid) {
|
||||
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// set harakiri here (if required and if i am a worker)
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
@@ -30,6 +52,13 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
|
||||
|
||||
@@ -39,12 +68,19 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
set_harakiri(0);
|
||||
}
|
||||
}
|
||||
if (uwsgi.muleid > 0) {
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].sig = 0;
|
||||
if(uwsgi.mules[uwsgi.muleid-1].harakiri > 0) {
|
||||
set_mule_harakiri(0);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0 && (getpid() == uwsgi.shared->spooler_pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -67,11 +103,23 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
use = &uwsgi.shared->signal_table[sig];
|
||||
|
||||
if (use->handler) {
|
||||
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
|
||||
uwsgi_unlock(uwsgi.signal_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(use->receiver, receiver);
|
||||
use->handler = handler;
|
||||
use->modifier1 = modifier1;
|
||||
|
||||
uwsgi_log("registered signal %d\n", sig);
|
||||
use->wid = uwsgi.mywid;
|
||||
|
||||
if (use->receiver[0] == 0) {
|
||||
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: default, any worker)\n", sig, uwsgi.mywid, modifier1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.signal_table_lock);
|
||||
|
||||
@@ -109,6 +157,87 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
|
||||
if (!uwsgi_up) {
|
||||
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
uwsgi_up = *up;
|
||||
}
|
||||
else {
|
||||
while(uwsgi_up) {
|
||||
old_up = uwsgi_up;
|
||||
uwsgi_up = uwsgi_up->next;
|
||||
}
|
||||
|
||||
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
|
||||
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
|
||||
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
|
||||
|
||||
uwsgi_lock(uwsgi.probe_table_lock);
|
||||
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while(up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fill the probe table
|
||||
ushared->probes[ushared->probes_cnt].func = up->func;
|
||||
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024-1);
|
||||
ushared->probes[ushared->probes_cnt].registered = 0;
|
||||
ushared->probes[ushared->probes_cnt].sig = sig;
|
||||
ushared->probes[ushared->probes_cnt].fd = -1;
|
||||
ushared->probes[ushared->probes_cnt].state = 0;
|
||||
ushared->probes[ushared->probes_cnt].last_event = 0;
|
||||
ushared->probes[ushared->probes_cnt].data = NULL;
|
||||
ushared->probes[ushared->probes_cnt].cycles = 0;
|
||||
ushared->probes[ushared->probes_cnt].bad = 0;
|
||||
|
||||
if (!timeout) {
|
||||
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].timeout = timeout;
|
||||
if (!freq) {
|
||||
freq = 1;
|
||||
}
|
||||
ushared->probes[ushared->probes_cnt].freq = freq;
|
||||
ushared->probes_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_add_timer(uint8_t sig, int secs) {
|
||||
|
||||
uwsgi_lock(uwsgi.timer_table_lock);
|
||||
@@ -184,24 +313,92 @@ int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
}
|
||||
|
||||
void create_signal_pipe(int *sigpipe) {
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_socket_nb(sigpipe[0]);
|
||||
uwsgi_socket_nb(sigpipe[1]);
|
||||
|
||||
if (uwsgi.signal_bufsize) {
|
||||
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
|
||||
uh.modifier1 = 110;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = sig;
|
||||
|
||||
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0) return -1;
|
||||
|
||||
if (write(fd, (char *) &uh, 4) != 4) {
|
||||
uwsgi_error("uwsgi_remote_signal_send()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL);
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
int so_bufsize = 0;
|
||||
|
||||
if (write(fd, &sig, 1) != 1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("getsockopt()");
|
||||
}
|
||||
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
|
||||
}
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_route_signal(uint8_t sig) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
|
||||
int i;
|
||||
|
||||
// send to first available worker
|
||||
if (use->receiver[0] == 0 || !strcmp(use->receiver, "worker") || !strcmp(use->receiver, "worker0")) {
|
||||
if (write(ushared->worker_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->worker_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to workers pool\n", sig);
|
||||
}
|
||||
}
|
||||
// send to all workers
|
||||
else if (!strcmp(use->receiver, "workers")) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
@@ -212,8 +409,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
if (i > uwsgi.numproc) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
if (write(uwsgi.workers[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
@@ -221,18 +417,18 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
else if (!strcmp(use->receiver, "subscribed")) {
|
||||
}
|
||||
// route to spooler
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (!strcmp(use->receiver, "spooler")) {
|
||||
if (ushared->worker_signal_pipe[0] != -1) {
|
||||
if (write(ushared->spooler_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(use->receiver, "mules")) {
|
||||
for(i=0;i<uwsgi.mules_cnt;i++) {
|
||||
if (write(uwsgi.mules[i].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
|
||||
}
|
||||
}
|
||||
@@ -243,20 +439,90 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else if (i == 0) {
|
||||
if (write(ushared->mule_signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to a mule\n", sig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (write(uwsgi.mules[i-1].signal_pipe[0], &sig, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
if (uwsgi_signal_send(uwsgi.mules[i-1].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp(use->receiver, "farm_", 5)) {
|
||||
char *name = use->receiver+5;
|
||||
struct uwsgi_farm *uf = get_farm_by_name(name);
|
||||
if (!uf) {
|
||||
uwsgi_log("unknown farm: %s\n", name);
|
||||
return;
|
||||
}
|
||||
if (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(use->receiver, "farm", 4)) {
|
||||
i = atoi(use->receiver+4);
|
||||
if (i > uwsgi.farms_cnt || i <= 0) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else {
|
||||
if (uwsgi_signal_send(uwsgi.farms[i-1].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// unregistered signal, sending it to all the workers
|
||||
uwsgi_log("^^^ UNSUPPORTED SIGNAL TARGET: %s ^^^\n", use->receiver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t uwsgi_signal_wait(int signum) {
|
||||
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
int ret;
|
||||
struct pollfd pfd[2];
|
||||
|
||||
if (signum > -1) {
|
||||
wait_for_specific_signal = 1;
|
||||
}
|
||||
|
||||
pfd[0].fd = uwsgi.signal_socket;
|
||||
pfd[0].events = POLLIN;
|
||||
pfd[1].fd = uwsgi.my_signal_socket;
|
||||
pfd[1].events = POLLIN;
|
||||
cycle:
|
||||
ret = poll(pfd, 2, -1);
|
||||
if (ret > 0) {
|
||||
if (pfd[0].revents == POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void)uwsgi_signal_handler(received_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents == POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void)uwsgi_signal_handler(received_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (received_signal != uwsgi_signal) goto cycle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return received_signal;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,43 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
char *uwsgi_getsockname(int fd) {
|
||||
|
||||
socklen_t socket_type_len = sizeof(struct sockaddr_un);
|
||||
union uwsgi_sockaddr usa;
|
||||
union uwsgi_sockaddr_ptr gsa;
|
||||
char computed_port[6];
|
||||
char ipv4a[INET_ADDRSTRLEN + 1];
|
||||
|
||||
gsa.sa = (struct sockaddr *) &usa;
|
||||
|
||||
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
|
||||
if (gsa.sa->sa_family == AF_UNIX) {
|
||||
if (usa.sa_un.sun_path[0] == 0) {
|
||||
return uwsgi_concat2("@", usa.sa_un.sun_path+1);
|
||||
}
|
||||
else {
|
||||
return uwsgi_str(usa.sa_un.sun_path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
memset(ipv4a, 0, INET_ADDRSTRLEN + 1);
|
||||
memset(computed_port, 0, 6);
|
||||
if (snprintf(computed_port, 6, "%d", ntohs(gsa.sa_in->sin_port)) > 0) {
|
||||
if (inet_ntop(AF_INET, (const void *) &gsa.sa_in->sin_addr.s_addr, ipv4a, INET_ADDRSTRLEN)) {
|
||||
if (!strcmp("0.0.0.0", ipv4a)) {
|
||||
return uwsgi_concat2(":", computed_port);
|
||||
}
|
||||
else {
|
||||
return uwsgi_concat3(ipv4a, ":", computed_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abstract_socket) {
|
||||
|
||||
int serverfd;
|
||||
@@ -412,7 +449,7 @@ char *generate_socket_name(char *socket_name) {
|
||||
if (!strncmp(socket_name, new_addr, strlen(socket_name))) {
|
||||
asterisk[0] = '*';
|
||||
new_socket = uwsgi_concat3(new_addr, ":", tcp_port + 1);
|
||||
uwsgi_log("found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
|
||||
uwsgi_log("[uwsgi-autoip] found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name);
|
||||
freeifaddrs(ifap);
|
||||
return new_socket;
|
||||
}
|
||||
@@ -460,15 +497,18 @@ socklen_t socket_to_un_addr(char *socket_name, struct sockaddr_un *sun_addr) {
|
||||
return sizeof(sun_addr->sun_family)+len;
|
||||
}
|
||||
|
||||
socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *sin_addr) {
|
||||
socklen_t socket_to_in_addr(char *socket_name, char *port, int portn, struct sockaddr_in *sin_addr) {
|
||||
|
||||
memset(sin_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sin_addr->sin_family = AF_INET;
|
||||
if (port) {
|
||||
port[0] = 0;
|
||||
*port = 0;
|
||||
sin_addr->sin_port = htons(atoi(port + 1));
|
||||
}
|
||||
else {
|
||||
sin_addr->sin_port = htons(portn);
|
||||
}
|
||||
|
||||
if (socket_name[0] == 0) {
|
||||
sin_addr->sin_addr.s_addr = INADDR_ANY;
|
||||
@@ -483,6 +523,10 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *s
|
||||
}
|
||||
}
|
||||
|
||||
if (port) {
|
||||
*port = ':';
|
||||
}
|
||||
|
||||
return sizeof(struct sockaddr_in);
|
||||
|
||||
}
|
||||
@@ -493,7 +537,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
struct sockaddr_in uws_addr;
|
||||
int reuse = 1;
|
||||
|
||||
socket_to_in_addr(socket_name, tcp_port, &uws_addr);
|
||||
socket_to_in_addr(socket_name, tcp_port, 0, &uws_addr);
|
||||
|
||||
serverfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverfd < 0) {
|
||||
@@ -1014,3 +1058,16 @@ void uwsgi_del_sockets_from_queue(int queue) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_is_bad_connection(int fd) {
|
||||
|
||||
int soopt = 0;
|
||||
socklen_t solen = sizeof(int) ;
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// will be 0 if all ok
|
||||
return soopt;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ pid_t spooler_start() {
|
||||
|
||||
int i;
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t pid = uwsgi_fork("uWSGI spooler");
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
@@ -65,13 +65,13 @@ void destroy_spool(char *dir, char *file) {
|
||||
|
||||
if (chdir(dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
uwsgi_log("something horrible happened to the spooler. Better to kill it.\n");
|
||||
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (unlink(file)) {
|
||||
uwsgi_error("unlink()");
|
||||
uwsgi_log("something horrible happened to the spooler. Better to kill it.\n");
|
||||
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size, c
|
||||
|
||||
close(fd);
|
||||
|
||||
uwsgi_log("written %d bytes to spool file %s\n", size + body_len + 4, filename);
|
||||
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
|
||||
|
||||
uwsgi_unlock(uwsgi.spooler_lock);
|
||||
|
||||
@@ -347,7 +347,7 @@ void spooler_manage_task(char *dir, char *task) {
|
||||
return;
|
||||
}
|
||||
if (!access(task, R_OK | W_OK)) {
|
||||
uwsgi_log("managing spool request %s ...\n", task);
|
||||
uwsgi_log("[spooler] managing request %s ...\n", task);
|
||||
|
||||
#ifdef __sun__
|
||||
// lockf needs write permission
|
||||
@@ -413,14 +413,20 @@ void spooler_manage_task(char *dir, char *task) {
|
||||
for(i=0;i<0xff;i++) {
|
||||
if (uwsgi.p[i]->spooler) {
|
||||
time_t now = time(NULL);
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
if (body) {
|
||||
free(body);
|
||||
}
|
||||
if (ret == 0) continue;
|
||||
callable_found = 1;
|
||||
if (ret == -2) {
|
||||
uwsgi_log("done with task/spool %s after %d seconds\n", task, time(NULL)-now);
|
||||
uwsgi_log("[spooler] done with task %s after %d seconds\n", task, time(NULL)-now);
|
||||
destroy_spool(dir, task);
|
||||
}
|
||||
// re-spool it
|
||||
|
||||
+464
@@ -0,0 +1,464 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
subscription subsystem
|
||||
|
||||
each subscription slot is as an auto-optmizing linked list. Originally it was a uwsgi_dict (now removed from uWSGI) but this
|
||||
would have not be able to support regexp as keys.
|
||||
|
||||
each slot has another circular linked list containing the nodes names
|
||||
|
||||
the structure and system is very similar to uwsgi_dyn_dict already used by the mime type parser
|
||||
|
||||
This system is not mean to run on shared memory. If you have multiple processes for the same app, you have to create
|
||||
a new subscriptions slot list.
|
||||
|
||||
To avoid removal of already using nodes, a reference count system has been implemented
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = *slot;
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
|
||||
while(current_slot) {
|
||||
#ifdef UWSGI_PCRE
|
||||
if (regexp) {
|
||||
if (uwsgi_regexp_match(current_slot->pattern, current_slot->pattern_extra, key, keylen) >= 0) {
|
||||
return current_slot;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
if (!uwsgi_strncmp(key, keylen, current_slot->key, current_slot->keylen)) {
|
||||
// auto optimization
|
||||
if (current_slot->prev) {
|
||||
if (current_slot->hits > current_slot->prev->hits) {
|
||||
struct uwsgi_subscribe_slot *slot_parent = current_slot->prev->prev, *slot_prev = current_slot->prev;
|
||||
if (slot_parent) {
|
||||
slot_parent->next = current_slot;
|
||||
}
|
||||
else {
|
||||
*slot = current_slot;
|
||||
}
|
||||
|
||||
slot_prev->prev = current_slot;
|
||||
slot_prev->next = current_slot->next;
|
||||
|
||||
current_slot->next = slot_prev;
|
||||
current_slot->prev = slot_parent;
|
||||
|
||||
}
|
||||
}
|
||||
return current_slot;
|
||||
}
|
||||
#ifdef UWSGI_PCRE
|
||||
}
|
||||
#endif
|
||||
current_slot = current_slot->next;
|
||||
// check for loopy optimization
|
||||
if (current_slot == *slot) break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
|
||||
uint64_t rr_pos = 0;
|
||||
|
||||
if (current_slot) {
|
||||
// node found, move up in the list increasing hits
|
||||
current_slot->hits++;
|
||||
time_t current = time(NULL);
|
||||
struct uwsgi_subscribe_node *node = current_slot->nodes;
|
||||
while(node) {
|
||||
// is the node alive ?
|
||||
if (current - node->last_check > uwsgi.subscription_tolerance) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
}
|
||||
if (node->death_mark && node->reference == 0) {
|
||||
// remove the node and move to next
|
||||
struct uwsgi_subscribe_node *dead_node = node;
|
||||
node = node->next;
|
||||
// if the slot has been removed, return NULL;
|
||||
if (uwsgi_remove_subscribe_node(slot, dead_node) == 1) {
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// only unmarked nodes can respond
|
||||
if (node->death_mark == 0 && rr_pos == current_slot->rr) {
|
||||
current_slot->rr++;
|
||||
node->reference++;
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
rr_pos++;
|
||||
}
|
||||
current_slot->rr = 1;
|
||||
if (current_slot->nodes) {
|
||||
if (current_slot->nodes->death_mark)
|
||||
return NULL;
|
||||
current_slot->nodes->reference++;
|
||||
}
|
||||
return current_slot->nodes;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen, int regexp) {
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
|
||||
if (current_slot) {
|
||||
struct uwsgi_subscribe_node *node = current_slot->nodes;
|
||||
while(node) {
|
||||
if (!uwsgi_strncmp(val, vallen, node->name, node->len)) {
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_node *node) {
|
||||
|
||||
int ret = 0;
|
||||
|
||||
struct uwsgi_subscribe_node *a_node;
|
||||
struct uwsgi_subscribe_slot *node_slot = node->slot;
|
||||
struct uwsgi_subscribe_slot *prev_slot = node_slot->prev;
|
||||
struct uwsgi_subscribe_slot *next_slot = node_slot->next;
|
||||
|
||||
// over-engineering to avoid race conditions
|
||||
node->len = 0;
|
||||
|
||||
if (node == node_slot->nodes) {
|
||||
node_slot->nodes = node->next;
|
||||
}
|
||||
else {
|
||||
a_node = node_slot->nodes;
|
||||
while(a_node) {
|
||||
if (a_node->next == node) {
|
||||
a_node->next = node->next;
|
||||
break;
|
||||
}
|
||||
a_node = a_node->next;
|
||||
}
|
||||
}
|
||||
|
||||
free(node);
|
||||
// no more nodes, remove the slot too
|
||||
if (node_slot->nodes == NULL) {
|
||||
|
||||
ret = 1;
|
||||
|
||||
// first check if i am the only node
|
||||
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
|
||||
free(node_slot);
|
||||
*slot = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// if i am the main entry point, set the next value
|
||||
if (node_slot == *slot) {
|
||||
*slot = next_slot;
|
||||
}
|
||||
|
||||
if (prev_slot) {
|
||||
prev_slot->next = next_slot;
|
||||
}
|
||||
if (next_slot) {
|
||||
next_slot->prev = prev_slot;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
if (node_slot->pattern) {
|
||||
pcre_free(node_slot->pattern);
|
||||
}
|
||||
if (node_slot->pattern_extra) {
|
||||
pcre_free(node_slot->pattern_extra);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(node_slot);
|
||||
struct uwsgi_subscribe_slot *x_slot = *slot;
|
||||
while(x_slot) {
|
||||
x_slot = x_slot->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr, int regexp) {
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen, 0), *old_slot = NULL, *a_slot;
|
||||
struct uwsgi_subscribe_node *node, *old_node = NULL;
|
||||
|
||||
if (usr->address_len > 0xff) return NULL;
|
||||
|
||||
if (current_slot) {
|
||||
node = current_slot->nodes;
|
||||
while(node) {
|
||||
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
|
||||
// remove death mark and update cores and load
|
||||
node->death_mark = 0;
|
||||
node->last_check = time(NULL);
|
||||
node->cores = usr->cores;
|
||||
node->load = usr->load;
|
||||
return node;
|
||||
}
|
||||
old_node = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
node->len = usr->address_len;
|
||||
node->modifier1 = usr->modifier1;
|
||||
node->modifier2 = usr->modifier2;
|
||||
node->requests = 0;
|
||||
node->transferred = 0;
|
||||
node->reference = 0;
|
||||
node->death_mark = 0;
|
||||
node->failcnt = 0;
|
||||
node->cores = usr->cores;
|
||||
node->load = usr->load;
|
||||
node->last_check = time(NULL);
|
||||
node->slot = current_slot;
|
||||
memcpy(node->name, usr->address, usr->address_len);
|
||||
if (old_node) {
|
||||
old_node->next = node;
|
||||
}
|
||||
node->next = NULL;
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
return node;
|
||||
}
|
||||
else {
|
||||
|
||||
current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
|
||||
current_slot->keylen = usr->keylen;
|
||||
memcpy(current_slot->key, usr->key, usr->keylen);
|
||||
current_slot->key[usr->keylen] = 0;
|
||||
current_slot->hits = 0;
|
||||
current_slot->rr = 0;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
current_slot->pattern = NULL;
|
||||
current_slot->pattern_extra = NULL;
|
||||
if (regexp) {
|
||||
if (uwsgi_regexp_build(current_slot->key, ¤t_slot->pattern, ¤t_slot->pattern_extra)) {
|
||||
free(current_slot);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
|
||||
current_slot->nodes->slot = current_slot;
|
||||
current_slot->nodes->len = usr->address_len;
|
||||
current_slot->nodes->reference = 0;
|
||||
current_slot->nodes->requests = 0;
|
||||
current_slot->nodes->transferred = 0;
|
||||
current_slot->nodes->death_mark = 0;
|
||||
current_slot->nodes->failcnt = 0;
|
||||
current_slot->nodes->modifier1 = usr->modifier1;
|
||||
current_slot->nodes->modifier2 = usr->modifier2;
|
||||
current_slot->nodes->cores = usr->cores;
|
||||
current_slot->nodes->load = usr->load;
|
||||
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
|
||||
current_slot->nodes->last_check = time(NULL);
|
||||
|
||||
current_slot->nodes->next = NULL;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// if key is a regexp, order it by keylen
|
||||
if (regexp) {
|
||||
old_slot = NULL;
|
||||
a_slot = *slot;
|
||||
while(a_slot) {
|
||||
if (a_slot->keylen > current_slot->keylen) {
|
||||
old_slot = a_slot;
|
||||
break;
|
||||
}
|
||||
a_slot = a_slot->next;
|
||||
}
|
||||
|
||||
if (old_slot) {
|
||||
current_slot->prev = old_slot->prev;
|
||||
old_slot->prev = current_slot;
|
||||
if (current_slot->prev) {
|
||||
old_slot->prev->next = current_slot;
|
||||
}
|
||||
|
||||
current_slot->next = old_slot;
|
||||
}
|
||||
else {
|
||||
a_slot = *slot;
|
||||
while(a_slot) {
|
||||
old_slot = a_slot;
|
||||
a_slot = a_slot->next;
|
||||
}
|
||||
|
||||
|
||||
if (old_slot) {
|
||||
old_slot->next = current_slot;
|
||||
}
|
||||
|
||||
current_slot->prev = old_slot;
|
||||
current_slot->next = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
a_slot = *slot;
|
||||
while(a_slot) {
|
||||
old_slot = a_slot;
|
||||
a_slot = a_slot->next;
|
||||
}
|
||||
|
||||
|
||||
if (old_slot) {
|
||||
old_slot->next = current_slot;
|
||||
}
|
||||
|
||||
current_slot->prev = old_slot;
|
||||
current_slot->next = NULL;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!*slot || current_slot->prev == NULL) {
|
||||
*slot = current_slot;
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-subscription] new pool: %.*s\n", usr->keylen, usr->key);
|
||||
uwsgi_log("[uwsgi-subscription] %.*s => new node: %.*s\n", usr->keylen, usr->key, usr->address_len, usr->address);
|
||||
return current_slot->nodes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd) {
|
||||
|
||||
char value_cores[sizeof(UMAX64_STR)+1];
|
||||
char value_load[sizeof(UMAX64_STR)+1];
|
||||
char value_modifier1[4];
|
||||
char value_modifier2[4];
|
||||
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc*uwsgi.cores, value_cores, sizeof(UMAX64_STR));
|
||||
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
|
||||
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
|
||||
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
|
||||
|
||||
if (!uwsgi.sockets) return;
|
||||
|
||||
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name)) + (2+9 + 2+value_modifier1_size) +
|
||||
(2+9 + 2+value_modifier2_size) + (2+5 + 2+value_cores_size) + (2+4 + 2+value_load_size);
|
||||
|
||||
char *subscrbuf = uwsgi_malloc(ssb_size);
|
||||
// leave space for uwsgi header
|
||||
char *ssb = subscrbuf+4;
|
||||
|
||||
// key = "domain"
|
||||
uint16_t ustrlen = 3;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "key", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = keysize;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, key, ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
// address = "first uwsgi socket"
|
||||
ustrlen = 7;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "address", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = strlen(uwsgi.sockets->name);
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, uwsgi.sockets->name, ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
// modifier1 = "modifier1"
|
||||
ustrlen = 9;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "modifier1", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = value_modifier1_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, value_modifier1, value_modifier1_size);
|
||||
ssb+=ustrlen;
|
||||
|
||||
// modifier2 = "modifier2"
|
||||
ustrlen = 9;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "modifier2", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = value_modifier2_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, value_modifier2, value_modifier2_size);
|
||||
ssb+=ustrlen;
|
||||
|
||||
// cores = uwsgi.numproc * uwsgi.cores
|
||||
ustrlen = 5;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "cores", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = value_cores_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, value_cores, value_cores_size);
|
||||
ssb+=ustrlen;
|
||||
|
||||
// load
|
||||
ustrlen = 4;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, "load", ustrlen);
|
||||
ssb+=ustrlen;
|
||||
|
||||
ustrlen = value_load_size;
|
||||
*ssb++ = (uint8_t) (ustrlen & 0xff);
|
||||
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
|
||||
memcpy(ssb, value_load, value_load_size);
|
||||
ssb+=ustrlen;
|
||||
|
||||
|
||||
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size-4);
|
||||
free(subscrbuf);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,12 @@ extern "C" {
|
||||
|
||||
#define UMAX16 65536
|
||||
|
||||
#define UMAX64_STR "18446744073709551616"
|
||||
|
||||
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_log_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log(x);
|
||||
#define uwsgi_error_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
|
||||
#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1);
|
||||
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_req_error(x) if (wsgi_req->uri_len > 0 && wsgi_req->method_len > 0 && wsgi_req->remote_addr_len > 0) uwsgi_log_verbose("%s: %s [%s line %d] during %.*s %.*s (%.*s)\n", x, strerror(errno), __FILE__, __LINE__,\
|
||||
@@ -36,8 +41,8 @@ extern "C" {
|
||||
#define MAX_GENERIC_PLUGINS 64
|
||||
#define MAX_RPC 64
|
||||
#define MAX_GATEWAYS 64
|
||||
#define MAX_DAEMONS 8
|
||||
#define MAX_SUBSCRIPTIONS 8
|
||||
#define MAX_TIMERS 64
|
||||
#define MAX_PROBES 64
|
||||
#define MAX_CRONS 64
|
||||
|
||||
#ifndef UWSGI_LOAD_EMBEDDED_PLUGINS
|
||||
@@ -62,6 +67,8 @@ extern char UWSGI_EMBED_CONFIG_END;
|
||||
#define ULEP(pname)\
|
||||
if (pname##_plugin.request) {\
|
||||
uwsgi.p[pname##_plugin.modifier1] = &pname##_plugin;\
|
||||
if (uwsgi.p[pname##_plugin.modifier1]->on_load)\
|
||||
uwsgi.p[pname##_plugin.modifier1]->on_load();\
|
||||
}\
|
||||
else {\
|
||||
if (uwsgi.gp_cnt >= MAX_GENERIC_PLUGINS) {\
|
||||
@@ -69,6 +76,8 @@ extern char UWSGI_EMBED_CONFIG_END;
|
||||
exit(1);\
|
||||
}\
|
||||
uwsgi.gp[uwsgi.gp_cnt] = &pname##_plugin;\
|
||||
if (uwsgi.gp[uwsgi.gp_cnt]->on_load)\
|
||||
uwsgi.gp[uwsgi.gp_cnt]->on_load();\
|
||||
uwsgi.gp_cnt++;\
|
||||
}\
|
||||
|
||||
@@ -123,8 +132,6 @@ extern char UWSGI_EMBED_CONFIG_END;
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef UWSGI_HAS_IFADDRS
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
@@ -268,23 +275,10 @@ struct uwsgi_help_item {
|
||||
|
||||
struct uwsgi_config_template {
|
||||
char *filename;
|
||||
int applied;
|
||||
struct uwsgi_config_template *next;
|
||||
};
|
||||
|
||||
struct uwsgi_static_map {
|
||||
|
||||
char *mountpoint;
|
||||
int mountpoint_len;
|
||||
|
||||
char *document_root;
|
||||
int document_root_len;
|
||||
|
||||
char *orig_document_root;
|
||||
int orig_document_root_len;
|
||||
|
||||
struct uwsgi_static_map *next;
|
||||
};
|
||||
|
||||
struct uwsgi_string_list {
|
||||
|
||||
char *value;
|
||||
@@ -301,6 +295,7 @@ struct uwsgi_dyn_dict {
|
||||
int vallen;
|
||||
|
||||
uint64_t hits;
|
||||
int status;
|
||||
|
||||
struct uwsgi_dyn_dict *prev;
|
||||
struct uwsgi_dyn_dict *next;
|
||||
@@ -337,8 +332,8 @@ struct uwsgi_gateway {
|
||||
// Daemons are external processes maintained by the master
|
||||
|
||||
struct uwsgi_daemon {
|
||||
char command[0xff];
|
||||
char tmp_command[0xff];
|
||||
char *command;
|
||||
char *tmp_command;
|
||||
pid_t pid;
|
||||
uint64_t respawns;
|
||||
time_t born;
|
||||
@@ -346,6 +341,21 @@ struct uwsgi_daemon {
|
||||
int status;
|
||||
int registered;
|
||||
//int pipe[2];
|
||||
|
||||
struct uwsgi_daemon *next;
|
||||
};
|
||||
|
||||
struct uwsgi_logger {
|
||||
char *name;
|
||||
ssize_t (*func)(struct uwsgi_logger *, char *, size_t);
|
||||
int configured;
|
||||
int fd;
|
||||
void *data;
|
||||
union uwsgi_sockaddr addr;
|
||||
socklen_t addr_len;
|
||||
int count;
|
||||
struct msghdr msg;
|
||||
struct uwsgi_logger *next;
|
||||
};
|
||||
|
||||
struct uwsgi_queue_header {
|
||||
@@ -528,6 +538,28 @@ struct uwsgi_opt {
|
||||
#define LONG_ARGS_EMPEROR_STATS 17150
|
||||
#define LONG_ARGS_SPOOLER_CHDIR 17151
|
||||
#define LONG_ARGS_LOCKS 17152
|
||||
#define LONG_ARGS_PROCNAME_PREFIX 17153
|
||||
#define LONG_ARGS_PROCNAME_APPEND 17154
|
||||
#define LONG_ARGS_PROCNAME 17155
|
||||
#define LONG_ARGS_PROCNAME_MASTER 17156
|
||||
#define LONG_ARGS_FARM 17157
|
||||
#define LONG_ARGS_MULES 17158
|
||||
#define LONG_ARGS_PROCNAME_PREFIX_SP 17159
|
||||
#define LONG_ARGS_UMASK 17160
|
||||
#define LONG_ARGS_PAUSE 17161
|
||||
#define LONG_ARGS_SIGNAL_BUFSIZE 17162
|
||||
#define LONG_ARGS_SIGNAL 17163
|
||||
#define LONG_ARGS_KSM 17164
|
||||
#define LONG_ARGS_LOGFILE_CHMOD 17165
|
||||
#define LONG_ARGS_SUBSCRIBE_FREQ 17166
|
||||
#define LONG_ARGS_SUBSCR_TOLERANCE 17167
|
||||
#define LONG_ARGS_UNSHARE 17168
|
||||
#define LONG_ARGS_EXEC_AS_ROOT 17169
|
||||
#define LONG_ARGS_EXEC_AS_USER 17170
|
||||
#define LONG_ARGS_STATIC_SKIP_EXT 17171
|
||||
#define LONG_ARGS_LOGGER 17172
|
||||
#define LONG_ARGS_STATIC_INDEX 17173
|
||||
#define LONG_ARGS_CHEAPER_STEP 17174
|
||||
|
||||
|
||||
#define UWSGI_OK 0
|
||||
@@ -638,6 +670,7 @@ struct uwsgi_plugin {
|
||||
const char *alias;
|
||||
uint8_t modifier1;
|
||||
void *data;
|
||||
void (*on_load) (void);
|
||||
int (*init) (void);
|
||||
void (*post_init) (void);
|
||||
void (*post_fork) (void);
|
||||
@@ -649,8 +682,10 @@ struct uwsgi_plugin {
|
||||
int (*request) (struct wsgi_request *);
|
||||
void (*after_request) (struct wsgi_request *);
|
||||
void (*init_apps) (void);
|
||||
void (*preinit_apps) (void);
|
||||
void (*fixup) (void);
|
||||
void (*master_fixup) (int);
|
||||
void (*master_cycle) (void);
|
||||
int (*mount_app) (char *, char *, int);
|
||||
int (*manage_udp) (char *, int, char *, int);
|
||||
int (*manage_xml) (char *, char *);
|
||||
@@ -669,18 +704,19 @@ struct uwsgi_plugin {
|
||||
|
||||
int (*spooler) (char *, char *, uint16_t, char *, size_t);
|
||||
|
||||
uint16_t(*rpc) (void *, uint8_t, char **, char *);
|
||||
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
|
||||
|
||||
void (*jail) (int (*)(void *), char **);
|
||||
|
||||
int (*mule)(char *);
|
||||
int (*mule_msg)(char *, size_t);
|
||||
struct uwsgi_help_item *help;
|
||||
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
#include <pcre.h>
|
||||
void uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra);
|
||||
int uwsgi_regexp_build(char *re, pcre **pattern, pcre_extra **pattern_extra);
|
||||
int uwsgi_regexp_match(pcre *pattern, pcre_extra *pattern_extra, char *subject, int length);
|
||||
#endif
|
||||
|
||||
@@ -959,6 +995,34 @@ struct uwsgi_signal_rb_timer {
|
||||
struct uwsgi_rb_timer *uwsgi_rb_timer;
|
||||
};
|
||||
|
||||
struct uwsgi_signal_probe {
|
||||
|
||||
int (*func)(int, struct uwsgi_signal_probe *);
|
||||
char args[1024];
|
||||
|
||||
int fd;
|
||||
int state;
|
||||
int bad;
|
||||
int last_event;
|
||||
void *data;
|
||||
uint64_t cycles;
|
||||
|
||||
int timeout;
|
||||
int freq;
|
||||
|
||||
int registered;
|
||||
uint8_t sig;
|
||||
};
|
||||
|
||||
struct uwsgi_probe {
|
||||
|
||||
char *name;
|
||||
int (*func)(int, struct uwsgi_signal_probe *);
|
||||
|
||||
struct uwsgi_probe *next;
|
||||
};
|
||||
|
||||
|
||||
struct uwsgi_server {
|
||||
|
||||
|
||||
@@ -966,6 +1030,17 @@ struct uwsgi_server {
|
||||
char hostname[256];
|
||||
int hostname_len;
|
||||
|
||||
char **orig_argv;
|
||||
char **argv;
|
||||
int argc;
|
||||
int max_procname;
|
||||
int auto_procname;
|
||||
char **environ;
|
||||
char *procname_prefix;
|
||||
char *procname_append;
|
||||
char *procname_master;
|
||||
char *procname;
|
||||
|
||||
// quiet startup
|
||||
int no_initial_output;
|
||||
|
||||
@@ -1011,6 +1086,7 @@ struct uwsgi_server {
|
||||
int cheap;
|
||||
// enable cheaper mode
|
||||
int cheaper;
|
||||
int cheaper_step;
|
||||
// minimal number of running workers in cheaper mode
|
||||
int cheaper_count;
|
||||
// enable idle mode
|
||||
@@ -1094,6 +1170,10 @@ struct uwsgi_server {
|
||||
int cap_count;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int unshare;
|
||||
#endif
|
||||
|
||||
// still working on it
|
||||
char *profiler;
|
||||
|
||||
@@ -1127,24 +1207,32 @@ struct uwsgi_server {
|
||||
off_t log_maxsize;
|
||||
char *log_backupname;
|
||||
|
||||
int log_syslog;
|
||||
int original_log_fd;
|
||||
|
||||
int log_socket;
|
||||
int log_socket_fd;
|
||||
union uwsgi_sockaddr *log_socket_addr;
|
||||
socklen_t log_socket_size;
|
||||
|
||||
|
||||
// static file serving
|
||||
char *check_static;
|
||||
size_t check_static_len;
|
||||
int file_serve_mode;
|
||||
|
||||
int build_mime_dict;
|
||||
char *mime_file;
|
||||
struct uwsgi_static_map *static_maps;
|
||||
|
||||
struct uwsgi_probe *probes;
|
||||
|
||||
struct uwsgi_string_list *exec_as_root;
|
||||
struct uwsgi_string_list *exec_as_user;
|
||||
|
||||
struct uwsgi_logger *loggers;
|
||||
struct uwsgi_logger *choosen_logger;
|
||||
char *requested_logger;
|
||||
char *choosen_logger_arg;
|
||||
int threaded_logger;
|
||||
|
||||
struct uwsgi_daemon *daemons;
|
||||
int daemons_cnt;
|
||||
|
||||
struct uwsgi_dyn_dict *static_maps;
|
||||
struct uwsgi_dyn_dict *check_static;
|
||||
struct uwsgi_dyn_dict *mimetypes;
|
||||
struct uwsgi_string_list *static_skip_ext;
|
||||
struct uwsgi_string_list *static_index;
|
||||
|
||||
char *logfile;
|
||||
int logfile_chown;
|
||||
@@ -1229,6 +1317,7 @@ struct uwsgi_server {
|
||||
int lazy_respawned;
|
||||
|
||||
int buffer_size;
|
||||
int signal_bufsize;
|
||||
|
||||
// post buffering
|
||||
int post_buffering;
|
||||
@@ -1270,6 +1359,7 @@ struct uwsgi_server {
|
||||
#ifdef UWSGI_THREADING
|
||||
// avoid thundering herd in threaded modes
|
||||
pthread_mutex_t six_feet_under_lock;
|
||||
pthread_mutex_t lock_static;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1279,12 +1369,15 @@ struct uwsgi_server {
|
||||
/* the list of mules */
|
||||
struct uwsgi_string_list *mules_patches;
|
||||
struct uwsgi_mule *mules;
|
||||
struct uwsgi_string_list *farms_list;
|
||||
struct uwsgi_farm *farms;
|
||||
|
||||
pid_t mypid;
|
||||
int mywid;
|
||||
|
||||
int muleid;
|
||||
int mules_cnt;
|
||||
int farms_cnt;
|
||||
|
||||
rlim_t max_fd;
|
||||
|
||||
@@ -1298,6 +1391,7 @@ struct uwsgi_server {
|
||||
int chmod_socket;
|
||||
char *chown_socket;
|
||||
mode_t chmod_socket_value;
|
||||
mode_t chmod_logfile_value;
|
||||
int listen_queue;
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
@@ -1385,7 +1479,6 @@ struct uwsgi_server {
|
||||
int zeromq_recv_flag;
|
||||
pthread_mutex_t zmq_lock;
|
||||
pthread_key_t zmq_pull;
|
||||
void *zmq_log_socket;
|
||||
#endif
|
||||
struct uwsgi_socket *sockets;
|
||||
struct uwsgi_socket *shared_sockets;
|
||||
@@ -1480,6 +1573,7 @@ struct uwsgi_server {
|
||||
void *signal_table_lock;
|
||||
void *fmon_table_lock;
|
||||
void *timer_table_lock;
|
||||
void *probe_table_lock;
|
||||
void *rb_timer_table_lock;
|
||||
void *cron_table_lock;
|
||||
void *rpc_table_lock;
|
||||
@@ -1488,14 +1582,21 @@ struct uwsgi_server {
|
||||
void *spooler_lock;
|
||||
#endif
|
||||
|
||||
void *daemon_table_lock;
|
||||
|
||||
char *startup_daemons[MAX_DAEMONS];
|
||||
int startup_daemons_cnt;
|
||||
|
||||
// subscription client
|
||||
char *subscriptions[MAX_SUBSCRIPTIONS];
|
||||
int subscriptions_cnt;
|
||||
int subscribe_freq;
|
||||
int subscription_tolerance;
|
||||
struct uwsgi_string_list *subscriptions;
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
int linux_ksm;
|
||||
int ksm_buffer_size;
|
||||
char *ksm_mappings_last;
|
||||
char *ksm_mappings_current;
|
||||
size_t ksm_mappings_last_size;
|
||||
size_t ksm_mappings_current_size;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1513,6 +1614,7 @@ struct uwsgi_lb_group {
|
||||
|
||||
|
||||
struct uwsgi_signal_entry {
|
||||
int wid;
|
||||
uint8_t modifier1;
|
||||
char receiver[64];
|
||||
void *handler;
|
||||
@@ -1594,6 +1696,7 @@ struct uwsgi_shared {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
pid_t spooler_pid;
|
||||
int spooler_frequency;
|
||||
time_t spooler_harakiri;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
@@ -1616,16 +1719,20 @@ struct uwsgi_shared {
|
||||
int spooler_signal_pipe[2];
|
||||
#endif
|
||||
int mule_signal_pipe[2];
|
||||
int mule_queue_pipe[2];
|
||||
|
||||
struct uwsgi_signal_entry signal_table[256];
|
||||
|
||||
struct uwsgi_fmon files_monitored[64];
|
||||
int files_monitored_cnt;
|
||||
|
||||
struct uwsgi_timer timers[64];
|
||||
struct uwsgi_signal_probe probes[MAX_PROBES];
|
||||
int probes_cnt;
|
||||
|
||||
struct uwsgi_timer timers[MAX_TIMERS];
|
||||
int timers_cnt;
|
||||
|
||||
struct uwsgi_signal_rb_timer rb_timers[64];
|
||||
struct uwsgi_signal_rb_timer rb_timers[MAX_TIMERS];
|
||||
int rb_timers_cnt;
|
||||
|
||||
struct uwsgi_rpc rpc_table[MAX_RPC];
|
||||
@@ -1633,12 +1740,10 @@ struct uwsgi_shared {
|
||||
|
||||
int worker_log_pipe[2];
|
||||
|
||||
struct uwsgi_daemon daemons[MAX_DAEMONS];
|
||||
int daemons_cnt;
|
||||
#ifdef __linux__
|
||||
struct tcp_info ti;
|
||||
#endif
|
||||
|
||||
uint64_t load;
|
||||
struct uwsgi_cron cron[MAX_CRONS];
|
||||
int cron_cnt;
|
||||
};
|
||||
@@ -1680,6 +1785,7 @@ struct uwsgi_worker {
|
||||
uint64_t respawn_count;
|
||||
|
||||
uint64_t requests;
|
||||
uint64_t delta_requests;
|
||||
uint64_t failed_requests;
|
||||
|
||||
time_t harakiri;
|
||||
@@ -1702,6 +1808,7 @@ struct uwsgi_worker {
|
||||
|
||||
int busy;
|
||||
int cheaped;
|
||||
int suspended;
|
||||
int sig;
|
||||
uint8_t signum;
|
||||
|
||||
@@ -1712,8 +1819,10 @@ struct uwsgi_worker {
|
||||
|
||||
uint64_t avg_response_time;
|
||||
|
||||
char name[0xff];
|
||||
};
|
||||
|
||||
|
||||
struct uwsgi_mule {
|
||||
int id;
|
||||
pid_t pid;
|
||||
@@ -1736,6 +1845,23 @@ struct uwsgi_mule {
|
||||
char name[0xff];
|
||||
};
|
||||
|
||||
struct uwsgi_mule_farm {
|
||||
struct uwsgi_mule *mule;
|
||||
struct uwsgi_mule_farm *next;
|
||||
};
|
||||
|
||||
struct uwsgi_farm {
|
||||
int id;
|
||||
char name[0xff];
|
||||
|
||||
int signal_pipe[2];
|
||||
int queue_pipe[2];
|
||||
|
||||
struct uwsgi_mule_farm *mules;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
char *uwsgi_get_cwd(void);
|
||||
|
||||
@@ -1763,7 +1889,7 @@ void daemonize(char *);
|
||||
void logto(char *);
|
||||
|
||||
void log_request(struct wsgi_request *);
|
||||
void get_memusage(void);
|
||||
void get_memusage(uint64_t *, uint64_t *);
|
||||
void harakiri(void);
|
||||
|
||||
void stats(int);
|
||||
@@ -1787,6 +1913,7 @@ pid_t spooler_start(void);
|
||||
|
||||
void set_harakiri(int);
|
||||
void set_mule_harakiri(int);
|
||||
void set_spooler_harakiri(int);
|
||||
void inc_harakiri(int);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
@@ -1796,7 +1923,7 @@ uint64_t uwsgi_swap64(uint64_t);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
ssize_t send_udp_message(uint8_t, char *, char *, uint16_t);
|
||||
ssize_t send_udp_message(uint8_t, uint8_t, char *, char *, uint16_t);
|
||||
#endif
|
||||
|
||||
int uwsgi_parse_packet(struct wsgi_request *, int);
|
||||
@@ -2011,13 +2138,13 @@ void uwsgi_route_signal(uint8_t);
|
||||
int uwsgi_start(void *);
|
||||
|
||||
int uwsgi_register_rpc(char *, uint8_t, uint8_t, void *);
|
||||
uint16_t uwsgi_rpc(char *, uint8_t, char **, char *);
|
||||
uint16_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char *);
|
||||
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
|
||||
|
||||
char *uwsgi_cheap_string(char *, int);
|
||||
|
||||
int uwsgi_parse_array(char *, uint16_t, char **, uint8_t *);
|
||||
int uwsgi_parse_array(char *, uint16_t, char **, uint16_t *, uint8_t *);
|
||||
|
||||
void log_syslog(char *);
|
||||
|
||||
struct uwsgi_gateway *register_gateway(char *, void (*)(void));
|
||||
struct uwsgi_gateway *register_fat_gateway(char *, void (*)(void));
|
||||
@@ -2050,7 +2177,6 @@ ssize_t fcgi_send_record(int, uint8_t, uint16_t, char *);
|
||||
ssize_t fcgi_send_param(int, char *, uint16_t, char *, uint16_t);
|
||||
uint16_t fcgi_get_record(int, char *);
|
||||
|
||||
int uwsgi_attach_daemon(char *);
|
||||
void spawn_daemon(struct uwsgi_daemon *);
|
||||
|
||||
void emperor_loop(void);
|
||||
@@ -2113,30 +2239,6 @@ struct uwsgi_dict {
|
||||
struct uwsgi_dict_item *items;
|
||||
};
|
||||
|
||||
#define SUBSCRIBER_PAGESIZE 4096
|
||||
#define SUBSCRIBER_NODES (SUBSCRIBER_PAGESIZE/128)-4
|
||||
|
||||
struct uwsgi_subscriber_name {
|
||||
uint16_t len;
|
||||
char name[128];
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
// total requests managed by this node
|
||||
uint64_t requests;
|
||||
// bytes transferred by this node
|
||||
uint64_t transferred;
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_subscriber {
|
||||
uint64_t nodes;
|
||||
uint64_t current;
|
||||
// support upto md5
|
||||
char auth[32];
|
||||
struct uwsgi_subscriber_name names[SUBSCRIBER_NODES];
|
||||
};
|
||||
|
||||
struct uwsgi_subscribe_req {
|
||||
char *key;
|
||||
@@ -2150,15 +2252,11 @@ struct uwsgi_subscribe_req {
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
uint64_t cores;
|
||||
uint64_t load;
|
||||
};
|
||||
|
||||
struct uwsgi_dict *uwsgi_dict_create(uint64_t, uint64_t);
|
||||
void uwsgi_add_subscriber(struct uwsgi_dict *, struct uwsgi_subscribe_req *);
|
||||
char *uwsgi_dict_get(struct uwsgi_dict *, char *, uint16_t, uint64_t *);
|
||||
int uwsgi_dict_set(struct uwsgi_dict *, char *, uint16_t, char *, uint64_t);
|
||||
|
||||
struct uwsgi_subscriber_name *uwsgi_get_subscriber(struct uwsgi_dict *, char *, uint16_t);
|
||||
|
||||
#ifndef _NO_UWSGI_RB
|
||||
#include "lib/rbtree.h"
|
||||
|
||||
@@ -2224,7 +2322,7 @@ int uwsgi_netlink_del(char *);
|
||||
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *);
|
||||
char *uwsgi_amqp_consume(int, uint64_t *, char **);
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
inline int uwsgi_starts_with(char *, int, char *, int);
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -2263,7 +2361,7 @@ uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, ch
|
||||
uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
void log_zeromq(char *);
|
||||
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *, char *, size_t len);
|
||||
int uwsgi_proto_zeromq_accept(struct wsgi_request *, int);
|
||||
void uwsgi_proto_zeromq_close(struct wsgi_request *);
|
||||
ssize_t uwsgi_proto_zeromq_writev_header(struct wsgi_request *, struct iovec *, size_t);
|
||||
@@ -2309,9 +2407,7 @@ void uwsgi_ignition(void);
|
||||
void master_check_cluster_nodes(void);
|
||||
int uwsgi_respawn_worker(int);
|
||||
|
||||
void log_socket(char *);
|
||||
|
||||
socklen_t socket_to_in_addr(char *, char *, struct sockaddr_in *);
|
||||
socklen_t socket_to_in_addr(char *, char *, int, struct sockaddr_in *);
|
||||
socklen_t socket_to_un_addr(char *, struct sockaddr_un *);
|
||||
|
||||
int uwsgi_get_shared_socket_fd_by_num(int);
|
||||
@@ -2342,8 +2438,6 @@ int uwsgi_signal_registered(uint8_t);
|
||||
|
||||
int uwsgi_endswith(char *, char *);
|
||||
|
||||
char *uwsgi_get_var(struct wsgi_request *, char *, uint16_t *);
|
||||
|
||||
int uwsgi_cache_server(char *, int);
|
||||
|
||||
void uwsgi_chown(char *, char *);
|
||||
@@ -2360,6 +2454,7 @@ int uwsgi_simple_parse_vars(struct wsgi_request *, char *, char *);
|
||||
|
||||
void uwsgi_build_mime_dict(char *);
|
||||
struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **, char *, int, char *, int);
|
||||
void uwsgi_dyn_dict_del(struct uwsgi_dyn_dict *);
|
||||
|
||||
void uwsgi_send_stats(int);
|
||||
|
||||
@@ -2371,10 +2466,116 @@ char *uwsgi_string_get_list(struct uwsgi_string_list **, int, size_t *);
|
||||
|
||||
void uwsgi_fixup_fds(int, int);
|
||||
|
||||
void uwsgi_set_processname(char *);
|
||||
|
||||
void http_url_decode(char *, uint16_t *, char *);
|
||||
|
||||
pid_t uwsgi_fork(char *);
|
||||
|
||||
struct uwsgi_mule *get_mule_by_id(int);
|
||||
struct uwsgi_mule_farm *uwsgi_mule_farm_new(struct uwsgi_mule_farm **, struct uwsgi_mule *);
|
||||
|
||||
int uwsgi_farm_has_mule(struct uwsgi_farm *, int);
|
||||
struct uwsgi_farm *get_farm_by_name(char *);
|
||||
|
||||
struct uwsgi_subscribe_slot;
|
||||
|
||||
struct uwsgi_subscribe_node {
|
||||
|
||||
char name[0xff];
|
||||
uint16_t len;
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
time_t last_check;
|
||||
|
||||
uint64_t requests;
|
||||
uint64_t transferred;
|
||||
|
||||
int death_mark;
|
||||
uint64_t reference;
|
||||
uint64_t cores;
|
||||
uint64_t load;
|
||||
uint64_t failcnt;
|
||||
|
||||
struct uwsgi_subscribe_slot *slot;
|
||||
|
||||
struct uwsgi_subscribe_node *next;
|
||||
};
|
||||
|
||||
struct uwsgi_subscribe_slot {
|
||||
|
||||
char key[0xff];
|
||||
uint16_t keylen;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
#endif
|
||||
|
||||
uint64_t hits;
|
||||
|
||||
// used for round robin
|
||||
uint64_t rr;
|
||||
|
||||
struct uwsgi_subscribe_node *nodes;
|
||||
|
||||
struct uwsgi_subscribe_slot *prev;
|
||||
struct uwsgi_subscribe_slot *next;
|
||||
};
|
||||
|
||||
void mule_send_msg(int, char *, size_t);
|
||||
|
||||
void create_signal_pipe(int *);
|
||||
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t, int);
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t, int);
|
||||
int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_node *);
|
||||
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **, struct uwsgi_subscribe_req *, int);
|
||||
|
||||
ssize_t uwsgi_mule_get_msg(int, int, char *, size_t, int);
|
||||
|
||||
uint8_t uwsgi_signal_wait(int);
|
||||
void uwsgi_add_app(int, uint8_t, char *, int);
|
||||
int uwsgi_signal_send(int, uint8_t);
|
||||
int uwsgi_remote_signal_send(char *, uint8_t);
|
||||
|
||||
void uwsgi_configure(void);
|
||||
void cluster_setup(void);
|
||||
void manage_cluster_announce(char *, uint16_t, char *, uint16_t, void *);
|
||||
|
||||
int uwsgi_read_response(int, struct uwsgi_header *, int, char **);
|
||||
char *uwsgi_simple_file_read(char *);
|
||||
|
||||
void uwsgi_send_subscription(char *, char *, size_t , uint8_t, uint8_t , uint8_t);
|
||||
|
||||
void uwsgi_subscribe(char *, uint8_t);
|
||||
|
||||
struct uwsgi_daemon *uwsgi_daemon_new(struct uwsgi_daemon **, char *);
|
||||
|
||||
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **, char *, int (*)(int, struct uwsgi_signal_probe *));
|
||||
int uwsgi_add_probe(uint8_t sig, char *, char *, int, int);
|
||||
|
||||
int uwsgi_is_bad_connection(int);
|
||||
int uwsgi_long2str2n(unsigned long long, char *, int);
|
||||
|
||||
#ifdef __linux__
|
||||
void uwsgi_build_unshare(char *);
|
||||
#ifdef MADV_MERGEABLE
|
||||
void uwsgi_linux_ksm_map(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
void uwsgi_build_cap(char *);
|
||||
#endif
|
||||
|
||||
void uwsgi_register_logger(char *, ssize_t (*func)(struct uwsgi_logger *, char *, size_t));
|
||||
struct uwsgi_logger *uwsgi_get_logger(char *);
|
||||
|
||||
char *uwsgi_getsockname(int);
|
||||
char *uwsgi_get_var(struct wsgi_request *, char *, uint16_t, uint16_t *);
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
#endif
|
||||
|
||||
+54
-18
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.0-dev'
|
||||
uwsgi_version = '1.0'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -99,13 +99,13 @@ def compile(cflags, objfile, srcfile):
|
||||
except:
|
||||
pass
|
||||
cmdline = "%s -c %s -o %s %s" % (GCC, cflags, objfile, srcfile)
|
||||
print(cmdline)
|
||||
print("[%s] %s" % (GCC, objfile))
|
||||
ret = os.system(cmdline)
|
||||
if ret != 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def build_uwsgi(uc):
|
||||
def build_uwsgi(uc, print_only=False):
|
||||
|
||||
gcc_list, cflags, ldflags, libs = uc.get_gcll()
|
||||
|
||||
@@ -126,6 +126,12 @@ def build_uwsgi(uc):
|
||||
cflags.append(epc)
|
||||
cflags.append(eplc)
|
||||
|
||||
if print_only:
|
||||
print(' '.join(cflags))
|
||||
sys.exit(0)
|
||||
|
||||
print("configured CFLAGS: %s" % ' '.join(cflags))
|
||||
|
||||
print("*** uWSGI compiling server core ***")
|
||||
for file in gcc_list:
|
||||
objfile = file
|
||||
@@ -160,6 +166,11 @@ def build_uwsgi(uc):
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Werror=declaration-after-statement')
|
||||
except:
|
||||
pass
|
||||
|
||||
for cfile in up.GCC_LIST:
|
||||
if not cfile.endswith('.a'):
|
||||
compile(' '.join(p_cflags),
|
||||
@@ -213,9 +224,10 @@ def build_uwsgi(uc):
|
||||
|
||||
class uConf(object):
|
||||
|
||||
def __init__(self, filename):
|
||||
def __init__(self, filename, mute=False):
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
print("using profile: %s" % filename)
|
||||
if not mute:
|
||||
print("using profile: %s" % filename)
|
||||
if not os.path.exists(filename):
|
||||
raise Exception("profile not found !!!")
|
||||
|
||||
@@ -231,18 +243,26 @@ class uConf(object):
|
||||
ulp.close()
|
||||
|
||||
self.config.read(filename)
|
||||
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify', 'mule',
|
||||
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
|
||||
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify', 'mule', 'subscription',
|
||||
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'cluster', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
self.gcc_list.append('proto/uwsgi')
|
||||
self.gcc_list.append('proto/http')
|
||||
self.gcc_list.append('proto/fastcgi')
|
||||
self.include_path = []
|
||||
|
||||
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
|
||||
|
||||
if uwsgi_os == 'Linux':
|
||||
self.gcc_list.append('lib/linux_ns')
|
||||
self.gcc_list.append('lib/netlink')
|
||||
self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
|
||||
try:
|
||||
lk_ver = uwsgi_os_k.split('.')
|
||||
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]) <= 9:
|
||||
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
gcc_version = str(spcall("%s -dumpversion" % GCC))
|
||||
@@ -266,8 +286,8 @@ class uConf(object):
|
||||
except:
|
||||
self.include_path = ['/usr/include', '/usr/local/include']
|
||||
|
||||
|
||||
print("detected include path: %s" % self.include_path)
|
||||
if not mute:
|
||||
print("detected include path: %s" % self.include_path)
|
||||
|
||||
try:
|
||||
gcc_major = int(gcc_version.split('.')[0])
|
||||
@@ -789,11 +809,21 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Werror=declaration-after-statement')
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Winline')
|
||||
except:
|
||||
pass
|
||||
|
||||
#for ofile in up.OBJ_LIST:
|
||||
# gcc_list.insert(0,ofile)
|
||||
|
||||
gccline = "%s -fPIC %s -o %s.so %s %s %s %s" % (GCC, shared_flag, plugin_dest, ' '.join(p_cflags), ' '.join(p_ldflags), ' '.join(gcc_list), ' '.join(p_libs) )
|
||||
print(gccline)
|
||||
print("[%s] %s.so" % (GCC, plugin_dest))
|
||||
|
||||
ret = os.system(gccline)
|
||||
if ret != 0:
|
||||
@@ -809,13 +839,7 @@ if __name__ == "__main__":
|
||||
print("please specify an argument")
|
||||
sys.exit(1)
|
||||
|
||||
if cmd == '--cflags':
|
||||
print(' '.join(cflags))
|
||||
if cmd == '--ldflags':
|
||||
print(' '.join(ldflags))
|
||||
if cmd == '--libs':
|
||||
print(' '.join(libs))
|
||||
elif cmd == '--build':
|
||||
if cmd == '--build':
|
||||
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
|
||||
try:
|
||||
bconf = sys.argv[2]
|
||||
@@ -826,6 +850,17 @@ if __name__ == "__main__":
|
||||
if not '/' in bconf:
|
||||
bconf = 'buildconf/%s' % bconf
|
||||
build_uwsgi(uConf(bconf))
|
||||
elif cmd == '--cflags':
|
||||
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
|
||||
try:
|
||||
bconf = sys.argv[2]
|
||||
except:
|
||||
pass
|
||||
if not bconf.endswith('.ini'):
|
||||
bconf += '.ini'
|
||||
if not '/' in bconf:
|
||||
bconf = 'buildconf/%s' % bconf
|
||||
build_uwsgi(uConf(bconf, True), True)
|
||||
elif cmd == '--unbit':
|
||||
build_uwsgi(uConf('buildconf/unbit.ini'))
|
||||
elif cmd == '--plugin':
|
||||
@@ -844,6 +879,7 @@ if __name__ == "__main__":
|
||||
name = sys.argv[4]
|
||||
except:
|
||||
name = None
|
||||
print("*** uWSGI building and linking plugin %s ***" % sys.argv[2] )
|
||||
build_plugin(sys.argv[2], uc, cflags, ldflags, libs, name)
|
||||
elif cmd == '--clean':
|
||||
os.system("rm -f *.o")
|
||||
|
||||
+162
-17
@@ -1,15 +1,21 @@
|
||||
import uwsgi
|
||||
from threading import Thread
|
||||
|
||||
if uwsgi.masterpid() == 0:
|
||||
raise Exception("you have to enable the uWSGI master process to use this module")
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except:
|
||||
import pickle
|
||||
|
||||
if uwsgi.opt.get('lazy'):
|
||||
raise Exception("uWSGI lazy mode is not supported by this module")
|
||||
|
||||
if uwsgi.masterpid() == 0:
|
||||
raise Exception(
|
||||
"you have to enable the uWSGI master process to use this module")
|
||||
|
||||
spooler_functions = {}
|
||||
mule_functions = {}
|
||||
postfork_chain = []
|
||||
|
||||
|
||||
def get_free_signal():
|
||||
for signum in xrange(0, 256):
|
||||
if not uwsgi.signal_registered(signum):
|
||||
@@ -17,12 +23,14 @@ def get_free_signal():
|
||||
|
||||
raise Exception("No free uwsgi signal available")
|
||||
|
||||
|
||||
def manage_spool_request(vars):
|
||||
ret = spooler_functions[vars['ud_spool_func']](vars)
|
||||
if not vars.has_key('ud_spool_ret'):
|
||||
if not 'ud_spool_ret' in vars:
|
||||
return ret
|
||||
return int(vars['ud_spool_ret'])
|
||||
|
||||
|
||||
def postfork_chain_hook():
|
||||
for f in postfork_chain:
|
||||
f()
|
||||
@@ -30,10 +38,12 @@ def postfork_chain_hook():
|
||||
uwsgi.spooler = manage_spool_request
|
||||
uwsgi.post_fork_hook = postfork_chain_hook
|
||||
|
||||
|
||||
class postfork(object):
|
||||
def __init__(self, f):
|
||||
postfork_chain.append(f)
|
||||
|
||||
|
||||
class spool(object):
|
||||
|
||||
def spool(self, *args, **kwargs):
|
||||
@@ -46,12 +56,14 @@ class spool(object):
|
||||
return uwsgi.spool(arguments)
|
||||
|
||||
def __init__(self, f):
|
||||
if not uwsgi.opt.has_key('spooler'):
|
||||
raise Exception("you have to enable the uWSGI spooler to use the @spool decorator")
|
||||
if not 'spooler' in uwsgi.opt:
|
||||
raise Exception(
|
||||
"you have to enable the uWSGI spooler to use @spool decorator")
|
||||
self.f = f
|
||||
spooler_functions[f.__name__] = self.f
|
||||
self.f.spool = self.spool
|
||||
self.base_dict = {'ud_spool_func':self.f.__name__}
|
||||
self.base_dict = {'ud_spool_func': self.f.__name__}
|
||||
|
||||
|
||||
class spoolforever(spool):
|
||||
|
||||
@@ -64,6 +76,7 @@ class spoolforever(spool):
|
||||
arguments.update(kwargs)
|
||||
return uwsgi.spool(arguments)
|
||||
|
||||
|
||||
class spoolraw(spool):
|
||||
|
||||
def spool(self, *args, **kwargs):
|
||||
@@ -75,6 +88,44 @@ class spoolraw(spool):
|
||||
return uwsgi.spool(arguments)
|
||||
|
||||
|
||||
class mulefunc(object):
|
||||
|
||||
def __init__(self, f):
|
||||
if callable(f):
|
||||
self.fname = f.__name__
|
||||
self.mule = 0
|
||||
mule_functions[f.__name__] = f
|
||||
else:
|
||||
self.mule = f
|
||||
self.fname = None
|
||||
|
||||
def real_call(self, *args, **kwargs):
|
||||
uwsgi.mule_msg(pickle.dumps(
|
||||
{
|
||||
'service': 'uwsgi_mulefunc',
|
||||
'func': self.fname,
|
||||
'args': args,
|
||||
'kwargs': kwargs
|
||||
}
|
||||
), self.mule)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if not self.fname:
|
||||
self.fname = args[0].__name__
|
||||
mule_functions[self.fname] = args[0]
|
||||
return self.real_call
|
||||
|
||||
return self.real_call(*args, **kwargs)
|
||||
|
||||
|
||||
def mule_msg_dispatcher(message):
|
||||
msg = pickle.loads(message)
|
||||
if msg['service'] == 'uwsgi_mulefunc':
|
||||
return mule_functions[msg['func']](*msg['args'], **msg['kwargs'])
|
||||
|
||||
uwsgi.mule_msg_hook = mule_msg_dispatcher
|
||||
|
||||
|
||||
class rpc(object):
|
||||
|
||||
def __init__(self, name):
|
||||
@@ -84,28 +135,111 @@ class rpc(object):
|
||||
uwsgi.register_rpc(self.name, f)
|
||||
return f
|
||||
|
||||
|
||||
class farm_loop(object):
|
||||
|
||||
def __init__(self, f, farm):
|
||||
self.f = f
|
||||
self.farm = farm
|
||||
|
||||
def __call__(self):
|
||||
if uwsgi.mule_id() == 0:
|
||||
return
|
||||
if not uwsgi.in_farm(self.farm):
|
||||
return
|
||||
while True:
|
||||
message = uwsgi.farm_get_msg()
|
||||
if message:
|
||||
self.f(message)
|
||||
|
||||
|
||||
class farm(object):
|
||||
|
||||
def __init__(self, name=None, **kwargs):
|
||||
self.name = name
|
||||
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(farm_loop(f, self.name))
|
||||
|
||||
|
||||
class mule_brain(object):
|
||||
|
||||
def __init__(self, f, num):
|
||||
self.f = f
|
||||
self.num = num
|
||||
|
||||
def __call__(self):
|
||||
if uwsgi.mule_id() == self.num:
|
||||
self.f()
|
||||
|
||||
|
||||
class mule_brainloop(mule_brain):
|
||||
|
||||
def __call__(self):
|
||||
if uwsgi.mule_id() == self.num:
|
||||
while True:
|
||||
self.f()
|
||||
|
||||
|
||||
class mule(object):
|
||||
def __init__(self, num):
|
||||
self.num = num
|
||||
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(mule_brain(f, self.num))
|
||||
|
||||
|
||||
class muleloop(mule):
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(mule_brainloop(f, self.num))
|
||||
|
||||
|
||||
class mulemsg_loop(object):
|
||||
|
||||
def __init__(self, f, num):
|
||||
self.f = f
|
||||
self.num = num
|
||||
|
||||
def __call__(self):
|
||||
if uwsgi.mule_id() == self.num:
|
||||
while True:
|
||||
message = uwsgi.mule_get_msg()
|
||||
if message:
|
||||
self.f(message)
|
||||
|
||||
|
||||
class mulemsg(object):
|
||||
def __init__(self, num):
|
||||
self.num = num
|
||||
|
||||
def __call__(self, f):
|
||||
postfork_chain.append(mulemsg_loop(f, self.num))
|
||||
|
||||
|
||||
class signal(object):
|
||||
|
||||
def __init__(self, num, **kwargs):
|
||||
self.num = num
|
||||
self.target = kwargs.get('target', '')
|
||||
self.target = kwargs.get('target', '')
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.register_signal(self.num, self.target, f)
|
||||
return f
|
||||
|
||||
|
||||
class timer(object):
|
||||
|
||||
def __init__(self, secs, **kwargs):
|
||||
self.num = kwargs.get('signum', get_free_signal())
|
||||
self.secs = secs
|
||||
self.target = kwargs.get('target', '')
|
||||
self.target = kwargs.get('target', '')
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.register_signal(self.num, self.target, f)
|
||||
uwsgi.add_timer(self.num, self.secs)
|
||||
return f
|
||||
|
||||
|
||||
class cron(object):
|
||||
|
||||
def __init__(self, minute, hour, day, month, dayweek, **kwargs):
|
||||
@@ -115,39 +249,51 @@ class cron(object):
|
||||
self.day = day
|
||||
self.month = month
|
||||
self.dayweek = dayweek
|
||||
self.target = kwargs.get('target', '')
|
||||
self.target = kwargs.get('target', '')
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.register_signal(self.num, self.target, f)
|
||||
uwsgi.add_cron(self.num, self.minute, self.hour, self.day, self.month, self.dayweek)
|
||||
uwsgi.add_cron(self.num, self.minute, self.hour,
|
||||
self.day, self.month, self.dayweek)
|
||||
return f
|
||||
|
||||
|
||||
|
||||
class rbtimer(object):
|
||||
|
||||
def __init__(self, secs, **kwargs):
|
||||
self.num = kwargs.get('signum', get_free_signal())
|
||||
self.secs = secs
|
||||
self.target = kwargs.get('target', '')
|
||||
self.target = kwargs.get('target', '')
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.register_signal(self.num, self.target, f)
|
||||
uwsgi.add_rb_timer(self.num, self.secs)
|
||||
return f
|
||||
|
||||
|
||||
class filemon(object):
|
||||
|
||||
def __init__(self, fsobj, **kwargs):
|
||||
self.num = kwargs.get('signum', get_free_signal())
|
||||
self.fsobj = fsobj
|
||||
self.target = kwargs.get('target', '')
|
||||
self.target = kwargs.get('target', '')
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.register_signal(self.num, self.target, f)
|
||||
uwsgi.add_file_monitor(self.num, self.fsobj)
|
||||
return f
|
||||
|
||||
|
||||
class erlang(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __call__(self, f):
|
||||
uwsgi.erlang_register_process(self.name, f)
|
||||
return f
|
||||
|
||||
|
||||
class lock(object):
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
@@ -162,6 +308,7 @@ class lock(object):
|
||||
finally:
|
||||
uwsgi.unlock()
|
||||
|
||||
|
||||
class thread(object):
|
||||
|
||||
def __init__(self, f):
|
||||
@@ -172,5 +319,3 @@ class thread(object):
|
||||
t.daemon = True
|
||||
t.start()
|
||||
return self.f
|
||||
|
||||
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
# based on uwsgidecorators.py
|
||||
|
||||
if UWSGI.masterpid == 0
|
||||
raise "you have to enable the uWSGI master process to use this module"
|
||||
end
|
||||
|
||||
def get_free_signal()
|
||||
for signum in 0..255
|
||||
if not UWSGI.signal_registered(signum)
|
||||
return signum
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$postfork_chain = []
|
||||
$mulefunc_list = []
|
||||
$spoolfunc_list = []
|
||||
|
||||
module UWSGI
|
||||
module_function
|
||||
def post_fork_hook()
|
||||
$postfork_chain.each {|func| func.call }
|
||||
end
|
||||
|
||||
module_function
|
||||
def spooler(args)
|
||||
$spoolfunc_list[args['ud_spool_func'].to_i].call(args)
|
||||
end
|
||||
|
||||
module_function
|
||||
def mule_msg_hook(message)
|
||||
service = Marshal.load(message)
|
||||
if service['service'] == 'uwsgi_mulefunc'
|
||||
mulefunc_manager(service)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def timer(secs, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_timer(freesig, secs)
|
||||
end
|
||||
|
||||
def rbtimer(secs, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_rb_timer(freesig, secs)
|
||||
end
|
||||
|
||||
def filemon(file, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_file_monitor(freesig, file)
|
||||
end
|
||||
|
||||
def cron(minute, hour, day, month, dayweek, target='', &block)
|
||||
freesig = get_free_signal
|
||||
UWSGI.register_signal(freesig, target, block)
|
||||
UWSGI.add_cron(freesig, minute, hour, day, month, dayweek)
|
||||
end
|
||||
|
||||
def signal(signum, target='', &block)
|
||||
UWSGI.register_signal(signum, target, block)
|
||||
end
|
||||
|
||||
def postfork(&block)
|
||||
$postfork_chain << block
|
||||
end
|
||||
|
||||
class SpoolProc < Proc
|
||||
def initialize(&block)
|
||||
@block = block
|
||||
@id = (($spoolfunc_list << block).length-1).to_s
|
||||
end
|
||||
|
||||
def call(args)
|
||||
args['ud_spool_func'] = @id
|
||||
UWSGI::send_to_spooler(args)
|
||||
end
|
||||
end
|
||||
|
||||
def rpc(name, &block)
|
||||
if block.arity <= 0
|
||||
UWSGI.register_rpc(name, block, 0)
|
||||
else
|
||||
UWSGI.register_rpc(name, block, block.arity)
|
||||
end
|
||||
end
|
||||
|
||||
def mulefunc_manager(service)
|
||||
$mulefunc_list[service['func']].real_call(service['args'])
|
||||
end
|
||||
|
||||
class MuleFunc < Proc
|
||||
|
||||
def initialize(id=0, &block)
|
||||
@id = id
|
||||
@block = block
|
||||
@func_pos = (($mulefunc_list << self).length)-1
|
||||
end
|
||||
|
||||
def real_call(*args)
|
||||
@block.call(*args)
|
||||
end
|
||||
|
||||
def call(*args)
|
||||
UWSGI.mule_msg( Marshal.dump( {
|
||||
'service' => 'uwsgi_mulefunc',
|
||||
'func' => @func_pos,
|
||||
'args'=> args
|
||||
}), @id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class MuleProc < Proc
|
||||
def initialize(id, block)
|
||||
@id = id
|
||||
@block = block
|
||||
end
|
||||
|
||||
def call()
|
||||
if UWSGI.mule_id == @id
|
||||
@block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MuleLoopProc < MuleProc
|
||||
def call()
|
||||
if UWSGI.mule_id == @id
|
||||
loop do
|
||||
@block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mule(id, &block)
|
||||
$postfork_chain << MuleProc.new(id, block)
|
||||
end
|
||||
|
||||
def muleloop(id, &block)
|
||||
$postfork_chain << MuleLoopProc.new(id, block)
|
||||
end
|
||||
+32
-13
@@ -2,11 +2,12 @@ import uwsgi
|
||||
import os
|
||||
import gc
|
||||
import sys
|
||||
from uwsgidecorators import *
|
||||
gc.set_debug(gc.DEBUG_SAVEALL)
|
||||
|
||||
print os.environ
|
||||
print sys.modules
|
||||
print sys.argv
|
||||
print(os.environ)
|
||||
print(sys.modules)
|
||||
print(sys.argv)
|
||||
|
||||
try:
|
||||
if sys.argv[1] == 'debug':
|
||||
@@ -29,12 +30,12 @@ def serve_logo(e, sr):
|
||||
def serve_options(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in xrange(0,256):
|
||||
yield "%d = %d<br/>" % (opt, uwsgi.get_option(opt))
|
||||
yield "<b>%d</b> = %d<br/>" % (opt, uwsgi.get_option(opt))
|
||||
|
||||
def serve_config(e, sr):
|
||||
sr('200 OK', [('Content-Type', 'text/html')])
|
||||
for opt in uwsgi.opt.keys():
|
||||
yield "%s = %s<br/>" % (opt, uwsgi.opt[opt])
|
||||
yield "<b>%s</b> = %s<br/>" % (opt, uwsgi.opt[opt])
|
||||
|
||||
routes = {}
|
||||
routes['/xsendfile'] = xsendfile
|
||||
@@ -42,13 +43,28 @@ routes['/logo'] = serve_logo
|
||||
routes['/config'] = serve_config
|
||||
routes['/options'] = serve_options
|
||||
|
||||
@postfork
|
||||
def setprocname():
|
||||
if uwsgi.worker_id() > 0:
|
||||
uwsgi.setprocname("i am the worker %d" % uwsgi.worker_id())
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
uwsgi.mule_msg(env['REQUEST_URI'], 1)
|
||||
try:
|
||||
uwsgi.mule_msg(env['REQUEST_URI'], 1)
|
||||
except:
|
||||
pass
|
||||
|
||||
gc.collect(2)
|
||||
req = uwsgi.workers()[uwsgi.worker_id()-1]['requests']
|
||||
|
||||
uwsgi.setprocname("worker %d managed %d requests" % (uwsgi.worker_id(), req))
|
||||
|
||||
try:
|
||||
gc.collect(2)
|
||||
except:
|
||||
pass
|
||||
if DEBUG:
|
||||
print env['wsgi.input'].fileno()
|
||||
print(env['wsgi.input'].fileno())
|
||||
|
||||
if routes.has_key(env['PATH_INFO']):
|
||||
return routes[env['PATH_INFO']](env, start_response)
|
||||
@@ -56,12 +72,15 @@ def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
|
||||
if DEBUG:
|
||||
print env['wsgi.input'].fileno()
|
||||
print(env['wsgi.input'].fileno())
|
||||
|
||||
gc.collect(2)
|
||||
try:
|
||||
gc.collect(2)
|
||||
except:
|
||||
pass
|
||||
|
||||
if DEBUG:
|
||||
print len(gc.get_objects())
|
||||
print(len(gc.get_objects()))
|
||||
|
||||
workers = ''
|
||||
for w in uwsgi.workers():
|
||||
@@ -76,7 +95,7 @@ def application(env, start_response):
|
||||
""" % (w['id'], w['pid'], w['status'], w['running_time']/1000, w['avg_rt']/1000, w['tx'], apps)
|
||||
|
||||
return """
|
||||
<img src="/logo"/> version %s<br/>
|
||||
<img src="/logo"/> version %s running on %s<br/>
|
||||
<hr size="1"/>
|
||||
|
||||
Configuration<br/>
|
||||
@@ -96,7 +115,7 @@ Workers and applications<br/>
|
||||
%s
|
||||
</table>
|
||||
|
||||
""" % (uwsgi.version, workers)
|
||||
""" % (uwsgi.version, uwsgi.hostname, workers)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, int app_tag
|
||||
add_exported_option((char *) node->name, (char *) node->children->content, 0);
|
||||
}
|
||||
else {
|
||||
add_exported_option((char *) node->name, "1", 0);
|
||||
add_exported_option((char *) node->name, strdup("1"), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,10 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
|
||||
case YAML_VALUE_TOKEN:
|
||||
status = 2;
|
||||
break;
|
||||
case YAML_FLOW_SEQUENCE_START_TOKEN:
|
||||
case YAML_BLOCK_SEQUENCE_START_TOKEN:
|
||||
status = 3;
|
||||
break;
|
||||
case YAML_BLOCK_MAPPING_START_TOKEN:
|
||||
if (!in_uwsgi_section) {
|
||||
if (key) {
|
||||
@@ -170,6 +174,8 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
break;
|
||||
case YAML_SCALAR_TOKEN:
|
||||
case YAML_FLOW_ENTRY_TOKEN:
|
||||
case YAML_BLOCK_ENTRY_TOKEN:
|
||||
if (status == 1) {
|
||||
key = (char *) token.data.scalar.value;
|
||||
}
|
||||
@@ -180,6 +186,12 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
|
||||
}
|
||||
status = 0;
|
||||
}
|
||||
else if (status == 3) {
|
||||
val = (char *) token.data.scalar.value;
|
||||
if (key && val && in_uwsgi_section) {
|
||||
add_exported_option(key, val, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
|
||||
parsing = 0;
|
||||
|
||||
Reference in New Issue
Block a user