mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d248b290f2 | ||
|
|
cb48070db1 | ||
|
|
cd34bac104 | ||
|
|
c966fbb163 | ||
|
|
feac596efc | ||
|
|
981ddfcefe | ||
|
|
5e561b6578 | ||
|
|
fab495fadc | ||
|
|
ecbda6dc26 | ||
|
|
e23766e4d0 | ||
|
|
6d9de4c618 | ||
|
|
4ca14f6046 | ||
|
|
d856c9920d | ||
|
|
fd62440265 | ||
|
|
d4041c9e1d | ||
|
|
dc9e1bd324 | ||
|
|
89bbd967ed | ||
|
|
276ada315d | ||
|
|
bdd0d408a0 | ||
|
|
5ddaa2e436 | ||
|
|
f9d0e75056 | ||
|
|
7776a1f0be | ||
|
|
a33a57d8af | ||
|
|
9371e2b8de | ||
|
|
6c1a842f7d | ||
|
|
d746deaf02 | ||
|
|
09fca72b4c | ||
|
|
2ffc31e578 | ||
|
|
2a254d195a | ||
|
|
95d3ee4e61 | ||
|
|
4d56474511 | ||
|
|
46a33b268a | ||
|
|
b0829cc2e3 | ||
|
|
93a0913182 | ||
|
|
0605148e21 | ||
|
|
e7b5c7c8e4 | ||
|
|
b2a0fd1914 | ||
|
|
9cc89a6052 | ||
|
|
1606b8b775 | ||
|
|
cfac385f8e | ||
|
|
99fd4572cb | ||
|
|
d3194ca011 | ||
|
|
af61a9e33f | ||
|
|
4896e22a62 | ||
|
|
7882d12a80 | ||
|
|
9342acc500 | ||
|
|
929a919c9d | ||
|
|
d1f6e97dd7 | ||
|
|
f9d76f90eb | ||
|
|
2de5e8994f | ||
|
|
7e935253a2 | ||
|
|
4c20d83573 | ||
|
|
7035a676a2 | ||
|
|
736f99d10b | ||
|
|
ea422a4576 | ||
|
|
e274f53286 | ||
|
|
c03dcf4617 | ||
|
|
d70c7ceb89 | ||
|
|
9ae1354d1a | ||
|
|
b29f0b9436 | ||
|
|
e01cd802d8 | ||
|
|
c7b57c9776 | ||
|
|
3a48b898ad | ||
|
|
4f4771b527 | ||
|
|
b43df60d7f | ||
|
|
10a5661218 | ||
|
|
a99670cfb5 | ||
|
|
7967e8ac3c | ||
|
|
e105ebe273 | ||
|
|
11d2c004c2 | ||
|
|
e8bfa12372 | ||
|
|
317e9efa2d | ||
|
|
4b99bff520 | ||
|
|
99f584cff0 | ||
|
|
fc6a79dcc9 | ||
|
|
75af812b83 | ||
|
|
0f4e1eb7e2 | ||
|
|
a3e0c2260f | ||
|
|
3f63caa5eb | ||
|
|
61bd3fb0e6 | ||
|
|
d6b4b8ea6e | ||
|
|
3a451fb42f | ||
|
|
7017712c6d | ||
|
|
49140c3387 | ||
|
|
1d9edc3e34 | ||
|
|
fffe070e30 | ||
|
|
29ce04adce | ||
|
|
c487fb0cf0 | ||
|
|
503fcd5ed5 | ||
|
|
7136beeff7 | ||
|
|
64c7d71c35 | ||
|
|
d2d714e933 | ||
|
|
f7399ef2ec | ||
|
|
4014bc53bd | ||
|
|
b8f42a8d0b | ||
|
|
b40442a0f8 | ||
|
|
bee3bf5d43 | ||
|
|
59cc3d7c04 | ||
|
|
8dc072732b | ||
|
|
37b7c31849 | ||
|
|
738b886267 | ||
|
|
8679f8b845 | ||
|
|
ecfae75886 | ||
|
|
cefc9fcc58 | ||
|
|
03104063cb | ||
|
|
ef10dc054f | ||
|
|
242497102e | ||
|
|
0242b464e7 | ||
|
|
353b837f67 | ||
|
|
d70ecab49f | ||
|
|
c65adaaac7 | ||
|
|
4f0406c1cc | ||
|
|
6ea535a74d | ||
|
|
2e66ae9abe | ||
|
|
39aa8ca8be | ||
|
|
ef80a7bba9 | ||
|
|
8a65125ae5 | ||
|
|
86d9b4bc0e | ||
|
|
1d691139c7 | ||
|
|
94eb4f078e | ||
|
|
47f3b39870 | ||
|
|
c67d26f8cc | ||
|
|
9c99b29e47 | ||
|
|
5ce2020d6f | ||
|
|
d965587d9d | ||
|
|
4f85c215cd | ||
|
|
1015ef9611 | ||
|
|
adcbc061b1 | ||
|
|
42229b08ce | ||
|
|
7bac625537 | ||
|
|
a3e9a288d3 | ||
|
|
946a46df86 | ||
|
|
e368b2da5e | ||
|
|
6b32ac086e | ||
|
|
1651e3b0ef | ||
|
|
fee6c65365 | ||
|
|
6070bd70a7 | ||
|
|
86ea390ba8 | ||
|
|
e9158255a1 | ||
|
|
cd80885a49 | ||
|
|
8925ea06e1 | ||
|
|
f1135c736a | ||
|
|
c9f0786edd | ||
|
|
7e52f14786 | ||
|
|
e35dcdbcdb | ||
|
|
c59a3cb35a | ||
|
|
a9703f8533 | ||
|
|
0de510b777 | ||
|
|
8a0fa1ffc4 | ||
|
|
4ca422a0a8 | ||
|
|
a979abf0c6 | ||
|
|
d12ddded55 | ||
|
|
3beead6459 | ||
|
|
248741a81f | ||
|
|
188b66e92c | ||
|
|
5ae1c6fbd1 | ||
|
|
51b9b5d070 | ||
|
|
dafe3bb12c | ||
|
|
973e508af7 | ||
|
|
8e31bb612e | ||
|
|
f920ac0fb0 | ||
|
|
ae1b5afd7d | ||
|
|
1f2bae130e | ||
|
|
4417e55862 | ||
|
|
74a84bdd3a | ||
|
|
b764252e7f | ||
|
|
2fd71be9d9 | ||
|
|
d65f873e77 | ||
|
|
1427c9ce1c | ||
|
|
c3de9320d7 | ||
|
|
674151e485 | ||
|
|
9c042ffc1c | ||
|
|
15194e6b55 |
@@ -0,0 +1,5 @@
|
||||
*.o
|
||||
*.py[co]
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
@@ -54,3 +54,5 @@ e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
|
||||
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
|
||||
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
|
||||
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
|
||||
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
|
||||
|
||||
@@ -18,3 +18,6 @@ Lukas Lalinsky
|
||||
Steven Fernandez
|
||||
Łukasz Mierzwa
|
||||
Roy Marples
|
||||
Aarni Koskela
|
||||
C Anthony Risinger
|
||||
Stephen Pierce
|
||||
|
||||
@@ -10,12 +10,27 @@
|
||||
- merged routers codebase (fastrouter, http, rawrouter)
|
||||
- https support in the http router
|
||||
- config report at the end of uWSGI build process
|
||||
- support for keepalive in the http router
|
||||
- improved subscription system (multicast and unix socket)
|
||||
- custom options
|
||||
- graceful reloads on shared sockets
|
||||
- configurable log-master buffer size
|
||||
- extreme-optimizations for the stats subsystem
|
||||
- redislog and mongodblog plugins
|
||||
- added python logger
|
||||
- mongodb and postgres imperial monitors
|
||||
- implemented psgix.logger and psgix.cleanup
|
||||
- full rack spec compliance
|
||||
- preliminary ipv6 support
|
||||
- gevent graceful reloads
|
||||
- support for multiple loggers and logformat
|
||||
- lazy-apps to load apps after fork() but without changing reloading subsystem
|
||||
- emperor heartbeat subsystem
|
||||
- cheaper busyness plugin
|
||||
- pluggable clock sources
|
||||
- added router_rewrite and router_http plugins
|
||||
- external spoolers
|
||||
- support for section:// and fd:// loaders
|
||||
- alarm subsystem (with curl and xmpp plugins)
|
||||
|
||||
|
||||
*** april 2012 ***
|
||||
|
||||
@@ -3,3 +3,6 @@ all:
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
|
||||
check:
|
||||
python uwsgiconfig.py --check
|
||||
|
||||
+2
-2
@@ -12,12 +12,12 @@ ssl = auto
|
||||
udp = true
|
||||
multicast = true
|
||||
threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
alarm = auto
|
||||
ipv6 = false
|
||||
debug = false
|
||||
unbit = false
|
||||
@@ -29,7 +29,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -1,30 +0,0 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
snmp = true
|
||||
erlang = false
|
||||
spooler = true
|
||||
embedded = true
|
||||
udp = true
|
||||
multicast = true
|
||||
threading = true
|
||||
sendfile = true
|
||||
proxy = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
http = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
routing = false
|
||||
stackless = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
plugin_dir = .
|
||||
embedded_plugins = python, ping, nagios, rack
|
||||
|
||||
[python]
|
||||
paste = true
|
||||
web3 = true
|
||||
@@ -1,29 +0,0 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
snmp = true
|
||||
erlang = false
|
||||
spooler = false
|
||||
embedded = false
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
nagios = true
|
||||
proxy = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ugreen = false
|
||||
http = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
routing = false
|
||||
stackless = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
plugins = rack
|
||||
bin_name = uwsgi
|
||||
plugin_dir = .
|
||||
embedded_plugins =
|
||||
+1
-1
@@ -11,12 +11,12 @@ embedded = true
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
ldap = true
|
||||
pcre = true
|
||||
routing = true
|
||||
alarm = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
ini = true
|
||||
yaml = false
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
spooler = true
|
||||
embedded = true
|
||||
udp = true
|
||||
multicast = false
|
||||
threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins =
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// generate a uwsgi signal on alarm
|
||||
void uwsgi_alarm_init_signal(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data8 = atoi(uai->arg);
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uwsgi_route_signal(uai->data8);
|
||||
}
|
||||
|
||||
// run a command on alarm
|
||||
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = uai->arg;
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_cmd(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
int pipe[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe)) {
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(pipe[0]);
|
||||
uwsgi_socket_nb(pipe[1]);
|
||||
if (write(pipe[1], msg, len) != (ssize_t) len) {
|
||||
close(pipe[0]);
|
||||
close(pipe[1]);
|
||||
return;
|
||||
}
|
||||
uwsgi_run_command(uai->data_ptr, pipe, -1);
|
||||
close(pipe[0]);
|
||||
close(pipe[1]);
|
||||
}
|
||||
|
||||
// pass the log line to a mule
|
||||
|
||||
void uwsgi_alarm_init_mule(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data32 = atoi(uai->arg);
|
||||
if (uai->data32 > (uint32_t) uwsgi.mules_cnt) {
|
||||
uwsgi_log_alarm("] invalid mule_id (%d mules available), fallback to 0\n", uwsgi.mules_cnt);
|
||||
uai->data32 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_alarm_func_mule(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
// skip if mules are not available
|
||||
if (uwsgi.mules_cnt == 0) return;
|
||||
int fd = uwsgi.shared->mule_queue_pipe[0];
|
||||
if (uai->data32 > 0) {
|
||||
int mule_id = uai->data32-1;
|
||||
fd = uwsgi.mules[mule_id].queue_pipe[0];
|
||||
}
|
||||
mule_send_msg(fd, msg, len);
|
||||
}
|
||||
|
||||
|
||||
// register a new alarm
|
||||
void uwsgi_register_alarm(char *name, void (*init)(struct uwsgi_alarm_instance *), void (*func)(struct uwsgi_alarm_instance *, char *, size_t)) {
|
||||
struct uwsgi_alarm *old_ua=NULL,*ua = uwsgi.alarms;
|
||||
while(ua) {
|
||||
// skip already initialized alarms
|
||||
if (!strcmp(ua->name, name)) {
|
||||
return;
|
||||
}
|
||||
old_ua = ua;
|
||||
ua = ua->next;
|
||||
}
|
||||
|
||||
ua = uwsgi_calloc(sizeof(struct uwsgi_alarm));
|
||||
ua->name = name;
|
||||
ua->init = init;
|
||||
ua->func = func;
|
||||
|
||||
if (old_ua) {
|
||||
old_ua->next = ua;
|
||||
}
|
||||
else {
|
||||
uwsgi.alarms = ua;
|
||||
}
|
||||
}
|
||||
|
||||
// register embedded alarms
|
||||
void uwsgi_register_embedded_alarms() {
|
||||
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
|
||||
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
|
||||
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
|
||||
}
|
||||
|
||||
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
|
||||
struct uwsgi_alarm *ua = uwsgi.alarms;
|
||||
while(ua) {
|
||||
if (!strcmp(ua->name, plugin)) {
|
||||
break;
|
||||
}
|
||||
ua = ua->next;
|
||||
}
|
||||
|
||||
if (!ua) return -1;
|
||||
|
||||
struct uwsgi_alarm_instance *old_uai = NULL, *uai = uwsgi.alarm_instances;
|
||||
while(uai) {
|
||||
old_uai = uai;
|
||||
uai = uai->next;
|
||||
}
|
||||
|
||||
uai = uwsgi_calloc(sizeof(struct uwsgi_alarm_instance));
|
||||
uai->name = name;
|
||||
uai->alarm = ua;
|
||||
uai->arg = arg;
|
||||
uai->last_msg = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
|
||||
if (old_uai) {
|
||||
old_uai->next = uai;
|
||||
}
|
||||
else {
|
||||
uwsgi.alarm_instances = uai;
|
||||
}
|
||||
|
||||
ua->init(uai);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get an alarm instance by its name
|
||||
static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi.alarm_instances;
|
||||
while(uai) {
|
||||
if (!strcmp(name, uai->name)) {
|
||||
return uai;
|
||||
}
|
||||
uai = uai->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_alarm_log_add(char *alarms, char *regexp) {
|
||||
|
||||
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
|
||||
while(ual) {
|
||||
old_ual = ual;
|
||||
ual = ual->next;
|
||||
}
|
||||
|
||||
ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
|
||||
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (old_ual) {
|
||||
old_ual->next = ual;
|
||||
}
|
||||
else {
|
||||
uwsgi.alarm_logs = ual;
|
||||
}
|
||||
|
||||
// map instances to the log
|
||||
char *list = uwsgi_str(alarms);
|
||||
char *p = strtok(list, ",");
|
||||
while(p) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) return -1;
|
||||
struct uwsgi_alarm_ll *old_uall=NULL,*uall = ual->alarms;
|
||||
while(uall) {
|
||||
old_uall = uall;
|
||||
uall = uall->next;
|
||||
}
|
||||
|
||||
uall = uwsgi_calloc(sizeof(struct uwsgi_alarm_ll));
|
||||
uall->alarm = uai;
|
||||
if (old_uall) {
|
||||
old_uall->next = uall;
|
||||
}
|
||||
else {
|
||||
ual->alarms = uall;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize alarms, instances and log regexps
|
||||
void uwsgi_alarms_init() {
|
||||
|
||||
// first of all, create instance of alarms
|
||||
struct uwsgi_string_list *usl = uwsgi.alarm_list;
|
||||
while(usl) {
|
||||
char *line = uwsgi_str(usl->value);
|
||||
char *space = strchr(line, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
char *plugin = space+1;
|
||||
char *colon = strchr(plugin, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
char *arg = colon+1;
|
||||
// here the alarm is mapped to a name and initialized
|
||||
if (uwsgi_alarm_add(line, plugin, arg)) {
|
||||
uwsgi_log("invalid alarm: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
// then map log-alarm
|
||||
usl = uwsgi.alarm_logs_list;
|
||||
while(usl) {
|
||||
char *line = uwsgi_str(usl->value);
|
||||
char *space = strchr(line, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid log-alarm syntax: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
char *regexp = space+1;
|
||||
// here the log-alarm is created
|
||||
if (uwsgi_alarm_log_add(line, regexp)) {
|
||||
uwsgi_log("invalid log-alarm: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a log should raise an alarm
|
||||
void uwsgi_alarm_log_check(char *msg, size_t len) {
|
||||
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12)) return;
|
||||
struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
|
||||
while(ual) {
|
||||
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
|
||||
uwsgi_alarm_log_run(ual, msg, len);
|
||||
}
|
||||
ual = ual->next;
|
||||
}
|
||||
}
|
||||
|
||||
// call the alarm func
|
||||
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
time_t now = uwsgi_now();
|
||||
// avoid alarm storming/loop if last message is the same
|
||||
if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) {
|
||||
if (now - uai->last_run < uwsgi.alarm_freq) return;
|
||||
}
|
||||
uai->alarm->func(uai, msg, len);
|
||||
uai->last_run = uwsgi_now();
|
||||
memcpy(uai->last_msg, msg, len);
|
||||
uai->last_msg_size = len;
|
||||
}
|
||||
|
||||
// call the alarms mapped to a log line
|
||||
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
|
||||
struct uwsgi_alarm_ll *uall = ual->alarms;
|
||||
while(uall) {
|
||||
uwsgi_alarm_run(uall->alarm, msg, len);
|
||||
uall = uall->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+121
-128
@@ -7,21 +7,21 @@ void uwsgi_async_init() {
|
||||
|
||||
uwsgi.async_queue = event_queue_init();
|
||||
|
||||
if (uwsgi.async_queue < 0) {
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.async_queue < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
|
||||
uwsgi_add_sockets_to_queue(uwsgi.async_queue, -1);
|
||||
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -37,23 +37,23 @@ void runqueue_remove(struct uwsgi_async_request *u_request) {
|
||||
|
||||
struct uwsgi_async_request *parent = u_request->prev;
|
||||
struct uwsgi_async_request *child = u_request->next;
|
||||
|
||||
if (parent) {
|
||||
parent->next = child;
|
||||
}
|
||||
if (child) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
if (parent) {
|
||||
parent->next = child;
|
||||
}
|
||||
if (child) {
|
||||
child->prev = parent;
|
||||
}
|
||||
|
||||
if (parent == NULL) {
|
||||
uwsgi.async_runqueue = child;
|
||||
}
|
||||
|
||||
if (u_request == uwsgi.async_runqueue_last) {
|
||||
uwsgi.async_runqueue_last = parent;
|
||||
}
|
||||
|
||||
free(u_request);
|
||||
free(u_request);
|
||||
|
||||
uwsgi.async_runqueue_cnt--;
|
||||
}
|
||||
@@ -63,21 +63,21 @@ void runqueue_push(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_async_request *uar;
|
||||
|
||||
if (uwsgi.async_runqueue == NULL) {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
}
|
||||
else {
|
||||
// empty runqueue, create a new one
|
||||
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uwsgi.async_runqueue->next = NULL;
|
||||
uwsgi.async_runqueue->prev = NULL;
|
||||
uwsgi.async_runqueue->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
|
||||
}
|
||||
else {
|
||||
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
}
|
||||
uar->prev = uwsgi.async_runqueue_last;
|
||||
uar->next = NULL;
|
||||
uar->wsgi_req = wsgi_req;
|
||||
uwsgi.async_runqueue_last->next = uar;
|
||||
uwsgi.async_runqueue_last = uar;
|
||||
}
|
||||
|
||||
uwsgi.async_runqueue_cnt++;
|
||||
|
||||
@@ -104,14 +104,15 @@ void async_expire_timeouts() {
|
||||
|
||||
struct uwsgi_rb_timer *urbt;
|
||||
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
|
||||
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
|
||||
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
|
||||
|
||||
if (urbt == NULL) return;
|
||||
if (urbt == NULL)
|
||||
return;
|
||||
|
||||
if (urbt->key <= current_time) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
if (urbt->key <= current_time) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
@@ -119,7 +120,7 @@ void async_expire_timeouts() {
|
||||
wsgi_req->async_timeout = NULL;
|
||||
uaf = wsgi_req->waiting_fds;
|
||||
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
|
||||
while(uaf) {
|
||||
while (uaf) {
|
||||
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
|
||||
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
|
||||
current_uaf = uaf;
|
||||
@@ -129,11 +130,11 @@ void async_expire_timeouts() {
|
||||
wsgi_req->waiting_fds = NULL;
|
||||
// put th request in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -141,10 +142,11 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0) return ;
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
// find first slot
|
||||
while(uad) {
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
}
|
||||
@@ -167,48 +169,49 @@ void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
}
|
||||
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
|
||||
event_queue_add_fd_read(uwsgi.async_queue, fd);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now()+timeout, wsgi_req);
|
||||
}
|
||||
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0) return ;
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
// find first slot
|
||||
while(uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
}
|
||||
// find first slot
|
||||
while (uad) {
|
||||
last_uad = uad;
|
||||
uad = uad->next;
|
||||
}
|
||||
|
||||
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
|
||||
uad->fd = fd;
|
||||
uad = uwsgi_malloc(sizeof(struct uwsgi_async_fd));
|
||||
uad->fd = fd;
|
||||
uad->event = event_queue_write();
|
||||
uad->prev = last_uad;
|
||||
uad->next = NULL;
|
||||
uad->prev = last_uad;
|
||||
uad->next = NULL;
|
||||
|
||||
if (last_uad) {
|
||||
last_uad->next = uad;
|
||||
}
|
||||
else {
|
||||
wsgi_req->waiting_fds = uad;
|
||||
}
|
||||
if (last_uad) {
|
||||
last_uad->next = uad;
|
||||
}
|
||||
else {
|
||||
wsgi_req->waiting_fds = uad;
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
async_add_timeout(wsgi_req, timeout);
|
||||
}
|
||||
|
||||
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
|
||||
event_queue_add_fd_write(uwsgi.async_queue, fd);
|
||||
event_queue_add_fd_write(uwsgi.async_queue, fd);
|
||||
|
||||
}
|
||||
|
||||
@@ -216,7 +219,12 @@ void async_schedule_to_req(void) {
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
|
||||
}
|
||||
|
||||
void *async_loop(void *arg1) {
|
||||
void async_loop() {
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the async loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *tmp_uaf;
|
||||
int interesting_fd, i;
|
||||
@@ -241,7 +249,8 @@ void *async_loop(void *arg1) {
|
||||
}
|
||||
|
||||
// set a default request manager
|
||||
if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
if (!uwsgi.schedule_to_req)
|
||||
uwsgi.schedule_to_req = async_schedule_to_req;
|
||||
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
|
||||
@@ -251,36 +260,36 @@ void *async_loop(void *arg1) {
|
||||
else {
|
||||
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
|
||||
if (uwsgi.async_runqueue_cnt) {
|
||||
timeout = 0;
|
||||
timeout = 0;
|
||||
}
|
||||
if (min_timeout) {
|
||||
timeout = min_timeout->key - uwsgi_now();
|
||||
if (timeout <= 0) {
|
||||
async_expire_timeouts();
|
||||
timeout = 0;
|
||||
}
|
||||
if (min_timeout) {
|
||||
timeout = min_timeout->key - uwsgi_now();
|
||||
if (timeout <= 0) {
|
||||
async_expire_timeouts();
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
timeout = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
|
||||
|
||||
// timeout ???
|
||||
if (uwsgi.async_nevents == 0) {
|
||||
async_expire_timeouts();
|
||||
async_expire_timeouts();
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<uwsgi.async_nevents;i++) {
|
||||
for (i = 0; i < uwsgi.async_nevents; i++) {
|
||||
// manage events
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
|
||||
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
is_a_new_connection = 0;
|
||||
@@ -288,11 +297,11 @@ void *async_loop(void *arg1) {
|
||||
// new request coming in ?
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
while (uwsgi_sock) {
|
||||
|
||||
if (interesting_fd == uwsgi_sock->fd) {
|
||||
|
||||
is_a_new_connection = 1;
|
||||
is_a_new_connection = 1;
|
||||
|
||||
uwsgi.wsgi_req = find_first_available_wsgi_req();
|
||||
if (uwsgi.wsgi_req == NULL) {
|
||||
@@ -304,30 +313,23 @@ void *async_loop(void *arg1) {
|
||||
break;
|
||||
}
|
||||
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
|
||||
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
|
||||
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
|
||||
#endif
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
|
||||
#endif
|
||||
|
||||
// on linux we do not need to reset the socket to blocking state
|
||||
#ifndef __linux__
|
||||
/* re-set blocking socket */
|
||||
int arg = uwsgi_sock->arg;
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
/* re-set blocking socket */
|
||||
int arg = uwsgi_sock->arg;
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
|
||||
@@ -357,10 +359,7 @@ void *async_loop(void *arg1) {
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
// parsing complete
|
||||
if (!proto_parser_status) {
|
||||
// remove fd from event poll and fd proto table
|
||||
#ifndef UWSGI_EVENT_USE_PORT
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
#endif
|
||||
// remove fd from event poll and fd proto table
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
// put request in the runqueue
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
@@ -387,21 +386,19 @@ void *async_loop(void *arg1) {
|
||||
}
|
||||
|
||||
// remove all the fd monitors and timeout
|
||||
while(uwsgi.wsgi_req->waiting_fds) {
|
||||
#ifndef UWSGI_EVENT_USE_PORT
|
||||
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
|
||||
#endif
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
uwsgi.wsgi_req->async_ready_fd = 1;
|
||||
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
|
||||
@@ -426,20 +423,18 @@ void *async_loop(void *arg1) {
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
// remove all the monitored fds and timeout
|
||||
while(uwsgi.wsgi_req->waiting_fds) {
|
||||
#ifndef UWSGI_EVENT_USE_PORT
|
||||
event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
|
||||
#endif
|
||||
while (uwsgi.wsgi_req->waiting_fds) {
|
||||
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
|
||||
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
|
||||
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
|
||||
free(tmp_uaf);
|
||||
}
|
||||
uwsgi.wsgi_req->waiting_fds = NULL;
|
||||
if (uwsgi.wsgi_req->async_timeout) {
|
||||
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
free(uwsgi.wsgi_req->async_timeout);
|
||||
uwsgi.wsgi_req->async_timeout = NULL;
|
||||
}
|
||||
|
||||
// remove from the list
|
||||
@@ -453,7 +448,7 @@ void *async_loop(void *arg1) {
|
||||
|
||||
}
|
||||
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove this request from suspended list
|
||||
// remove this request from suspended list
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
@@ -464,6 +459,4 @@ void *async_loop(void *arg1) {
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
+43
-2
@@ -13,15 +13,56 @@ struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_buffer_fix(struct uwsgi_buffer *ub, size_t len) {
|
||||
if (ub->limit >0 && len > ub->limit) return -1;
|
||||
if (ub->len < len) {
|
||||
char *new_buf = realloc(ub->buf, len);
|
||||
if (!new_buf) {
|
||||
uwsgi_error("uwsgi_buffer_fix()");
|
||||
return -1;
|
||||
}
|
||||
ub->buf = new_buf;
|
||||
ub->len = len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_ensure(struct uwsgi_buffer *ub, size_t len) {
|
||||
size_t remains = ub->len - ub->pos;
|
||||
if (remains < len) {
|
||||
size_t new_len = ub->len + (len - remains);
|
||||
if (ub->limit >0 && new_len > ub->limit) {
|
||||
new_len = ub->limit;
|
||||
if (new_len == ub->len) return -1;
|
||||
}
|
||||
char *new_buf = realloc(ub->buf, new_len);
|
||||
if (!new_buf) {
|
||||
uwsgi_error("uwsgi_buffer_ensure()");
|
||||
return -1;
|
||||
}
|
||||
ub->buf = new_buf;
|
||||
ub->len = new_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
|
||||
|
||||
size_t remains = ub->len - ub->pos;
|
||||
|
||||
if (len > remains) {
|
||||
size_t chunk_size = UMAX(len, (size_t) uwsgi.page_size);
|
||||
if (ub->limit >0 && ub->len + chunk_size > ub->limit) {
|
||||
// retry with another minimal size
|
||||
if (len < (size_t) uwsgi.page_size) {
|
||||
chunk_size = len;
|
||||
}
|
||||
if (ub->len + chunk_size > ub->limit) return -1;
|
||||
}
|
||||
char *new_buf = realloc(ub->buf, ub->len + chunk_size);
|
||||
if (!new_buf) {
|
||||
uwsgi_error("realloc()");
|
||||
uwsgi_error("uwsgi_buffer_append()");
|
||||
return -1;
|
||||
}
|
||||
ub->buf = new_buf;
|
||||
@@ -54,7 +95,7 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("uwsgi_buffer_send()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
+23
-5
@@ -3,7 +3,6 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_init_cache() {
|
||||
int i;
|
||||
|
||||
if (!uwsgi.cache_blocksize)
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
@@ -64,6 +63,7 @@ void uwsgi_init_cache() {
|
||||
}
|
||||
else {
|
||||
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
int i;
|
||||
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
|
||||
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
|
||||
}
|
||||
@@ -85,8 +85,11 @@ void uwsgi_init_cache() {
|
||||
|
||||
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
|
||||
|
||||
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);
|
||||
uwsgi_log("*** Cache subsystem initialized: %lluMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n",
|
||||
(unsigned long long) ((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) {
|
||||
@@ -243,7 +246,6 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
struct uwsgi_cache_item *uci, *ucii;
|
||||
|
||||
int ret = -1;
|
||||
int slot;
|
||||
|
||||
if (!keylen || !vallen) return -1;
|
||||
|
||||
@@ -283,7 +285,7 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
uci->keysize = keylen;
|
||||
ret = 0;
|
||||
// now put the value in the 16bit hashtable
|
||||
slot = uci->djbhash % 0xffff;
|
||||
int slot = uci->djbhash % 0xffff;
|
||||
// reset values
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
@@ -441,3 +443,19 @@ int uwsgi_cache_server(char *socket, int threads) {
|
||||
return *fd;
|
||||
}
|
||||
|
||||
int uwsgi_cache_enabled() {
|
||||
if (uwsgi.cache_max_items > 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_cache_wlock() {
|
||||
uwsgi.lock_ops.wlock(uwsgi.cache_lock);
|
||||
}
|
||||
|
||||
void uwsgi_cache_rlock() {
|
||||
uwsgi.lock_ops.rlock(uwsgi.cache_lock);
|
||||
}
|
||||
|
||||
void uwsgi_cache_rwunlock() {
|
||||
uwsgi.lock_ops.rwunlock(uwsgi.cache_lock);
|
||||
}
|
||||
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
#include "../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
External uwsgi daemons
|
||||
|
||||
There are 3 kind of daemons (read: external applications) that can be managed
|
||||
by uWSGI.
|
||||
|
||||
1) dumb daemons (attached with --attach-daemon)
|
||||
they must not daemonize() and when they exit() the master is notified (via waitpid)
|
||||
and the process is respawned
|
||||
2) smart daemons with daemonization
|
||||
you specify a pidfile and a command
|
||||
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
|
||||
the daemon is respawned
|
||||
3) smart daemons without daemonization
|
||||
same as 2, but the daemonization and pidfile creation is managed by uWSGI
|
||||
|
||||
status:
|
||||
|
||||
0 -> never started
|
||||
1 -> just started
|
||||
2 -> started and monitored (only in pidfile based)
|
||||
|
||||
*/
|
||||
|
||||
void uwsgi_daemons_smart_check() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
// monitored instance
|
||||
if (ud->status == 2) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
else {
|
||||
ud->pidfile_checks++;
|
||||
if (ud->pidfile_checks >= (uint64_t) ud->freq) {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (checked_pid != ud->pid) {
|
||||
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
|
||||
ud->pid = checked_pid;
|
||||
}
|
||||
// all ok, pidfile and process found
|
||||
else {
|
||||
ud->status = 2;
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a dumb daemon dies and we do not wat to respawn it
|
||||
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
return -1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this function is called when a dumb daemon dies and we want to respawn it
|
||||
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_check_pidfile(char *filename) {
|
||||
struct stat st;
|
||||
pid_t ret = -1;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
goto end;
|
||||
}
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
goto end2;
|
||||
}
|
||||
char *pidstr = uwsgi_calloc(st.st_size+1);
|
||||
if (read(fd, pidstr, st.st_size) != st.st_size) {
|
||||
uwsgi_error("read()");
|
||||
goto end3;
|
||||
}
|
||||
pid_t pid = atoi(pidstr);
|
||||
if (pid <= 0) goto end3;
|
||||
if (!kill(pid, 0)) {
|
||||
ret = pid;
|
||||
}
|
||||
end3:
|
||||
free(pidstr);
|
||||
end2:
|
||||
close(fd);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uwsgi_daemons_spawn_all() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (!ud->registered) {
|
||||
if (ud->pidfile) {
|
||||
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
|
||||
if (checked_pid <= 0) {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
else {
|
||||
ud->pid = checked_pid;
|
||||
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_spawn_daemon(ud);
|
||||
}
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_detach_daemons() {
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0 && !ud->pidfile)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
ud = ud->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
ud->pidfile_checks = 0;
|
||||
if (ud->respawns == 0) {
|
||||
ud->born = uwsgi_now();
|
||||
}
|
||||
|
||||
ud->respawns++;
|
||||
ud->last_spawn = uwsgi_now();
|
||||
|
||||
}
|
||||
else {
|
||||
// close uwsgi sockets
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
if (ud->daemonize) {
|
||||
/* refork... */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
}
|
||||
if (pid != 0) {
|
||||
_exit(0);
|
||||
}
|
||||
uwsgi_write_pidfile(ud->pidfile);
|
||||
}
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0)) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!ud->pidfile) {
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep(throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re":"", ud->command);
|
||||
uwsgi_exec_command_with_args(ud->command);
|
||||
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);
|
||||
|
||||
// never here;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
|
||||
struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
|
||||
char *pidfile = NULL;
|
||||
int daemonize = 0;
|
||||
int freq = 10;
|
||||
|
||||
char *command = uwsgi_str(value);
|
||||
|
||||
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
|
||||
char *space = strchr(command, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
pidfile = command;
|
||||
// check for freq
|
||||
char *comma = strchr(pidfile, ',');
|
||||
if (comma) {
|
||||
*comma = 0;
|
||||
freq = atoi(comma+1);
|
||||
}
|
||||
command = space + 1;
|
||||
if (!strcmp(opt, "smart-attach-daemon2")) {
|
||||
daemonize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
uwsgi.daemons = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = uwsgi.daemons;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_ud) {
|
||||
old_ud = uwsgi_ud;
|
||||
uwsgi_ud = uwsgi_ud->next;
|
||||
}
|
||||
|
||||
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
old_ud->next = uwsgi_ud;
|
||||
}
|
||||
|
||||
uwsgi_ud->command = command;
|
||||
uwsgi_ud->pid = 0;
|
||||
uwsgi_ud->status = 0;
|
||||
uwsgi_ud->freq = freq;
|
||||
uwsgi_ud->registered = 0;
|
||||
uwsgi_ud->next = NULL;
|
||||
uwsgi_ud->respawns = 0;
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
}
|
||||
|
||||
+25
-1
@@ -1076,7 +1076,20 @@ void emperor_loop() {
|
||||
diedpid = 0;
|
||||
}
|
||||
if (diedpid < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
// it looks like it happens when OOM is triggered to Linux cgroup, but it could be a uWSGI bug :P
|
||||
// by the way, fallback to a clean situation...
|
||||
if (errno == ECHILD) {
|
||||
uwsgi_log("--- MUTINY DETECTED !!! IMPALING VASSALS... ---\n");
|
||||
ui_current = ui->ui_next;
|
||||
while (ui_current) {
|
||||
struct uwsgi_instance *rebel_vassal = ui_current;
|
||||
ui_current = ui_current->ui_next;
|
||||
emperor_del(rebel_vassal);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
ui_current = ui;
|
||||
while (ui_current->ui_next) {
|
||||
@@ -1129,6 +1142,13 @@ void emperor_send_stats(int fd) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi.stats_http) {
|
||||
if (uwsgi_send_http_stats(client_fd)) {
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_stats *us = uwsgi_stats_new(8192);
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION))
|
||||
@@ -1280,6 +1300,10 @@ void emperor_send_stats(int fd) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
ssize_t res = write(client_fd, us->base + pos, remains);
|
||||
if (res <= 0) {
|
||||
if (res < 0) {
|
||||
|
||||
+245
-30
@@ -28,7 +28,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
@@ -38,7 +38,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,53 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN|POLLOUT, NULL)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN|POLLOUT, NULL)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
@@ -63,16 +106,30 @@ int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
if (pe[id].portev_events = POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
port_event_t *pe = (port_event_t *) events;
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
|
||||
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *) eq)) {
|
||||
uwsgi_error("port_associate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
@@ -82,7 +139,7 @@ int event_queue_add_fd_write(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
@@ -96,7 +153,17 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
return (long) pe[id].portev_user;
|
||||
}
|
||||
|
||||
return (int) pe[id].portev_object;
|
||||
int fd = (int) pe[id].portev_object;
|
||||
int eq = (int) pe[id].portev_user;
|
||||
|
||||
if (pe[id].portev_events == POLLOUT) {
|
||||
event_queue_add_fd_write(eq, fd);
|
||||
}
|
||||
if (pe[id].portev_events == POLLIN) {
|
||||
event_queue_add_fd_read(eq, fd);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
@@ -104,7 +171,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
int ret;
|
||||
uint_t nget = 1;
|
||||
timespec_t ts;
|
||||
port_event_t *pe;
|
||||
|
||||
if (timeout >= 0) {
|
||||
ts.tv_sec = timeout;
|
||||
@@ -123,8 +189,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pe = (port_event_t *) events;
|
||||
|
||||
return nget;
|
||||
}
|
||||
|
||||
@@ -209,7 +273,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
@@ -225,7 +289,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
@@ -241,9 +305,75 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
struct epoll_event ee;
|
||||
|
||||
memset(&ee, 0, sizeof(struct epoll_event));
|
||||
ee.events = EPOLLIN;
|
||||
ee.data.fd = fd;
|
||||
|
||||
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
|
||||
uwsgi_error("epoll_ctl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
struct epoll_event ee;
|
||||
|
||||
memset(&ee, 0, sizeof(struct epoll_event));
|
||||
ee.events = EPOLLOUT;
|
||||
ee.data.fd = fd;
|
||||
|
||||
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
|
||||
uwsgi_error("epoll_ctl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
struct epoll_event ee;
|
||||
|
||||
memset(&ee, 0, sizeof(struct epoll_event));
|
||||
ee.events = EPOLLIN|EPOLLOUT;
|
||||
ee.data.fd = fd;
|
||||
|
||||
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
|
||||
uwsgi_error("epoll_ctl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
struct epoll_event ee;
|
||||
|
||||
memset(&ee, 0, sizeof(struct epoll_event));
|
||||
ee.events = EPOLLIN|EPOLLOUT;
|
||||
ee.data.fd = fd;
|
||||
|
||||
if (epoll_ctl(eq, EPOLL_CTL_MOD, fd, &ee)) {
|
||||
uwsgi_error("epoll_ctl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
@@ -258,7 +388,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
@@ -274,7 +404,7 @@ int event_queue_add_fd_write(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
@@ -295,6 +425,23 @@ int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct epoll_event *ee = (struct epoll_event *) events;
|
||||
if (ee[id].events & EPOLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct epoll_event *ee = (struct epoll_event *) events;
|
||||
if (ee[id].events & EPOLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
|
||||
int ret;
|
||||
@@ -357,13 +504,11 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_DISABLE, 0, 0, 0);
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
@@ -371,20 +516,18 @@ int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_DISABLE, 0, 0, 0);
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
@@ -392,9 +535,63 @@ int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_read(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_readwrite_to_write(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
|
||||
struct kevent kev;
|
||||
|
||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
|
||||
@@ -406,7 +603,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
@@ -419,7 +616,7 @@ int event_queue_add_fd_read(int eq, int fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
@@ -479,8 +676,23 @@ int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct kevent *ev = (struct kevent *) events;
|
||||
if ( ev[id].filter == EVFILT_READ ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct kevent *ev = (struct kevent *) events;
|
||||
if ( ev[id].filter == EVFILT_WRITE ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
|
||||
int ret;
|
||||
@@ -663,11 +875,11 @@ int event_queue_add_file_monitor(int eq, char *filename, int *id) {
|
||||
#endif
|
||||
|
||||
if (add_to_queue) {
|
||||
return event_queue_add_fd_read(eq, ifd);
|
||||
}
|
||||
else {
|
||||
return ifd;
|
||||
if (event_queue_add_fd_read(eq, ifd)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ifd;
|
||||
}
|
||||
|
||||
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
@@ -799,7 +1011,10 @@ int event_queue_add_timer(int eq, int *id, int sec) {
|
||||
}
|
||||
|
||||
*id = tfd;
|
||||
return event_queue_add_fd_read(eq, tfd);
|
||||
if (event_queue_add_fd_read(eq, tfd)) {
|
||||
return -1;
|
||||
}
|
||||
return tfd;
|
||||
}
|
||||
|
||||
struct uwsgi_timer *event_queue_ack_timer(int id) {
|
||||
|
||||
+11
@@ -16,6 +16,8 @@ void uwsgi_init_default() {
|
||||
uwsgi.cache_server_fd = -1;
|
||||
uwsgi.stats_fd = -1;
|
||||
|
||||
uwsgi.stats_pusher_default_freq = 3;
|
||||
|
||||
uwsgi.original_log_fd = -1;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
@@ -74,6 +76,15 @@ void uwsgi_init_default() {
|
||||
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
uwsgi.alarm_freq = 3;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
uwsgi.multicast_ttl = 1;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
|
||||
@@ -629,3 +629,12 @@ nextlock:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_user_lock(int lock_num) {
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
}
|
||||
|
||||
void uwsgi_user_unlock(int lock_num) {
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
}
|
||||
|
||||
|
||||
+55
-7
@@ -298,14 +298,33 @@ void uwsgi_setup_log_master(void) {
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.requested_logger;
|
||||
while(usl) {
|
||||
char *colon = strchr(usl->value, ':');
|
||||
char *id = NULL;
|
||||
char *name = usl->value;
|
||||
|
||||
char *space = strchr(name, ' ');
|
||||
if (space) {
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for(i=0;i<(space-name);i++) {
|
||||
if (!isalnum(name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_id) {
|
||||
id = uwsgi_concat2n(name, space-name, "", 0);
|
||||
name = space+1;
|
||||
}
|
||||
}
|
||||
|
||||
char *colon = strchr(name, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(usl->value);
|
||||
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
|
||||
if (!choosen_logger) {
|
||||
uwsgi_log("unable to find logger %s\n", usl->value);
|
||||
uwsgi_log("unable to find logger %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -313,6 +332,7 @@ void uwsgi_setup_log_master(void) {
|
||||
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
|
||||
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
|
||||
choosen_logger = copy_of_choosen_logger;
|
||||
choosen_logger->id = id;
|
||||
choosen_logger->next = NULL;
|
||||
|
||||
if (colon) {
|
||||
@@ -330,6 +350,15 @@ void uwsgi_setup_log_master(void) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
// set logger by its id
|
||||
struct uwsgi_regexp_list *url = uwsgi.log_route;
|
||||
while(url) {
|
||||
url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
|
||||
url = url->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi.original_log_fd = dup(1);
|
||||
create_logpipe();
|
||||
}
|
||||
@@ -529,9 +558,7 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *tsize = (char *) msecs;
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
char *msg4 = " via offload() ";
|
||||
|
||||
@@ -544,11 +571,9 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
via = msg1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -17) {
|
||||
@@ -598,6 +623,15 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
|
||||
// not enough space for logging the request, just log a (safe) minimal message
|
||||
if (rlen > 4096) {
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
|
||||
// argh, last resort, truncate it
|
||||
if (rlen > 4096) {
|
||||
rlen = 4096;
|
||||
}
|
||||
}
|
||||
|
||||
logvec[logvecpos].iov_base = logpkt;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
|
||||
@@ -763,6 +797,20 @@ struct uwsgi_logger *uwsgi_get_logger(char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
|
||||
while (ul) {
|
||||
if (!strcmp(ul->id, id)) {
|
||||
return ul;
|
||||
}
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
|
||||
ssize_t rlen = 0;
|
||||
|
||||
+92
-44
@@ -10,70 +10,118 @@ struct wsgi_request *simple_current_wsgi_req() {
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_register_loop(char *name, void *loop) {
|
||||
void uwsgi_register_loop(char *name, void (*func)(void)) {
|
||||
|
||||
if (uwsgi.loops_cnt >= MAX_LOOPS) {
|
||||
uwsgi_log("you can define %d loops at max\n", MAX_LOOPS);
|
||||
exit(1);
|
||||
struct uwsgi_loop *old_loop = NULL, *loop = uwsgi.loops;
|
||||
|
||||
while(loop) {
|
||||
// check if the loop engine is already registered
|
||||
if (!strcmp(name, loop->name)) return;
|
||||
old_loop = loop;
|
||||
loop = loop->next;
|
||||
}
|
||||
|
||||
uwsgi.loops[uwsgi.loops_cnt].name = name;
|
||||
uwsgi.loops[uwsgi.loops_cnt].loop = loop;
|
||||
uwsgi.loops_cnt++;
|
||||
loop = uwsgi_calloc(sizeof(struct uwsgi_loop));
|
||||
loop->name = name;
|
||||
loop->loop = func;
|
||||
|
||||
if (old_loop) {
|
||||
old_loop->next = loop;
|
||||
}
|
||||
else {
|
||||
uwsgi.loops = loop;
|
||||
}
|
||||
}
|
||||
|
||||
void *uwsgi_get_loop(char *name) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_loop *loop = uwsgi.loops;
|
||||
|
||||
for (i = 0; i < uwsgi.loops_cnt; i++) {
|
||||
if (!strcmp(name, uwsgi.loops[i].name)) {
|
||||
return uwsgi.loops[i].loop;
|
||||
while(loop) {
|
||||
if (!strcmp(name, loop->name)) {
|
||||
return loop->loop;
|
||||
}
|
||||
loop = loop->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *simple_loop(void *arg1) {
|
||||
/*
|
||||
|
||||
this is the default (simple) loop.
|
||||
|
||||
it will run simple_loop_run function for each spawned thread
|
||||
|
||||
simple_loop_run monitors sockets and signals descriptors
|
||||
and manages them.
|
||||
|
||||
*/
|
||||
|
||||
void simple_loop() {
|
||||
uwsgi_loop_cores_run(simple_loop_run);
|
||||
}
|
||||
|
||||
void uwsgi_loop_cores_run(void *(*func)(void *)) {
|
||||
int i;
|
||||
#ifdef UWSGI_THREADING
|
||||
for (i = 1; i < uwsgi.threads; i++) {
|
||||
long j = i;
|
||||
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
|
||||
}
|
||||
#endif
|
||||
long y = 0;
|
||||
func((void *) y);
|
||||
}
|
||||
|
||||
void uwsgi_setup_thread_req(long core_id, struct wsgi_request *wsgi_req) {
|
||||
int i;
|
||||
sigset_t smask;
|
||||
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
|
||||
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
|
||||
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
// run per-thread socket hook
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_sock->proto_thread_fixup) {
|
||||
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void simple_loop_run_int(int core_id) {
|
||||
long y = core_id;
|
||||
simple_loop_run((void *) y);
|
||||
}
|
||||
|
||||
void *simple_loop_run(void *arg1) {
|
||||
|
||||
long core_id = (long) arg1;
|
||||
|
||||
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
int i;
|
||||
sigset_t smask;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
|
||||
pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
|
||||
|
||||
if (core_id > 0) {
|
||||
// block all signals on new threads
|
||||
sigfillset(&smask);
|
||||
#ifdef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
// run per-thread socket hook
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_sock->proto_thread_fixup) {
|
||||
uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init_thread) {
|
||||
uwsgi.p[i]->init_thread(core_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_setup_thread_req(core_id, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+82
-45
@@ -265,6 +265,9 @@ int uwsgi_master_log(void) {
|
||||
|
||||
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
|
||||
if (rlen > 0) {
|
||||
#ifdef UWSGI_ALARM
|
||||
uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
|
||||
#endif
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
|
||||
while(url) {
|
||||
@@ -273,15 +276,49 @@ int uwsgi_master_log(void) {
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
#endif
|
||||
if (uwsgi.choosen_logger) {
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
while(ul) {
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
ul = ul->next;
|
||||
if (uwsgi.log_filter_rules) {
|
||||
int show = 0;
|
||||
url = uwsgi.log_filter_rules;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
show = 1;
|
||||
break;
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (!show) return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
url = uwsgi.log_route;
|
||||
int finish = 0;
|
||||
while(url) {
|
||||
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
|
||||
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
|
||||
if (ul_route) {
|
||||
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
url = url->next;
|
||||
}
|
||||
if (finish) return 0;
|
||||
#endif
|
||||
|
||||
int raw_log = 1;
|
||||
|
||||
struct uwsgi_logger *ul = uwsgi.choosen_logger;
|
||||
while(ul) {
|
||||
// check for named logger
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
raw_log = 0;
|
||||
next:
|
||||
ul = ul->next;
|
||||
}
|
||||
|
||||
if (raw_log) {
|
||||
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
@@ -481,13 +518,13 @@ clear:
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
void get_linux_tcp_info(int fd) {
|
||||
int get_linux_tcp_info(int fd) {
|
||||
socklen_t tis = sizeof(struct tcp_info);
|
||||
|
||||
if (!getsockopt(fd, IPPROTO_TCP, TCP_INFO, &uwsgi.shared->ti, &tis)) {
|
||||
// a check for older linux kernels
|
||||
if (!uwsgi.shared->ti.tcpi_sacked) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi.shared->load = uwsgi.shared->ti.tcpi_unacked;
|
||||
@@ -509,7 +546,11 @@ void get_linux_tcp_info(int fd) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, uwsgi.shared->ti.tcpi_unacked, uwsgi.shared->ti.tcpi_sacked);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
|
||||
return uwsgi.shared->ti.tcpi_unacked;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#include <linux/sockios.h>
|
||||
@@ -520,7 +561,7 @@ void get_linux_tcp_info(int fd) {
|
||||
|
||||
#ifdef SIOBKLGQ
|
||||
|
||||
void get_linux_unbit_SIOBKLGQ(int fd) {
|
||||
int get_linux_unbit_SIOBKLGQ(int fd) {
|
||||
|
||||
int queue = 0;
|
||||
if (ioctl(fd, SIOBKLGQ, &queue) >= 0) {
|
||||
@@ -530,8 +571,11 @@ void get_linux_unbit_SIOBKLGQ(int fd) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, queue, uwsgi.listen_queue);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -644,6 +688,11 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.threaded_logger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
// initialize the alarm subsystem
|
||||
uwsgi_alarms_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) {
|
||||
@@ -685,6 +734,15 @@ int master_loop(char **argv, char **environ) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.stats_fd);
|
||||
uwsgi_log("*** Stats server enabled on %s fd: %d ***\n", uwsgi.stats, uwsgi.stats_fd);
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.requested_stats_pushers) {
|
||||
if (!uwsgi_thread_new(uwsgi_stats_pusher_loop)) {
|
||||
uwsgi_log("!!! unable to spawn stats pusher thread !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
if (uwsgi.udp_socket) {
|
||||
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
|
||||
@@ -733,15 +791,7 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
|
||||
// spawn daemons
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (!ud->registered) {
|
||||
spawn_daemon(ud);
|
||||
ud->registered = 1;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
|
||||
uwsgi_daemons_spawn_all();
|
||||
|
||||
// first subscription
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
@@ -805,9 +855,11 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_daemons_smart_check();
|
||||
|
||||
if (uwsgi.to_outworld) {
|
||||
//uwsgi_log("%d/%d\n", uwsgi.lazy_respawned, uwsgi.numproc);
|
||||
if (uwsgi.lazy_respawned >= uwsgi.numproc || (uwsgi.cheaper && uwsgi.lazy_respawned == uwsgi.cheaper_count)) {
|
||||
if (uwsgi.lazy_respawned >= uwsgi.marked_workers || uwsgi.lazy_respawned >= uwsgi.numproc) {
|
||||
uwsgi.to_outworld = 0;
|
||||
uwsgi.master_mercy = 0;
|
||||
uwsgi.lazy_respawned = 0;
|
||||
@@ -838,8 +890,7 @@ int master_loop(char **argv, char **environ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((uwsgi.cheap || uwsgi.ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
|
||||
if ((uwsgi.cheap || uwsgi.ready_to_die >= uwsgi.marked_workers || uwsgi.ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
|
||||
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
|
||||
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
|
||||
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
@@ -849,7 +900,7 @@ int master_loop(char **argv, char **environ) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((uwsgi.cheap || uwsgi.ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
|
||||
if ((uwsgi.cheap || uwsgi.ready_to_reload >= uwsgi.marked_workers || uwsgi.ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
|
||||
uwsgi_reload(argv);
|
||||
// never here (unless in shared library mode)
|
||||
return -1;
|
||||
@@ -981,7 +1032,7 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
uwsgi_send_stats(uwsgi.stats_fd);
|
||||
uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats);
|
||||
goto health_cycle;
|
||||
}
|
||||
}
|
||||
@@ -1248,11 +1299,11 @@ health_cycle:
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->family == AF_INET) {
|
||||
get_linux_tcp_info(uwsgi_sock->fd);
|
||||
uwsgi_sock->queue = get_linux_tcp_info(uwsgi_sock->fd);
|
||||
}
|
||||
#ifdef SIOBKLGQ
|
||||
else if (uwsgi_sock->family == AF_UNIX) {
|
||||
get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
|
||||
uwsgi_sock->queue = get_linux_unbit_SIOBKLGQ(uwsgi_sock->fd);
|
||||
}
|
||||
#endif
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
@@ -1436,17 +1487,7 @@ health_cycle:
|
||||
continue;
|
||||
|
||||
/* reload the daemons */
|
||||
// TODO reload_daemons(diedpid);
|
||||
pid_found = 0;
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid) {
|
||||
spawn_daemon(ud);
|
||||
pid_found = 1;
|
||||
break;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
pid_found = uwsgi_daemon_check_pid_reload(diedpid);
|
||||
|
||||
if (pid_found)
|
||||
continue;
|
||||
@@ -1492,14 +1533,7 @@ health_cycle:
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid == diedpid) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
goto next;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
if (uwsgi_daemon_check_pid_death(diedpid)) goto next;
|
||||
|
||||
if (WIFEXITED(waitpid_status)) {
|
||||
uwsgi_log("subprocess %d exited with code %d\n", (int) diedpid, WEXITSTATUS(waitpid_status));
|
||||
@@ -1558,6 +1592,9 @@ next:
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].pid = 0;
|
||||
|
||||
+312
-200
@@ -492,6 +492,27 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
// we count the respawns before errors...
|
||||
uwsgi.workers[wid].respawn_count++;
|
||||
// ... same for update time
|
||||
uwsgi.workers[wid].last_spawn = uwsgi.current_time;
|
||||
// ... and memory/harakiri
|
||||
uwsgi.workers[wid].harakiri = 0;
|
||||
uwsgi.workers[wid].user_harakiri = 0;
|
||||
uwsgi.workers[wid].pending_harakiri = 0;
|
||||
uwsgi.workers[wid].rss_size = 0;
|
||||
uwsgi.workers[wid].vsz_size = 0;
|
||||
|
||||
// internal statuses should be reset too
|
||||
|
||||
uwsgi.workers[wid].cheaped = 0;
|
||||
uwsgi.workers[wid].busy = 0;
|
||||
uwsgi.workers[wid].suspended = 0;
|
||||
uwsgi.workers[wid].sig = 0;
|
||||
|
||||
// this is required for various checks
|
||||
uwsgi.workers[wid].delta_requests = 0;
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
@@ -505,25 +526,30 @@ int uwsgi_respawn_worker(int wid) {
|
||||
signal(SIGTSTP, worker_wakeup);
|
||||
uwsgi.mywid = wid;
|
||||
uwsgi.mypid = getpid();
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
// pid is updated by the master
|
||||
//uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
// OVERENGINEERING (just to be safe)
|
||||
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
|
||||
/*
|
||||
uwsgi.workers[uwsgi.mywid].harakiri = 0;
|
||||
uwsgi.workers[uwsgi.mywid].user_harakiri = 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].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].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
|
||||
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
|
||||
@@ -548,6 +574,9 @@ int uwsgi_respawn_worker(int wid) {
|
||||
uwsgi_error("fork()");
|
||||
}
|
||||
else {
|
||||
// the pid is set only in the master, as the worker should never use it
|
||||
uwsgi.workers[wid].pid = pid;
|
||||
|
||||
if (respawns > 0) {
|
||||
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
|
||||
}
|
||||
@@ -736,18 +765,9 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_send_stats(int fd) {
|
||||
struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
|
||||
int i, j;
|
||||
struct sockaddr_un client_src;
|
||||
struct uwsgi_app *ua;
|
||||
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;
|
||||
}
|
||||
int i;
|
||||
|
||||
struct uwsgi_stats *us = uwsgi_stats_new(8192);
|
||||
|
||||
@@ -761,6 +781,14 @@ void uwsgi_send_stats(int fd) {
|
||||
goto end;
|
||||
#endif
|
||||
|
||||
int signal_queue = 0;
|
||||
if (ioctl(uwsgi.shared->worker_signal_pipe[1], FIONREAD, &signal_queue)) {
|
||||
uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) uwsgi.shared->load))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) getpid()))
|
||||
@@ -771,248 +799,330 @@ void uwsgi_send_stats(int fd) {
|
||||
goto end;
|
||||
|
||||
char *cwd = uwsgi_get_cwd();
|
||||
if (uwsgi_stats_keyval_comma(us, "cwd", cwd))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) {
|
||||
free(cwd);
|
||||
goto end;
|
||||
}
|
||||
free(cwd);
|
||||
|
||||
if (uwsgi.daemons) {
|
||||
if (uwsgi_stats_key(us, "daemons"))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) (ud->respawns - 1)))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (ud->next) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_key(us, "locks"))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
while (uli) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong(us, uli->id, (unsigned long long) uli->pid))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uli->next) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_key(us, "sockets"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_key(us, "workers"))
|
||||
goto end0;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "static_offload_threads", (unsigned long long) uwsgi.workers[i + 1].static_offload_threads))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keyval_comma(us, "name", uwsgi_sock->name))
|
||||
goto end;
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
|
||||
goto end0;
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
|
||||
goto end0;
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
|
||||
goto end0;
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
|
||||
goto end0;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "idle"))
|
||||
goto end0;
|
||||
}
|
||||
}
|
||||
if (uwsgi_stats_keyval_comma(us, "proto", uwsgi_sock->proto_name ? uwsgi_sock->proto_name : "uwsgi"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time))
|
||||
goto end0;
|
||||
|
||||
// applications list
|
||||
if (uwsgi_stats_key(us, "apps"))
|
||||
goto end0;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end0;
|
||||
|
||||
|
||||
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
|
||||
ua = &uwsgi.workers[i + 1].apps[j];
|
||||
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", ua->requests))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
|
||||
goto end0;
|
||||
|
||||
if (ua->chdir) {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
|
||||
goto end0;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ""))
|
||||
goto end0;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
|
||||
if (j < uwsgi.workers[i + 1].apps_cnt - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
|
||||
// cores list
|
||||
if (uwsgi_stats_key(us, "cores"))
|
||||
goto end0;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end0;
|
||||
|
||||
for (j = 0; j < uwsgi.cores; j++) {
|
||||
struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j];
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end0;
|
||||
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
|
||||
if (j < uwsgi.cores-1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong(us, "can_offload", (unsigned long long) uwsgi_sock->can_offload))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
|
||||
if (i < uwsgi.numproc - 1) {
|
||||
goto end;
|
||||
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
if (uwsgi_sock) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end0;
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end0;
|
||||
goto end;
|
||||
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
ssize_t res = write(client_fd, us->base + pos, remains);
|
||||
if (res <= 0) {
|
||||
if (res < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
goto end0;
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_key(us, "workers"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals))
|
||||
goto end;
|
||||
|
||||
if (ioctl(uwsgi.workers[i+1].signal_pipe[1], FIONREAD, &signal_queue)) {
|
||||
uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
|
||||
goto end;
|
||||
/*
|
||||
if (uwsgi_stats_keylong_comma(us, "static_offload_threads", (unsigned long long) uwsgi.workers[i + 1].static_offload_threads))
|
||||
goto end;
|
||||
*/
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
|
||||
goto end;
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].busy) {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_stats_keyval_comma(us, "status", "idle"))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time))
|
||||
goto end;
|
||||
|
||||
// applications list
|
||||
if (uwsgi_stats_key(us, "apps"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
int j;
|
||||
|
||||
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
|
||||
struct uwsgi_app *ua = &uwsgi.workers[i + 1].apps[j];
|
||||
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", ua->requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
|
||||
goto end;
|
||||
|
||||
if (ua->chdir) {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_stats_keyval(us, "chdir", ""))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (j < uwsgi.workers[i + 1].apps_cnt - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
|
||||
// cores list
|
||||
if (uwsgi_stats_key(us, "cores"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
for (j = 0; j < uwsgi.cores; j++) {
|
||||
struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j];
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (j < uwsgi.cores-1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (i < uwsgi.numproc - 1) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
pos += res;
|
||||
remains -= res;
|
||||
}
|
||||
|
||||
end0:
|
||||
free(cwd);
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (uspool) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
if (uwsgi_stats_key(us, "spoolers"))
|
||||
goto end;
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
while (uspool) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "dir", uspool->dir))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uspool->pid))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "tasks", (unsigned long long) uspool->tasks))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "respawns", (unsigned long long) uspool->respawned))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong(us, "running", (unsigned long long) uspool->running))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
uspool = uspool->next;
|
||||
if (uspool) {
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
return us;
|
||||
end:
|
||||
free(us->base);
|
||||
free(us);
|
||||
close(client_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
@@ -1046,7 +1156,7 @@ void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
|
||||
void trigger_harakiri(int i) {
|
||||
int j;
|
||||
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d) ***\n", i, uwsgi.workers[i].pid);
|
||||
uwsgi_log("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri+1);
|
||||
if (uwsgi.harakiri_verbose) {
|
||||
#ifdef __linux__
|
||||
int proc_file;
|
||||
@@ -1098,7 +1208,9 @@ void trigger_harakiri(int i) {
|
||||
// allow SIGUSR2 to be delivered
|
||||
sleep(1);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
uwsgi.workers[i].harakiri_count++;
|
||||
if (!uwsgi.workers[i].pending_harakiri)
|
||||
uwsgi.workers[i].harakiri_count++;
|
||||
uwsgi.workers[i].pending_harakiri++;
|
||||
}
|
||||
// to avoid races
|
||||
|
||||
|
||||
+3
-2
@@ -49,10 +49,11 @@ void uwsgi_systemd_init(char *systemd_socket) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = strlen(systemd_socket);
|
||||
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
|
||||
memset(sd_sun, 0, sizeof(struct sockaddr_un));
|
||||
sd_sun->sun_family = AF_UNIX;
|
||||
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
|
||||
strncpy(sd_sun->sun_path, systemd_socket, UMIN(len, sizeof(sd_sun->sun_path)));
|
||||
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
|
||||
|
||||
msghdr = uwsgi_malloc(sizeof(struct msghdr));
|
||||
@@ -62,7 +63,7 @@ void uwsgi_systemd_init(char *systemd_socket) {
|
||||
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
|
||||
|
||||
msghdr->msg_name = sd_sun;
|
||||
msghdr->msg_namelen = sizeof(struct sockaddr_un);
|
||||
msghdr->msg_namelen = sizeof(struct sockaddr_un) - (sizeof(sd_sun->sun_path)-len);
|
||||
|
||||
uwsgi.notification_object = msghdr;
|
||||
|
||||
|
||||
+3
-3
@@ -7,7 +7,8 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
size_t s_len = 0;
|
||||
char *buf = uwsgi_elf_section(filename, "uwsgi", &s_len);
|
||||
if (buf) {
|
||||
char *p = strtok(buf, "\n");
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(buf, "\n", &ctx);
|
||||
while(p) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (equal) {
|
||||
@@ -16,7 +17,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
uwsgi_load_plugin(-1, equal+1, NULL);
|
||||
}
|
||||
}
|
||||
p = strtok(NULL, "\n");
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
@@ -78,7 +79,6 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
char *plugin_name = plugin;
|
||||
char *plugin_symbol_name_start = plugin;
|
||||
|
||||
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
|
||||
+31
-77
@@ -368,7 +368,11 @@ int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
@@ -1024,9 +1028,14 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for static files
|
||||
|
||||
// skip methods other than GET and HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) &&
|
||||
uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip extensions
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
@@ -1037,6 +1046,7 @@ next:
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
|
||||
udd = uwsgi.check_static;
|
||||
while(udd) {
|
||||
@@ -1162,7 +1172,11 @@ int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
@@ -1908,42 +1922,31 @@ int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, si
|
||||
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;
|
||||
|
||||
// if it is a HEAD request just skip transfer
|
||||
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ok, the file must be transferred from uWSGI
|
||||
if (wsgi_req->socket->can_offload) {
|
||||
if (!uwsgi_offload_request_do(wsgi_req, real_filename, st->st_size)) {
|
||||
wsgi_req->status = -30;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void *uwsgi_static_offload_thread(void *req) {
|
||||
|
||||
struct uwsgi_offload_request *uof_req = (struct uwsgi_offload_request *) req;
|
||||
|
||||
uwsgi_real_file_serve(&uof_req->wsgi_req, uof_req->real_filename, uof_req->real_filename_len, &uof_req->st);
|
||||
|
||||
// close the connection with the webserver
|
||||
if (!uof_req->wsgi_req.fd_closed || !uof_req->wsgi_req.body_as_file) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
uof_req->wsgi_req.socket->proto_close(&uof_req->wsgi_req);
|
||||
}
|
||||
|
||||
// free buffer
|
||||
free(uof_req->buffer);
|
||||
// free hvec
|
||||
free(uof_req->hvec);
|
||||
free(uof_req);
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads--;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
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, int is_a_file) {
|
||||
|
||||
@@ -1996,56 +1999,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
// Ok, the file must be served as static from uWSGI
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uint64_t offload_thread_count = uwsgi.workers[uwsgi.mywid].static_offload_threads;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (offload_thread_count > (uint64_t) uwsgi.static_offload_to_thread) {
|
||||
uwsgi_log_verbose("OVERLOAD !!! unable to offload static file serving\n");
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
|
||||
|
||||
// buffer
|
||||
uor->buffer = uwsgi_malloc(uwsgi.buffer_size); memcpy(uor->buffer, wsgi_req->buffer, uwsgi.buffer_size);
|
||||
// iovec
|
||||
uor->hvec = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size); memcpy(uor->hvec, wsgi_req->hvec, sizeof(struct iovec) * uwsgi.vec_size);
|
||||
|
||||
// wsgi_req
|
||||
memcpy(&uor->wsgi_req, wsgi_req, sizeof(struct wsgi_request));
|
||||
|
||||
uor->wsgi_req.buffer = uor->buffer;
|
||||
uor->wsgi_req.hvec = uor->hvec;
|
||||
|
||||
// stat
|
||||
memcpy(&uor->st, &st, sizeof(struct stat));
|
||||
|
||||
// filename
|
||||
memcpy(uor->real_filename, real_filename, real_filename_len);
|
||||
uor->real_filename_len = real_filename_len;
|
||||
uor->real_filename[uor->real_filename_len] = 0;
|
||||
|
||||
// avoid closing the connection
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads++;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (pthread_create(&uor->tid, &uwsgi.static_offload_thread_attr, uwsgi_static_offload_thread, (void *) uor)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
// bad condition, better to exit...
|
||||
exit(1);
|
||||
}
|
||||
wsgi_req->status = -30;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
+194
-4
@@ -1,9 +1,201 @@
|
||||
#ifdef UWSGI_SENDFILE
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
enqueue a file transfer to the offload thread
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_offload_request_do(struct wsgi_request *wsgi_req, char *filename, size_t len) {
|
||||
|
||||
struct stat st;
|
||||
|
||||
// avoid closing the connection
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
// fill offload request
|
||||
struct uwsgi_offload_request uor;
|
||||
uor.fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
if (uor.fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
goto error;
|
||||
}
|
||||
uor.s = wsgi_req->poll.fd;
|
||||
// make a fstat to get the file size
|
||||
if (!len) {
|
||||
if (fstat(uor.fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
goto error2;
|
||||
}
|
||||
len = st.st_size;
|
||||
}
|
||||
uor.pos = 0;
|
||||
uor.len = len;
|
||||
uor.written = 0;
|
||||
uor.buf = NULL;
|
||||
uor.prev = NULL;
|
||||
uor.next = NULL;
|
||||
|
||||
// put socket in non-blocking mode
|
||||
uwsgi_socket_nb(uor.s);
|
||||
|
||||
if (write(uwsgi.offload_thread->pipe[0], &uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
|
||||
goto error2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error2:
|
||||
close(uor.fd);
|
||||
error:
|
||||
wsgi_req->fd_closed = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_offload_close(struct uwsgi_offload_request *uor) {
|
||||
// close the socket and the file descriptor
|
||||
close(uor->s);
|
||||
close(uor->fd);
|
||||
// remove the structure from the linked list;
|
||||
struct uwsgi_offload_request *prev = uor->prev;
|
||||
struct uwsgi_offload_request *next = uor->next;
|
||||
|
||||
if (uor == uwsgi.offload_requests_head) {
|
||||
uwsgi.offload_requests_head = next;
|
||||
}
|
||||
|
||||
if (uor == uwsgi.offload_requests_tail) {
|
||||
uwsgi.offload_requests_tail = prev;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
if (uor->buf) {
|
||||
free(uor->buf);
|
||||
}
|
||||
|
||||
free(uor);
|
||||
}
|
||||
|
||||
static void uwsgi_offload_append(struct uwsgi_offload_request *uor) {
|
||||
|
||||
if (!uwsgi.offload_requests_head) {
|
||||
uwsgi.offload_requests_head = uor;
|
||||
}
|
||||
|
||||
if (uwsgi.offload_requests_tail) {
|
||||
uwsgi.offload_requests_tail->next = uor;
|
||||
uor->prev = uwsgi.offload_requests_tail;
|
||||
}
|
||||
|
||||
uwsgi.offload_requests_tail = uor;
|
||||
}
|
||||
|
||||
static struct uwsgi_offload_request *uwsgi_offload_get_by_socket(int s) {
|
||||
struct uwsgi_offload_request *uor = uwsgi.offload_requests_head;
|
||||
while(uor) {
|
||||
if (uor->s == s) {
|
||||
return uor;
|
||||
}
|
||||
uor = uor->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
int i;
|
||||
void *events = event_queue_alloc(uwsgi.static_offload_to_thread);
|
||||
|
||||
for(;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, -1, events, uwsgi.static_offload_to_thread);
|
||||
for (i=0;i<nevents;i++) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
if (interesting_fd == uwsgi.offload_thread->pipe[1]) {
|
||||
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
|
||||
ssize_t len = read(uwsgi.offload_thread->pipe[1], uor, sizeof(struct uwsgi_offload_request));
|
||||
if (len != sizeof(struct uwsgi_offload_request)) {
|
||||
uwsgi_error("read()");
|
||||
free(uor);
|
||||
continue;
|
||||
}
|
||||
// start monitoring socket for write
|
||||
if (event_queue_add_fd_write(ut->queue, uor->s)) {
|
||||
free(uor);
|
||||
continue;
|
||||
}
|
||||
uwsgi_offload_append(uor);
|
||||
continue;
|
||||
}
|
||||
// ok check for socket writability
|
||||
struct uwsgi_offload_request *uor = uwsgi_offload_get_by_socket(interesting_fd);
|
||||
if (!uor) continue;
|
||||
// sendfile() in chunks (128k is a good size...)
|
||||
#if defined(__linux__)
|
||||
ssize_t len = sendfile(uor->s, uor->fd, &uor->pos, 128*1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
if (uor->written >= uor->len) {
|
||||
uwsgi_offload_close(uor);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (len < 0) {
|
||||
if (errno == EAGAIN) continue;
|
||||
uwsgi_error("sendfile()");
|
||||
}
|
||||
#else
|
||||
if (!uor->buf) {
|
||||
uor->buf = uwsgi_malloc(32768);
|
||||
uor->to_write = 0;
|
||||
}
|
||||
if (uor->to_write == 0) {
|
||||
ssize_t len = read(uor->fd, uor->buf, 32768);
|
||||
if (len > 0) {
|
||||
uor->to_write = len;
|
||||
uor->buf_pos = 0;
|
||||
continue;
|
||||
}
|
||||
else if (len < 0) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
uwsgi_offload_close(uor);
|
||||
continue;
|
||||
}
|
||||
ssize_t len = write(uor->s, uor->buf + uor->buf_pos, uor->to_write);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
uor->to_write -= len;
|
||||
uor->buf_pos += len;
|
||||
if (uor->written >= uor->len) {
|
||||
uwsgi_offload_close(uor);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (len < 0) {
|
||||
if (errno == EAGAIN) continue;
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
#endif
|
||||
uwsgi_offload_close(uor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_offload_thread_start() {
|
||||
return uwsgi_thread_new(uwsgi_offload_loop);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_sendfile(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int fd = wsgi_req->sendfile_fd;
|
||||
@@ -173,5 +365,3 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+227
-216
@@ -4,13 +4,15 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_signal_handler(uint8_t sig) {
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
use = &uwsgi.shared->signal_table[sig];
|
||||
|
||||
if (!use->handler) return -1;
|
||||
|
||||
if (!uwsgi.p[use->modifier1]->signal_handler) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// check for COW
|
||||
if (uwsgi.master_process) {
|
||||
@@ -34,52 +36,52 @@ int uwsgi_signal_handler(uint8_t sig) {
|
||||
}
|
||||
}
|
||||
|
||||
// set harakiri here (if required and if i am a worker)
|
||||
|
||||
// set harakiri here (if required and if i am a worker)
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 1;
|
||||
uwsgi.workers[uwsgi.mywid].signum = sig;
|
||||
uwsgi.workers[uwsgi.mywid].sig = 1;
|
||||
uwsgi.workers[uwsgi.mywid].signum = sig;
|
||||
uwsgi.workers[uwsgi.mywid].signals++;
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.muleid > 0) {
|
||||
uwsgi.mules[uwsgi.muleid-1].sig = 1;
|
||||
uwsgi.mules[uwsgi.muleid-1].signum = sig;
|
||||
uwsgi.mules[uwsgi.muleid-1].signals++;
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
|
||||
uwsgi.mules[uwsgi.muleid - 1].signals++;
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
|
||||
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_SPOOLER
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
|
||||
}
|
||||
}
|
||||
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_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);
|
||||
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
if(uwsgi.workers[uwsgi.mywid].harakiri > 0) {
|
||||
set_harakiri(0);
|
||||
uwsgi.workers[uwsgi.mywid].sig = 0;
|
||||
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
|
||||
set_harakiri(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);
|
||||
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.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
|
||||
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
|
||||
set_spooler_harakiri(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@@ -97,7 +99,8 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
struct uwsgi_signal_entry *use = NULL;
|
||||
|
||||
if (strlen(receiver) > 63) return -1;
|
||||
if (strlen(receiver) > 63)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.signal_table_lock);
|
||||
|
||||
@@ -109,7 +112,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(use->receiver, receiver, strlen(receiver)+1);
|
||||
strncpy(use->receiver, receiver, strlen(receiver) + 1);
|
||||
use->handler = handler;
|
||||
use->modifier1 = modifier1;
|
||||
use->wid = uwsgi.mywid;
|
||||
@@ -129,7 +132,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
|
||||
int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
if (strlen(filename) > (0xff-1)) {
|
||||
if (strlen(filename) > (0xff - 1)) {
|
||||
uwsgi_log("uwsgi_add_file_monitor: invalid filename length\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -140,9 +143,9 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
|
||||
|
||||
// fill the fmon table, the master will use it to add items to the event queue
|
||||
memcpy(ushared->files_monitored[ushared->files_monitored_cnt].filename, filename, strlen(filename));
|
||||
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
|
||||
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
|
||||
ushared->files_monitored[ushared->files_monitored_cnt].sig = sig;
|
||||
|
||||
|
||||
ushared->files_monitored_cnt++;
|
||||
}
|
||||
else {
|
||||
@@ -157,31 +160,31 @@ 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_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
|
||||
|
||||
struct uwsgi_probe *uwsgi_up = *up, *old_up;
|
||||
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;
|
||||
}
|
||||
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 = uwsgi_malloc(sizeof(struct uwsgi_probe));
|
||||
old_up->next = uwsgi_up;
|
||||
}
|
||||
|
||||
uwsgi_up->name = name;
|
||||
uwsgi_up->func = func;
|
||||
uwsgi_up->next = NULL;
|
||||
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;
|
||||
return uwsgi_up;
|
||||
}
|
||||
|
||||
|
||||
@@ -189,10 +192,10 @@ 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) {
|
||||
if (ushared->probes_cnt < MAX_PROBES) {
|
||||
|
||||
struct uwsgi_probe *up = uwsgi.probes;
|
||||
while(up) {
|
||||
while (up) {
|
||||
if (!strcmp(up->name, kind)) {
|
||||
break;
|
||||
}
|
||||
@@ -201,15 +204,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
|
||||
|
||||
if (!up) {
|
||||
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
return -1;
|
||||
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;
|
||||
// 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;
|
||||
@@ -225,15 +228,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int 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;
|
||||
}
|
||||
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);
|
||||
uwsgi_unlock(uwsgi.probe_table_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -267,107 +270,109 @@ void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
|
||||
int i;
|
||||
|
||||
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while(uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
if (!uc) {
|
||||
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uwsgi.crons = uc;
|
||||
}
|
||||
else {
|
||||
old_uc = uc;
|
||||
while (uc->next) {
|
||||
uc = uc->next;
|
||||
old_uc = uc;
|
||||
}
|
||||
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
|
||||
uc = old_uc->next;
|
||||
}
|
||||
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
memset(uc, 0, sizeof(struct uwsgi_cron));
|
||||
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value+i;
|
||||
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
|
||||
uwsgi_log("invalid cron syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
uc->command = value + i;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.cron_table_lock);
|
||||
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
if (ushared->cron_cnt < MAX_CRONS) {
|
||||
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
ushared->cron[ushared->cron_cnt].sig = sig;
|
||||
ushared->cron[ushared->cron_cnt].minute = minute;
|
||||
ushared->cron[ushared->cron_cnt].hour = hour;
|
||||
ushared->cron[ushared->cron_cnt].day = day;
|
||||
ushared->cron[ushared->cron_cnt].month = month;
|
||||
ushared->cron[ushared->cron_cnt].week = week;
|
||||
ushared->cron_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
uwsgi_unlock(uwsgi.cron_table_lock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
|
||||
|
||||
if (!uwsgi.master_process) return -1;
|
||||
if (!uwsgi.master_process)
|
||||
return -1;
|
||||
|
||||
uwsgi_lock(uwsgi.rb_timer_table_lock);
|
||||
uwsgi_lock(uwsgi.rb_timer_table_lock);
|
||||
|
||||
if (ushared->rb_timers_cnt < 64) {
|
||||
if (ushared->rb_timers_cnt < 64) {
|
||||
|
||||
// fill the timer table, the master will use it to add items to the event queue
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
|
||||
ushared->rb_timers_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max 64 rb_timers !!!\n");
|
||||
uwsgi_unlock(uwsgi.rb_timer_table_lock);
|
||||
return -1;
|
||||
}
|
||||
// fill the timer table, the master will use it to add items to the event queue
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
|
||||
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
|
||||
ushared->rb_timers_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("you can register max 64 rb_timers !!!\n");
|
||||
uwsgi_unlock(uwsgi.rb_timer_table_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_unlock(uwsgi.rb_timer_table_lock);
|
||||
uwsgi_unlock(uwsgi.rb_timer_table_lock);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
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]);
|
||||
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_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[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_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()");
|
||||
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,9 +384,10 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
|
||||
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 (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (write(fd, (char *) &uh, 4) != 4) {
|
||||
uwsgi_error("uwsgi_remote_signal_send()");
|
||||
@@ -403,16 +409,16 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -430,7 +436,7 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
// send to all workers
|
||||
else if (!strcmp(use->receiver, "workers")) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
@@ -438,13 +444,13 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
}
|
||||
// route to specific worker
|
||||
else if (!strncmp(use->receiver, "worker", 6)) {
|
||||
i = atoi(use->receiver+6);
|
||||
i = atoi(use->receiver + 6);
|
||||
if (i > uwsgi.numproc) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
|
||||
}
|
||||
}
|
||||
// route to subscribed
|
||||
else if (!strcmp(use->receiver, "subscribed")) {
|
||||
@@ -454,54 +460,54 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
else if (!strcmp(use->receiver, "spooler")) {
|
||||
if (ushared->worker_signal_pipe[0] != -1) {
|
||||
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to the spooler\n", 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++) {
|
||||
for (i = 0; i < uwsgi.mules_cnt; i++) {
|
||||
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);
|
||||
}
|
||||
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp(use->receiver, "mule", 4)) {
|
||||
i = atoi(use->receiver+4);
|
||||
i = atoi(use->receiver + 4);
|
||||
if (i > uwsgi.mules_cnt) {
|
||||
uwsgi_log("invalid signal target: %s\n", use->receiver);
|
||||
}
|
||||
else if (i == 0) {
|
||||
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
|
||||
uwsgi_log("could not deliver signal %d to a mule\n", sig);
|
||||
}
|
||||
uwsgi_log("could not deliver signal %d to a mule\n", sig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,51 +518,56 @@ void uwsgi_route_signal(uint8_t sig) {
|
||||
|
||||
}
|
||||
|
||||
uint8_t uwsgi_signal_wait(int signum) {
|
||||
int 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];
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
int received_signal = -1;
|
||||
int ret;
|
||||
struct pollfd pfd[2];
|
||||
|
||||
if (signum > -1) {
|
||||
wait_for_specific_signal = 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
ret = poll(pfd, 2, -1);
|
||||
if (ret > 0) {
|
||||
if (pfd[0].revents == POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void) uwsgi_signal_handler(uwsgi_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (signum != uwsgi_signal)
|
||||
goto cycle;
|
||||
}
|
||||
received_signal = uwsgi_signal;
|
||||
}
|
||||
}
|
||||
if (pfd[1].revents == POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) != 1) {
|
||||
uwsgi_error("read()");
|
||||
}
|
||||
else {
|
||||
(void) uwsgi_signal_handler(uwsgi_signal);
|
||||
if (wait_for_specific_signal) {
|
||||
if (signum != uwsgi_signal)
|
||||
goto cycle;
|
||||
}
|
||||
}
|
||||
received_signal = uwsgi_signal;
|
||||
}
|
||||
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;
|
||||
return received_signal;
|
||||
}
|
||||
|
||||
void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
@@ -565,27 +576,27 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
|
||||
ssize_t ret = read(fd, &uwsgi_signal, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret > 0) {
|
||||
}
|
||||
else if (ret > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
|
||||
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
|
||||
}
|
||||
}
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
destroy:
|
||||
// better to kill the whole worker...
|
||||
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
|
||||
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
|
||||
end_me(0);
|
||||
|
||||
}
|
||||
|
||||
@@ -249,11 +249,14 @@ static uint64_t get_uwsgi_snmp_value(uint64_t val, uint8_t * oid_t) {
|
||||
static uint64_t get_uwsgi_custom_snmp_value(uint64_t val, uint8_t * oid_t) {
|
||||
|
||||
val--;
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
if (uwsgi.shared->snmp_value[val].type) {
|
||||
*oid_t = uwsgi.shared->snmp_value[val].type;
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
return uwsgi.shared->snmp_value[val].val;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
*oid_t = SNMP_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+59
-13
@@ -174,6 +174,7 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
struct sockaddr_in uws_addr;
|
||||
char *udp_port;
|
||||
int bcast = 1;
|
||||
int reuse = 1;
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
struct ip_mreq mc;
|
||||
@@ -231,6 +232,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
if (multicast) {
|
||||
// if multicast is enabled remember to bind to INADDR_ANY
|
||||
@@ -265,6 +270,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_TTL, &uwsgi.multicast_ttl, sizeof(uwsgi.multicast_ttl))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -325,7 +334,11 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
|
||||
memcpy(uws_addr.sun_path, socket_name, UMIN(strlen(socket_name), 102));
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
@@ -363,7 +376,11 @@ int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
|
||||
|
||||
socket_name[strlen(socket_name)] = ':';
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);
|
||||
#else
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
@@ -542,7 +559,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
@@ -550,7 +567,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#ifdef IP_FREEBIND
|
||||
if (uwsgi.freebind) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("IP_FREEBIND setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
}
|
||||
@@ -560,7 +577,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (uwsgi.reuse_port) {
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("SO_REUSEPORT setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
#else
|
||||
@@ -568,11 +585,21 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (uwsgi.so_send_timeout) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = uwsgi.so_send_timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
|
||||
uwsgi_error("SO_SNDTIMEO setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
#ifdef __linux__
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("TCP_DEFER_ACCEPT setsockopt()");
|
||||
}
|
||||
// OSX has no SO_ACCEPTFILTER !!!
|
||||
#elif defined(__freebsd__)
|
||||
@@ -580,7 +607,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
strcpy(afa.af_name, "dataready");
|
||||
afa.af_arg[0] = 0;
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("SO_ACCEPTFILTER setsockopt()");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -588,19 +615,27 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
|
||||
if (uwsgi.so_keepalive) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_KEEPALIVE, &uwsgi.so_keepalive, sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_error("SO_KEEPALIVE setsockopt()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
if (errno == EADDRINUSE) {
|
||||
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
|
||||
uwsgi_log("probably another instance of uWSGI is running on the same address (%s).\n", socket_name);
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn");
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%i).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
@@ -650,13 +685,16 @@ void uwsgi_socket_b(int fd) {
|
||||
|
||||
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout, int async) {
|
||||
|
||||
int arg, ret;
|
||||
int ret;
|
||||
int soopt = 0;
|
||||
socklen_t solen = sizeof(int);
|
||||
int cnt;
|
||||
/* set non-blocking socket */
|
||||
|
||||
arg = fcntl(fdpoll->fd, F_GETFL, NULL);
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
// hmm, nothing to do, as we are already non-blocking
|
||||
#else
|
||||
int arg = fcntl(fdpoll->fd, F_GETFL, NULL);
|
||||
if (arg < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return -1;
|
||||
@@ -666,6 +704,7 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
|
||||
uwsgi_error("fcntl()");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = connect(fdpoll->fd, addr, addr_size);
|
||||
|
||||
@@ -673,17 +712,20 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
|
||||
if (ret < 0 && errno != EINPROGRESS) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
// hmm, nothing to do, as we are already non-blocking
|
||||
#else
|
||||
/* re-set blocking socket */
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(fdpoll->fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (async)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (ret < 0) {
|
||||
/* check what happened */
|
||||
@@ -1742,9 +1784,11 @@ setup_proto:
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.static_offload_to_thread)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
if (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi")) {
|
||||
if (uwsgi.protocol && (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi"))) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
|
||||
}
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
@@ -1770,6 +1814,8 @@ setup_proto:
|
||||
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
|
||||
uwsgi_sock->proto_sendfile = NULL;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.static_offload_to_thread)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
|
||||
+8
-6
@@ -355,12 +355,6 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
}
|
||||
wakeup = tmp_wakeup;
|
||||
|
||||
// need to recycle ?
|
||||
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
|
||||
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
|
||||
end_me(0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +545,14 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
|
||||
uwsgi_protected_close(spool_fd);
|
||||
uspool->running = 0;
|
||||
|
||||
|
||||
// need to recycle ?
|
||||
if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
|
||||
uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
|
||||
end_me(0);
|
||||
}
|
||||
|
||||
|
||||
if (chdir(dir)) {
|
||||
uwsgi_error("chdir()");
|
||||
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
|
||||
|
||||
+226
-9
@@ -3,15 +3,21 @@
|
||||
utility functions for fast generating json output for the stats subsystem
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_stats *uwsgi_stats_new(size_t chunk_size) {
|
||||
struct uwsgi_stats *us = uwsgi_malloc(sizeof(struct uwsgi_stats));
|
||||
us->base = uwsgi_malloc(chunk_size);
|
||||
us->base[0] = '{';
|
||||
us->base[1] = '\n';
|
||||
us->pos = 2;
|
||||
us->pos = 1;
|
||||
us->chunk = chunk_size;
|
||||
us->size = chunk_size;
|
||||
us->tabs = 1;
|
||||
us->minified = uwsgi.stats_minified;
|
||||
if (!us->minified) {
|
||||
us->base[1] = '\n';
|
||||
us->pos++;
|
||||
}
|
||||
return us;
|
||||
}
|
||||
|
||||
@@ -36,6 +42,7 @@ int uwsgi_stats_symbol_nl(struct uwsgi_stats *us, char sym) {
|
||||
if (uwsgi_stats_symbol(us, sym)) {
|
||||
return -1;
|
||||
}
|
||||
if (us->minified) return 0;
|
||||
return uwsgi_stats_symbol(us, '\n');
|
||||
}
|
||||
|
||||
@@ -45,6 +52,7 @@ int uwsgi_stats_comma(struct uwsgi_stats *us) {
|
||||
}
|
||||
|
||||
int uwsgi_stats_apply_tabs(struct uwsgi_stats *us) {
|
||||
if (us->minified) return 0;
|
||||
size_t i;
|
||||
for(i=0;i<us->tabs;i++) {
|
||||
if (uwsgi_stats_symbol(us, '\t')) return -1;
|
||||
@@ -55,14 +63,16 @@ int uwsgi_stats_apply_tabs(struct uwsgi_stats *us) {
|
||||
|
||||
int uwsgi_stats_object_open(struct uwsgi_stats *us) {
|
||||
if (uwsgi_stats_apply_tabs(us)) return -1;
|
||||
us->tabs++;
|
||||
if (!us->minified) us->tabs++;
|
||||
return uwsgi_stats_symbol_nl(us, '{');
|
||||
}
|
||||
|
||||
int uwsgi_stats_object_close(struct uwsgi_stats *us) {
|
||||
if (uwsgi_stats_symbol(us, '\n')) return -1;
|
||||
us->tabs--;
|
||||
if (uwsgi_stats_apply_tabs(us)) return -1;
|
||||
if (!us->minified) {
|
||||
if (uwsgi_stats_symbol(us, '\n')) return -1;
|
||||
us->tabs--;
|
||||
if (uwsgi_stats_apply_tabs(us)) return -1;
|
||||
}
|
||||
return uwsgi_stats_symbol(us, '}');
|
||||
}
|
||||
|
||||
@@ -72,9 +82,11 @@ int uwsgi_stats_list_open(struct uwsgi_stats *us) {
|
||||
}
|
||||
|
||||
int uwsgi_stats_list_close(struct uwsgi_stats *us) {
|
||||
if (uwsgi_stats_symbol(us, '\n')) return -1;
|
||||
us->tabs--;
|
||||
if (uwsgi_stats_apply_tabs(us)) return -1;
|
||||
if (!us->minified) {
|
||||
if (uwsgi_stats_symbol(us, '\n')) return -1;
|
||||
us->tabs--;
|
||||
if (uwsgi_stats_apply_tabs(us)) return -1;
|
||||
}
|
||||
return uwsgi_stats_symbol(us, ']');
|
||||
}
|
||||
|
||||
@@ -264,3 +276,208 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
|
||||
if (ret) return -1;
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
void uwsgi_send_stats(int fd, struct uwsgi_stats * (*func)(void)) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (uwsgi.stats_http) {
|
||||
if (uwsgi_send_http_stats(client_fd)) {
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_stats *us = func();
|
||||
if (!us) goto end;
|
||||
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while (remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
ssize_t res = write(client_fd, us->base + pos, remains);
|
||||
if (res <= 0) {
|
||||
if (res < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
goto end0;
|
||||
}
|
||||
pos += res;
|
||||
remains -= res;
|
||||
}
|
||||
|
||||
end0:
|
||||
free(us->base);
|
||||
free(us);
|
||||
|
||||
end:
|
||||
close(client_fd);
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
|
||||
struct uwsgi_stats_pusher *usp = uwsgi.stats_pushers;
|
||||
while(usp) {
|
||||
if (!strcmp(usp->name, name)) {
|
||||
return usp;
|
||||
}
|
||||
usp = usp->next;
|
||||
}
|
||||
return usp;
|
||||
}
|
||||
|
||||
void uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
|
||||
struct uwsgi_stats_pusher_instance *old_uspi = NULL, *uspi = uwsgi.stats_pusher_instances;
|
||||
while(uspi) {
|
||||
old_uspi = uspi;
|
||||
uspi = uspi->next;
|
||||
}
|
||||
|
||||
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
|
||||
uspi->pusher = pusher;
|
||||
uspi->arg = arg;
|
||||
if (old_uspi) {
|
||||
old_uspi->next = uspi;
|
||||
}
|
||||
else {
|
||||
uwsgi.stats_pusher_instances = uspi;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(1);
|
||||
for(;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
|
||||
if (nevents > 0) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, 0);
|
||||
char buf[4096];
|
||||
ssize_t len = read(interesting_fd, buf, 4096);
|
||||
if (len <= 0) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] goodbye...\n");
|
||||
return;
|
||||
}
|
||||
uwsgi_log("[uwsgi-stats-pusher] message received from master: %.*s\n", (int) len, buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
struct uwsgi_stats_pusher_instance *uspi = uwsgi.stats_pusher_instances;
|
||||
struct uwsgi_stats *us = NULL;
|
||||
while(uspi) {
|
||||
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
|
||||
if ( (uspi->last_run + delta) <= now) {
|
||||
if (!us) {
|
||||
us = uwsgi_master_generate_stats();
|
||||
if (!us) goto next;
|
||||
}
|
||||
uspi->pusher->func(uspi, us->base, us->pos);
|
||||
uspi->last_run = now;
|
||||
}
|
||||
next:
|
||||
uspi = uspi->next;
|
||||
}
|
||||
|
||||
if (us) {
|
||||
free(us->base);
|
||||
free(us);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_stats_pusher_setup() {
|
||||
struct uwsgi_string_list *usl = uwsgi.requested_stats_pushers;
|
||||
while(usl) {
|
||||
char *ssp = uwsgi_str(usl->value);
|
||||
struct uwsgi_stats_pusher *pusher = NULL;
|
||||
char *colon = strchr(ssp, ':');
|
||||
if (colon) {
|
||||
*colon = 0;
|
||||
}
|
||||
pusher = uwsgi_stats_pusher_get(ssp);
|
||||
if (!pusher) {
|
||||
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
|
||||
exit(1);
|
||||
}
|
||||
char *arg = NULL;
|
||||
if (colon) {
|
||||
arg = colon+1;
|
||||
*colon = ':';
|
||||
}
|
||||
uwsgi_stats_pusher_add(pusher, arg);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_register_stats_pusher(char *name, void(*func) (struct uwsgi_stats_pusher_instance *, char *, size_t)) {
|
||||
|
||||
struct uwsgi_stats_pusher *pusher = uwsgi.stats_pushers, *old_pusher = NULL;
|
||||
|
||||
while(pusher) {
|
||||
old_pusher = pusher;
|
||||
pusher = pusher->next;
|
||||
}
|
||||
|
||||
pusher = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher));
|
||||
pusher->name = name;
|
||||
pusher->func = func;
|
||||
|
||||
if (old_pusher) {
|
||||
old_pusher->next = pusher;
|
||||
}
|
||||
else {
|
||||
uwsgi.stats_pushers = pusher;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher_file_conf {
|
||||
char *path;
|
||||
char *freq;
|
||||
char *separator;
|
||||
};
|
||||
|
||||
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
|
||||
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
|
||||
if (!uspi->configured) {
|
||||
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
|
||||
if (uspi->arg) {
|
||||
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=',
|
||||
"path", &uspic->path,
|
||||
"separator", &uspic->separator,
|
||||
"freq", &uspic->freq, NULL)) {
|
||||
free(uspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!uspic->path) uspic->path = "uwsgi.stats";
|
||||
if (!uspic->separator) uspic->separator = "\n\n";
|
||||
if (uspic->freq) uspi->freq = atoi(uspic->freq);
|
||||
uspi->configured = 1;
|
||||
uspi->data = uspic;
|
||||
}
|
||||
|
||||
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uspic->path);
|
||||
return;
|
||||
}
|
||||
ssize_t rlen = write(fd, json, json_len);
|
||||
if (rlen != (ssize_t) json_len) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
rlen = write(fd, uspic->separator, strlen(uspic->separator));
|
||||
if (rlen != (ssize_t ) strlen(uspic->separator)) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
+204
-186
@@ -4,10 +4,9 @@
|
||||
|
||||
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 subscription slot is as an hashed item in a dictionary
|
||||
|
||||
each slot has another circular linked list containing the nodes names
|
||||
each slot has a 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
|
||||
|
||||
@@ -21,7 +20,7 @@
|
||||
|
||||
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 *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
|
||||
@@ -42,43 +41,32 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
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[hash_key] = current_slot;
|
||||
}
|
||||
|
||||
if (current_slot->next) {
|
||||
current_slot->next->prev = slot_prev;
|
||||
}
|
||||
|
||||
slot_prev->prev = current_slot;
|
||||
slot_prev->next = current_slot->next;
|
||||
|
||||
current_slot->next = slot_prev;
|
||||
current_slot->prev = slot_parent;
|
||||
|
||||
}
|
||||
}
|
||||
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[hash_key] = current_slot;
|
||||
}
|
||||
|
||||
if (current_slot->next) {
|
||||
current_slot->next->prev = slot_prev;
|
||||
}
|
||||
|
||||
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[hash_key]) break;
|
||||
@@ -87,80 +75,172 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, int regexp) {
|
||||
// least reference count
|
||||
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
|
||||
// if node is NULL we are in the second step (in lrc mode we do not use the first step)
|
||||
if (node) return NULL;
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
|
||||
|
||||
if (current_slot) {
|
||||
// slot found, move up in the list increasing hits
|
||||
current_slot->hits++;
|
||||
time_t now = uwsgi_now();
|
||||
struct uwsgi_subscribe_node *node = current_slot->nodes;
|
||||
while(node) {
|
||||
// is the node alive ?
|
||||
if (now - node->last_check > uwsgi.subscription_tolerance) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) uwsgi.mypid, (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
}
|
||||
// is the node must be removed ?
|
||||
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;
|
||||
}
|
||||
|
||||
if (node->death_mark == 0 && node->wrr > 0) {
|
||||
node->wrr--;
|
||||
node->reference++;
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
// no wrr > 0 node found, reset them
|
||||
node = current_slot->nodes;
|
||||
uint64_t min_weight = 0;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
if (min_weight == 0 || node->weight < min_weight) min_weight = node->weight;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
// now set wrr
|
||||
node = current_slot->nodes;
|
||||
struct uwsgi_subscribe_node *choosen_node = NULL;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
node->wrr = node->weight/min_weight;
|
||||
struct uwsgi_subscribe_node *choosen_node = NULL;
|
||||
node = current_slot->nodes;
|
||||
uint64_t min_rc = 0;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
if (min_rc == 0 || node->reference < min_rc) {
|
||||
min_rc = node->reference;
|
||||
choosen_node = node;
|
||||
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests))
|
||||
break;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
if (choosen_node) {
|
||||
choosen_node->wrr--;
|
||||
choosen_node->reference++;
|
||||
}
|
||||
return choosen_node;
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (choosen_node) {
|
||||
choosen_node->reference++;
|
||||
}
|
||||
|
||||
return choosen_node;
|
||||
}
|
||||
|
||||
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) {
|
||||
// weighted least reference count
|
||||
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
|
||||
// if node is NULL we are in the second step (in wlrc mode we do not use the first step)
|
||||
if (node) return NULL;
|
||||
|
||||
struct uwsgi_subscribe_node *choosen_node = NULL;
|
||||
node = current_slot->nodes;
|
||||
double min_rc = 0;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
// node->weight is always >= 1, we can safely use it as divider
|
||||
double ref = (double) node->reference / (double) node->weight;
|
||||
double next_node_ref = 0;
|
||||
if (node->next)
|
||||
next_node_ref = (double) node->next->reference / (double) node->next->weight;
|
||||
|
||||
if (min_rc == 0 || ref < min_rc) {
|
||||
min_rc = ref;
|
||||
choosen_node = node;
|
||||
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->requests <= node->requests))
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (choosen_node) {
|
||||
choosen_node->reference++;
|
||||
}
|
||||
|
||||
return choosen_node;
|
||||
}
|
||||
|
||||
// weighted round robin algo
|
||||
static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wrr(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) {
|
||||
// if node is NULL we are in the second step
|
||||
if (node) {
|
||||
if (node->death_mark == 0 && node->wrr > 0) {
|
||||
node->wrr--;
|
||||
node->reference++;
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// no wrr > 0 node found, reset them
|
||||
node = current_slot->nodes;
|
||||
uint64_t min_weight = 0;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
if (min_weight == 0 || node->weight < min_weight) min_weight = node->weight;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
// now set wrr
|
||||
node = current_slot->nodes;
|
||||
struct uwsgi_subscribe_node *choosen_node = NULL;
|
||||
while(node) {
|
||||
if (!node->death_mark) {
|
||||
node->wrr = node->weight/min_weight;
|
||||
choosen_node = node;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
if (choosen_node) {
|
||||
choosen_node->wrr--;
|
||||
choosen_node->reference++;
|
||||
}
|
||||
return choosen_node;
|
||||
}
|
||||
|
||||
void uwsgi_subscription_set_algo(char *algo) {
|
||||
|
||||
if (!algo) goto wrr;
|
||||
|
||||
if (!strcmp(algo,"wrr")) {
|
||||
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(algo,"lrc")) {
|
||||
uwsgi.subscription_algo = uwsgi_subscription_algo_lrc;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(algo,"wlrc")) {
|
||||
uwsgi.subscription_algo = uwsgi_subscription_algo_wlrc;
|
||||
return;
|
||||
}
|
||||
|
||||
wrr:
|
||||
uwsgi.subscription_algo = uwsgi_subscription_algo_wrr;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen, regexp);
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen);
|
||||
if (!current_slot) return NULL;
|
||||
|
||||
// slot found, move up in the list increasing hits
|
||||
current_slot->hits++;
|
||||
time_t now = uwsgi_now();
|
||||
struct uwsgi_subscribe_node *node = current_slot->nodes;
|
||||
while(node) {
|
||||
// is the node alive ?
|
||||
if (now - node->last_check > uwsgi.subscription_tolerance) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[uwsgi-subscription for pid %d] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) uwsgi.mypid, (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
|
||||
node->failcnt++;
|
||||
node->death_mark = 1;
|
||||
}
|
||||
// do i need to remove the node ?
|
||||
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;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_node *choosen_node = uwsgi.subscription_algo(current_slot, node);
|
||||
if (choosen_node) return choosen_node;
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return uwsgi.subscription_algo(current_slot, node);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (keylen > 0xff) return NULL;
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen);
|
||||
if (current_slot) {
|
||||
struct uwsgi_subscribe_node *node = current_slot->nodes;
|
||||
while(node) {
|
||||
@@ -210,14 +290,6 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
|
||||
// first check if i am the only node
|
||||
if ((!prev_slot && !next_slot) || next_slot == node_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
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
@@ -241,14 +313,6 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
|
||||
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
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
EVP_PKEY_free(node_slot->sign_public_key);
|
||||
@@ -263,9 +327,9 @@ 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_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) {
|
||||
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen, 0), *old_slot = NULL, *a_slot;
|
||||
struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot;
|
||||
struct uwsgi_subscribe_node *node, *old_node = NULL;
|
||||
|
||||
if (usr->address_len > 0xff || usr->address_len == 0) return NULL;
|
||||
@@ -386,17 +450,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
current_slot->key[usr->keylen] = 0;
|
||||
current_slot->hits = 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;
|
||||
@@ -418,63 +471,20 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
|
||||
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[hash_key];
|
||||
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[hash_key];
|
||||
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;
|
||||
}
|
||||
a_slot = slot[hash_key];
|
||||
while(a_slot) {
|
||||
old_slot = a_slot;
|
||||
a_slot = a_slot->next;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
a_slot = slot[hash_key];
|
||||
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
|
||||
if (old_slot) {
|
||||
old_slot->next = current_slot;
|
||||
}
|
||||
#endif
|
||||
|
||||
current_slot->prev = old_slot;
|
||||
current_slot->next = NULL;
|
||||
|
||||
|
||||
if (!slot[hash_key] || current_slot->prev == NULL) {
|
||||
slot[hash_key] = current_slot;
|
||||
@@ -488,6 +498,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
|
||||
}
|
||||
|
||||
|
||||
// TODO rewrite it using uwsgi buffers
|
||||
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
|
||||
|
||||
char value_cores[sizeof(UMAX64_STR)+1];
|
||||
@@ -721,3 +732,10 @@ int uwsgi_no_subscriptions(struct uwsgi_subscribe_slot **slot) {
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
|
||||
if (!uwsgi.subscription_algo) {
|
||||
uwsgi_subscription_set_algo(NULL);
|
||||
}
|
||||
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
|
||||
}
|
||||
|
||||
+281
-139
@@ -840,6 +840,26 @@ void uwsgi_linux_ksm_map(void) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
long uwsgi_num_from_file(char *filename) {
|
||||
char buf[16];
|
||||
ssize_t len;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
return -1L;
|
||||
}
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
if (len == 0) {
|
||||
uwsgi_log("read error %s\n", filename);
|
||||
close(fd);
|
||||
return -1L;
|
||||
}
|
||||
close(fd);
|
||||
return strtol(buf, (char **)NULL, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
// setup for a new request
|
||||
void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
@@ -848,9 +868,7 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id, struct uwsgi_so
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
|
||||
wsgi_req->async_id = async_id;
|
||||
#ifdef UWSGI_SENDFILE
|
||||
wsgi_req->sendfile_fd = -1;
|
||||
#endif
|
||||
|
||||
wsgi_req->hvec = uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].hvec;
|
||||
wsgi_req->buffer = uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].buffer;
|
||||
@@ -1474,7 +1492,7 @@ int uwsgi_get_app_id(char *app_name, int app_name_len, int modifier1) {
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (uwsgi_apps[i].touch_reload) {
|
||||
if (uwsgi_apps[i].touch_reload[0]) {
|
||||
if (!stat(uwsgi_apps[i].touch_reload, &st)) {
|
||||
if (st.st_mtime != uwsgi_apps[i].touch_reload_mtime) {
|
||||
// serve the new request and reload
|
||||
@@ -2154,6 +2172,8 @@ void *uwsgi_malloc(size_t size) {
|
||||
char *ptr = malloc(size);
|
||||
if (ptr == NULL) {
|
||||
uwsgi_error("malloc()");
|
||||
uwsgi_log("!!! tried memory allocation of %llu bytes !!!\n", (unsigned long long) size);
|
||||
uwsgi_backtrace(uwsgi.backtrace_depth);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -2655,105 +2675,6 @@ char *uwsgi_get_last_char(char *what, char c) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
char *argv[64];
|
||||
char *a;
|
||||
int cnt = 1;
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
if (ud->respawns == 0) {
|
||||
ud->born = uwsgi_now();
|
||||
}
|
||||
|
||||
ud->respawns++;
|
||||
ud->last_spawn = uwsgi_now();
|
||||
|
||||
}
|
||||
else {
|
||||
// close uwsgi sockets
|
||||
uwsgi_close_all_sockets();
|
||||
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0)) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
uwsgi_error("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#endif
|
||||
|
||||
// free the old area
|
||||
if (ud->tmp_command)
|
||||
free(ud->tmp_command);
|
||||
|
||||
ud->tmp_command = uwsgi_str(ud->command);
|
||||
|
||||
a = strtok(ud->tmp_command, " ");
|
||||
if (a) {
|
||||
argv[0] = a;
|
||||
while (a != NULL) {
|
||||
a = strtok(NULL, " ");
|
||||
if (a) {
|
||||
argv[cnt] = a;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
argv[0] = ud->tmp_command;
|
||||
}
|
||||
|
||||
argv[cnt] = NULL;
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" (%s) for %d seconds\n", ud->command, argv[0], throttle);
|
||||
sleep(throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] spawning \"%s\" (%s)\n", ud->command, argv[0]);
|
||||
if (execvp(argv[0], argv)) {
|
||||
uwsgi_error("execvp()");
|
||||
}
|
||||
uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\" (%s)\n", ud->command, argv[0]);
|
||||
|
||||
// never here;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *uwsgi_num2str(int num) {
|
||||
|
||||
char *str = uwsgi_malloc(11);
|
||||
@@ -3062,39 +2983,6 @@ char *uwsgi_netstring(char *buf, size_t len, char **netstring, size_t * netstrin
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_daemon *uwsgi_daemon_new(struct uwsgi_daemon **ud, char *command) {
|
||||
|
||||
struct uwsgi_daemon *uwsgi_ud = *ud, *old_ud;
|
||||
|
||||
if (!uwsgi_ud) {
|
||||
*ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
uwsgi_ud = *ud;
|
||||
}
|
||||
else {
|
||||
while (uwsgi_ud) {
|
||||
old_ud = uwsgi_ud;
|
||||
uwsgi_ud = uwsgi_ud->next;
|
||||
}
|
||||
|
||||
uwsgi_ud = uwsgi_malloc(sizeof(struct uwsgi_daemon));
|
||||
old_ud->next = uwsgi_ud;
|
||||
}
|
||||
|
||||
uwsgi_ud->command = command;
|
||||
uwsgi_ud->tmp_command = NULL;
|
||||
uwsgi_ud->pid = 0;
|
||||
uwsgi_ud->status = 0;
|
||||
uwsgi_ud->registered = 0;
|
||||
uwsgi_ud->next = NULL;
|
||||
uwsgi_ud->respawns = 0;
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
|
||||
uwsgi.daemons_cnt++;
|
||||
|
||||
return uwsgi_ud;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_dyn_dict *uwsgi_dyn_dict_new(struct uwsgi_dyn_dict **dd, char *key, int keylen, char *val, int vallen) {
|
||||
|
||||
struct uwsgi_dyn_dict *uwsgi_dd = *dd, *old_dd;
|
||||
@@ -3192,7 +3080,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list *uwsgi_regexp_new_list(struct uwsgi_regexp_list **list, char *value) {
|
||||
struct uwsgi_regexp_list *uwsgi_regexp_custom_new_list(struct uwsgi_regexp_list **list, char *value, char *custom) {
|
||||
|
||||
struct uwsgi_regexp_list *url = *list, *old_url;
|
||||
|
||||
@@ -3215,10 +3103,14 @@ struct uwsgi_regexp_list *uwsgi_regexp_new_list(struct uwsgi_regexp_list **list,
|
||||
}
|
||||
url->next = NULL;
|
||||
url->custom = 0;
|
||||
url->custom_ptr = NULL;
|
||||
url->custom_str = custom;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
char *uwsgi_string_get_list(struct uwsgi_string_list **list, int pos, size_t * len) {
|
||||
@@ -3895,6 +3787,7 @@ void uwsgi_apply_config_pass(char symbol, char *(*hook) (char *)) {
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
int has_symbol = 0;
|
||||
int depth = 0;
|
||||
char *magic_key = NULL;
|
||||
char *magic_val = NULL;
|
||||
if (uwsgi.exported_opts[i]->value && !uwsgi.exported_opts[i]->configured) {
|
||||
@@ -3904,10 +3797,20 @@ void uwsgi_apply_config_pass(char symbol, char *(*hook) (char *)) {
|
||||
}
|
||||
else if (uwsgi.exported_opts[i]->value[j] == '(' && has_symbol == 1) {
|
||||
has_symbol = 2;
|
||||
depth = 0;
|
||||
magic_key = uwsgi.exported_opts[i]->value + j + 1;
|
||||
}
|
||||
else if (has_symbol > 1) {
|
||||
if (uwsgi.exported_opts[i]->value[j] == ')') {
|
||||
if (uwsgi.exported_opts[i]->value[j] == '(') {
|
||||
has_symbol++;
|
||||
depth++;
|
||||
}
|
||||
else if (uwsgi.exported_opts[i]->value[j] == ')') {
|
||||
if (depth > 0) {
|
||||
has_symbol++;
|
||||
depth--;
|
||||
continue;
|
||||
}
|
||||
if (has_symbol <= 2) {
|
||||
magic_key = NULL;
|
||||
has_symbol = 0;
|
||||
@@ -3977,7 +3880,7 @@ void uwsgi_set_processname(char *name) {
|
||||
// end with \0
|
||||
memset(uwsgi.orig_argv[0] + amount + 1 + (uwsgi.max_procname - (amount)), '\0', 1);
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
if (uwsgi.procname_prefix) {
|
||||
if (!uwsgi.procname_append) {
|
||||
setproctitle("-%s%s", uwsgi.procname_prefix, name);
|
||||
@@ -4385,7 +4288,7 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0) {
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
|
||||
uwsgi_log("unable to assign ssl certificate %s\n", crt);
|
||||
exit(1);
|
||||
}
|
||||
@@ -4846,3 +4749,242 @@ clear:
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *uwsgi_thread_run(void *arg) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) arg;
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
ut->queue = event_queue_init();
|
||||
event_queue_add_fd_read(ut->queue, ut->pipe[1]);
|
||||
|
||||
ut->func(ut);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_thread *uwsgi_thread_new(void (*func)(struct uwsgi_thread *)) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_malloc(sizeof(struct uwsgi_thread));
|
||||
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ut->pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ut->pipe)) {
|
||||
#endif
|
||||
free(ut);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ut->pipe[0]);
|
||||
uwsgi_socket_nb(ut->pipe[1]);
|
||||
|
||||
ut->func = func;
|
||||
|
||||
pthread_attr_init(&ut->tattr);
|
||||
pthread_attr_setdetachstate(&ut->tattr, PTHREAD_CREATE_DETACHED);
|
||||
// 512K should be enough...
|
||||
pthread_attr_setstacksize(&ut->tattr, 512 * 1024);
|
||||
|
||||
if (pthread_create(&ut->tid, &ut->tattr, uwsgi_thread_run, ut)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ut;
|
||||
error:
|
||||
close(ut->pipe[0]);
|
||||
close(ut->pipe[1]);
|
||||
free(ut);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// evaluate a math expression
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
double uwsgi_matheval(char *expr) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("matheval expr = %s\n", expr);
|
||||
#endif
|
||||
double ret = 0.0;
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) return ret;
|
||||
ret = evaluator_evaluate(e, 0, NULL, NULL);
|
||||
evaluator_destroy(e);
|
||||
return ret;
|
||||
}
|
||||
char *uwsgi_matheval_str(char *expr) {
|
||||
double ret = uwsgi_matheval(expr);
|
||||
return uwsgi_num2str((int) ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_kvlist_parse(char *src, size_t len, char list_separator, char kv_separator, ...) {
|
||||
size_t i;
|
||||
va_list ap;
|
||||
struct uwsgi_string_list *itemlist = NULL;
|
||||
|
||||
char *buf = uwsgi_calloc(len + 1);
|
||||
|
||||
// ok let's start splitting the string
|
||||
int escaped = 0;
|
||||
char *base = buf;
|
||||
char *ptr = buf;
|
||||
for(i=0;i<len;i++) {
|
||||
if (src[i] == list_separator && !escaped) {
|
||||
*ptr++= 0;
|
||||
uwsgi_string_new_list(&itemlist, base);
|
||||
base = ptr;
|
||||
}
|
||||
else if (src[i] == '\\' && !escaped) {
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr > base) {
|
||||
uwsgi_string_new_list(&itemlist, base);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = itemlist;
|
||||
while(usl) {
|
||||
len = strlen(usl->value);
|
||||
char *item_buf = uwsgi_calloc(len + 1);
|
||||
base = item_buf;
|
||||
ptr = item_buf;
|
||||
escaped = 0;
|
||||
for(i=0;i<len;i++) {
|
||||
if (usl->value[i] == kv_separator && !escaped) {
|
||||
*ptr++= 0;
|
||||
va_start(ap, kv_separator);
|
||||
for(;;) {
|
||||
char *p = va_arg(ap, char *);
|
||||
if (!p) break;
|
||||
char **pp = va_arg(ap, char **);
|
||||
if (!pp) break;
|
||||
if (!strcmp(p, base)) {
|
||||
*pp = uwsgi_str(usl->value+i+1);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
base = ptr;
|
||||
break;
|
||||
}
|
||||
else if (usl->value[i] == '\\' && !escaped) {
|
||||
escaped = 1;
|
||||
}
|
||||
else if (escaped) {
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= usl->value[i];
|
||||
}
|
||||
}
|
||||
free(item_buf);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_send_http_stats(int fd) {
|
||||
|
||||
char buf[4096];
|
||||
|
||||
int ret = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) return -1;
|
||||
|
||||
if (read(fd, buf, 4096) <= 0) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (!ub) return -1;
|
||||
|
||||
if (uwsgi_buffer_append(ub, "HTTP/1.0 200 OK\r\n", 17)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "Connection: close\r\n", 19)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "Content-Type: application/json\r\n", 32)) goto error;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto error;
|
||||
|
||||
if (uwsgi_buffer_send(ub, fd)) goto error;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_simple_set_status(struct wsgi_request *wsgi_req, int status) {
|
||||
wsgi_req->status = status;
|
||||
}
|
||||
|
||||
void uwsgi_simple_inc_headers(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
|
||||
void uwsgi_simple_response_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
}
|
||||
|
||||
void uwsgi_simple_response_write_header(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, buf, len);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_simple_request_read(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
if (wsgi_req->post_cl == 0) return 0;
|
||||
if ((size_t)wsgi_req->post_pos >= wsgi_req->post_cl) return 0;
|
||||
size_t remains = wsgi_req->post_cl - wsgi_req->post_pos;
|
||||
remains = UMIN(len, remains);
|
||||
|
||||
int fd = -1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// data in memory ?
|
||||
if (fd == -1) {
|
||||
memcpy(buf, wsgi_req->post_buffering_buf + wsgi_req->post_buffering_read, remains);
|
||||
wsgi_req->post_buffering_read+=remains;
|
||||
wsgi_req->post_pos += remains;
|
||||
return remains;
|
||||
}
|
||||
|
||||
if (uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
|
||||
uwsgi_log("error waiting for request body");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t rlen = read(fd, buf, remains);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("error reading request body:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->post_pos += rlen;
|
||||
return rlen;
|
||||
}
|
||||
|
||||
int uwsgi_plugin_modifier1(char *plugin) {
|
||||
int ret = -1;
|
||||
char *symbol_name = uwsgi_concat2(plugin, "_plugin");
|
||||
struct uwsgi_plugin *up = dlsym(RTLD_DEFAULT, symbol_name);
|
||||
if (!up) goto end;
|
||||
ret = up->modifier1;
|
||||
end:
|
||||
free(symbol_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+166
-67
@@ -95,6 +95,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"disable-write-exception", no_argument, 0, "disable exception generation on write()/writev()", uwsgi_opt_true, &uwsgi.disable_write_exception, 0},
|
||||
|
||||
{"inherit", required_argument, 0, "use the specified file as config template", uwsgi_opt_load, NULL, 0},
|
||||
{"include", required_argument, 0, "include the specified file as immediate configuration", uwsgi_opt_load, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"daemonize", required_argument, 'd', "daemonize uWSGI", uwsgi_opt_set_str, &uwsgi.daemonize, 0},
|
||||
{"daemonize2", required_argument, 0, "daemonize uWSGI after app loading", uwsgi_opt_set_str, &uwsgi.daemonize2, 0},
|
||||
{"stop", required_argument, 0, "stop an instance", uwsgi_opt_pidfile_signal, (void *) SIGINT, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -263,6 +264,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"command-mode", no_argument, 0, "force command mode", uwsgi_opt_true, &uwsgi.command_mode, UWSGI_OPT_IMMEDIATE},
|
||||
{"no-defer-accept", no_argument, 0, "disable deferred-accept on sockets", uwsgi_opt_true, &uwsgi.no_defer_accept, 0},
|
||||
{"so-keepalive", no_argument, 0, "enable TCP KEEPALIVEs", uwsgi_opt_true, &uwsgi.so_keepalive, 0},
|
||||
{"so-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-send-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"so-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"socket-write-timeout", no_argument, 0, "set SO_SNDTIMEO", uwsgi_opt_set_int, &uwsgi.so_send_timeout, 0},
|
||||
{"limit-as", required_argument, 0, "limit processes address space/vsz", uwsgi_opt_set_megabytes, &uwsgi.rl.rlim_max, 0},
|
||||
{"limit-nproc", required_argument, 0, "limit the number of spawnable processes", uwsgi_opt_set_int, &uwsgi.rl_nproc.rlim_max, 0},
|
||||
{"reload-on-as", required_argument, 0, "reload if address space is higher than specified megabytes", uwsgi_opt_set_megabytes, &uwsgi.reload_on_as, UWSGI_OPT_MEMORY},
|
||||
@@ -300,8 +305,15 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
{"stats-server", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
{"stats-http", no_argument, 0, "prefix stats server json output with http headers", uwsgi_opt_true, &uwsgi.stats_http, UWSGI_OPT_MASTER},
|
||||
{"stats-minified", no_argument, 0, "minify statistics json output", uwsgi_opt_true, &uwsgi.stats_minified, UWSGI_OPT_MASTER},
|
||||
{"stats-min", no_argument, 0, "minify statistics json output", uwsgi_opt_true, &uwsgi.stats_minified, UWSGI_OPT_MASTER},
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER},
|
||||
{"stats-pusher-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-pushers-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_MULTICAST
|
||||
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"cluster", required_argument, 0, "join specified uWSGI cluster", uwsgi_opt_set_str, &uwsgi.cluster, UWSGI_OPT_MASTER},
|
||||
{"cluster-nodes", required_argument, 0, "get nodes list from the specified cluster", uwsgi_opt_true, &uwsgi.cluster_nodes, UWSGI_OPT_MASTER | UWSGI_OPT_CLUSTER},
|
||||
{"cluster-reload", required_argument, 0, "send a reload message to the cluster", uwsgi_opt_cluster_reload, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -311,6 +323,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
{"subscription-algo", required_argument, 0, "set load balancing algorithm for the subscription system", uwsgi_opt_ssa, NULL, 0},
|
||||
{"subscription-dotsplit", no_argument, 0, "try to fallback to the next part (dot based) in subscription key", uwsgi_opt_true, &uwsgi.subscription_dotsplit, 0},
|
||||
{"subscribe-to", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
|
||||
{"st", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
|
||||
{"subscribe", required_argument, 0, "subscribe to the specified subscription server", uwsgi_opt_add_string_list, &uwsgi.subscriptions, UWSGI_OPT_MASTER},
|
||||
@@ -351,6 +365,15 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
#ifdef UWSGI_PCRE
|
||||
{"log-drain", required_argument, 0, "drain (do not show) log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_drain_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-filter", required_argument, 0, "show only log lines matching the specified regexp", uwsgi_opt_add_regexp_list, &uwsgi.log_filter_rules, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
#endif
|
||||
#ifdef UWSGI_ALARM
|
||||
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
|
||||
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
@@ -473,6 +496,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"loops-list", no_argument, 0, "list enabled loop engines", uwsgi_opt_true, &uwsgi.loop_list, 0},
|
||||
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"plugins", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugin", required_argument, 0, "load uWSGI plugins", uwsgi_opt_load_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"plugins-dir", required_argument, 0, "add a directory to uWSGI plugin search path", uwsgi_opt_add_string_list, &uwsgi.plugins_dir, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -645,14 +670,22 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
|
||||
char *tmp = NULL;
|
||||
|
||||
magic_table['o'] = filename;
|
||||
if (filename[0] == '/') {
|
||||
magic_table['p'] = filename;
|
||||
char *fullname = uwsgi_expand_path(filename, strlen(filename), NULL);
|
||||
if (!fullname) {
|
||||
fullname = filename;
|
||||
}
|
||||
// free unused memory
|
||||
else {
|
||||
magic_table['p'] = uwsgi_concat3(uwsgi.cwd, "/", filename);
|
||||
char *minimal_name = uwsgi_malloc(strlen(fullname) + 1);
|
||||
memcpy(minimal_name, fullname, strlen(fullname));
|
||||
minimal_name[strlen(fullname)] = 0;
|
||||
free(fullname);
|
||||
fullname = minimal_name;
|
||||
}
|
||||
magic_table['s'] = uwsgi_get_last_char(magic_table['p'], '/') + 1;
|
||||
|
||||
magic_table['o'] = filename;
|
||||
magic_table['p'] = fullname;
|
||||
magic_table['s'] = uwsgi_get_last_char(fullname, '/') + 1;
|
||||
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
|
||||
if (magic_table['d'][strlen(magic_table['d']) - 1] == '/') {
|
||||
tmp = magic_table['d'] + (strlen(magic_table['d']) - 1);
|
||||
@@ -818,6 +851,16 @@ void kill_them_all(int signum) {
|
||||
|
||||
if (uwsgi.to_hell == 1)
|
||||
return;
|
||||
|
||||
// count the number of active workers
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
uwsgi.marked_workers = active_workers;
|
||||
|
||||
uwsgi.to_hell = 1;
|
||||
|
||||
if (uwsgi.reload_mercy > 0) {
|
||||
@@ -854,12 +897,7 @@ void kill_them_all(int signum) {
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
ud = ud->next;
|
||||
}
|
||||
uwsgi_detach_daemons();
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid > 0)
|
||||
@@ -880,6 +918,15 @@ void grace_them_all(int signum) {
|
||||
if (uwsgi.to_heaven == 1 || uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0)
|
||||
return;
|
||||
|
||||
// count the number of active workers
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
uwsgi.marked_workers = active_workers;
|
||||
|
||||
if (!uwsgi.lazy)
|
||||
uwsgi.to_heaven = 1;
|
||||
else
|
||||
@@ -903,12 +950,7 @@ void grace_them_all(int signum) {
|
||||
uwsgi_log("killing the emperor with pid %d\n", uwsgi.emperor_pid);
|
||||
}
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
ud = ud->next;
|
||||
}
|
||||
uwsgi_detach_daemons();
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid > 0)
|
||||
@@ -989,17 +1031,21 @@ void reap_them_all(int signum) {
|
||||
if (uwsgi.to_outworld == 1 || uwsgi.lazy_respawned > 0)
|
||||
return;
|
||||
|
||||
// count the number of active workers
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
uwsgi.marked_workers = active_workers;
|
||||
|
||||
if (!uwsgi.lazy)
|
||||
uwsgi.to_heaven = 1;
|
||||
else
|
||||
uwsgi.to_outworld = 1;
|
||||
|
||||
struct uwsgi_daemon *ud = uwsgi.daemons;
|
||||
while (ud) {
|
||||
if (ud->pid > 0)
|
||||
kill(-ud->pid, SIGKILL);
|
||||
ud = ud->next;
|
||||
}
|
||||
uwsgi_detach_daemons();
|
||||
|
||||
for (i = 0; i < ushared->gateways_cnt; i++) {
|
||||
if (ushared->gateways[i].pid > 0)
|
||||
@@ -1501,10 +1547,11 @@ static void router_list(void) {
|
||||
#endif
|
||||
|
||||
static void loop_list(void) {
|
||||
int i;
|
||||
struct uwsgi_loop *loop = uwsgi.loops;
|
||||
uwsgi_log("\n*** uWSGI loaded loop engines ***\n");
|
||||
for(i=0;i<uwsgi.loops_cnt;i++) {
|
||||
uwsgi_log("%s\n", uwsgi.loops[i].name);
|
||||
while(loop) {
|
||||
uwsgi_log("%s\n", loop->name);
|
||||
loop = loop->next;
|
||||
}
|
||||
uwsgi_log("--- end of loop engines list ---\n\n");
|
||||
}
|
||||
@@ -1529,6 +1576,18 @@ static void clocks_list(void) {
|
||||
uwsgi_log("--- end of clocks list ---\n\n");
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
static void alarms_list(void) {
|
||||
struct uwsgi_alarm *alarms = uwsgi.alarms;
|
||||
uwsgi_log("\n*** uWSGI loaded alarms ***\n");
|
||||
while(alarms) {
|
||||
uwsgi_log("%s\n", alarms->name);
|
||||
alarms = alarms->next;
|
||||
}
|
||||
uwsgi_log("--- end of alarms list ---\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static time_t uwsgi_unix_seconds() {
|
||||
return time(NULL);
|
||||
}
|
||||
@@ -1706,6 +1765,11 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// last pass: REFERENCEs
|
||||
uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
// optional pass: MATH
|
||||
uwsgi_apply_config_pass('=', uwsgi_matheval_str);
|
||||
#endif
|
||||
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
@@ -1743,6 +1807,17 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_imperial_monitor("dir", uwsgi_imperial_monitor_directory_init, uwsgi_imperial_monitor_directory);
|
||||
uwsgi_register_imperial_monitor("glob", uwsgi_imperial_monitor_glob_init, uwsgi_imperial_monitor_glob);
|
||||
|
||||
// setup stats pushers
|
||||
uwsgi_register_stats_pusher("file", uwsgi_stats_pusher_file);
|
||||
uwsgi_stats_pusher_setup();
|
||||
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
// register embedded alarms
|
||||
uwsgi_register_embedded_alarms();
|
||||
#endif
|
||||
|
||||
|
||||
/* uWSGI IS CONFIGURED !!! */
|
||||
|
||||
if (uwsgi.dump_options) {
|
||||
@@ -1782,6 +1857,11 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
if (uwsgi.clock_list)
|
||||
clocks_list();
|
||||
|
||||
#ifdef UWSGI_ALARM
|
||||
if (uwsgi.alarms_list)
|
||||
alarms_list();
|
||||
#endif
|
||||
|
||||
// set the clock
|
||||
if (uwsgi.requested_clock)
|
||||
uwsgi_set_clock(uwsgi.requested_clock);
|
||||
@@ -1950,7 +2030,7 @@ int uwsgi_start(void *v_argv) {
|
||||
#ifdef RLIMIT_NPROC
|
||||
if (uwsgi.rl_nproc.rlim_max > 0) {
|
||||
uwsgi.rl_nproc.rlim_cur = uwsgi.rl_nproc.rlim_max;
|
||||
uwsgi_log("limiting number of processes to %d...\n", (int) uwsgi.rl_nproc.rlim_max);
|
||||
uwsgi_log_initial("limiting number of processes to %d...\n", (int) uwsgi.rl_nproc.rlim_max);
|
||||
if (setrlimit(RLIMIT_NPROC, &uwsgi.rl_nproc)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
@@ -1958,10 +2038,10 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (!getrlimit(RLIMIT_NPROC, &uwsgi.rl_nproc)) {
|
||||
if (uwsgi.rl_nproc.rlim_cur != RLIM_INFINITY) {
|
||||
uwsgi_log("your processes number limit is %d\n", (int) uwsgi.rl_nproc.rlim_cur);
|
||||
uwsgi_log_initial("your processes number limit is %d\n", (int) uwsgi.rl_nproc.rlim_cur);
|
||||
if ((int)uwsgi.rl_nproc.rlim_cur < uwsgi.numproc+uwsgi.master_process) {
|
||||
uwsgi.numproc = uwsgi.rl_nproc.rlim_cur - 1;
|
||||
uwsgi_log("!!! number of workers adjusted to %d due to system limits !!!\n", uwsgi.numproc);
|
||||
uwsgi_log_initial("!!! number of workers adjusted to %d due to system limits !!!\n", uwsgi.numproc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1970,7 +2050,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (uwsgi.rl.rlim_max > 0) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.rl.rlim_max;
|
||||
uwsgi_log("limiting address space of processes...\n");
|
||||
uwsgi_log_initial("limiting address space of processes...\n");
|
||||
if (setrlimit(RLIMIT_AS, &uwsgi.rl)) {
|
||||
uwsgi_error("setrlimit()");
|
||||
}
|
||||
@@ -1986,7 +2066,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_log("scheduler priority set to %d\n", uwsgi.prio);
|
||||
uwsgi_log_initial("scheduler priority set to %d\n", uwsgi.prio);
|
||||
}
|
||||
}
|
||||
if (!getrlimit(RLIMIT_AS, &uwsgi.rl)) {
|
||||
@@ -2031,15 +2111,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// prepare offload threads
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_attr_init(&uwsgi.static_offload_thread_attr);
|
||||
pthread_attr_setdetachstate(&uwsgi.static_offload_thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
// 512K should be enough...
|
||||
pthread_attr_setstacksize(&uwsgi.static_offload_thread_attr, 512 * 1024);
|
||||
pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
|
||||
}
|
||||
|
||||
if (uwsgi.requested_max_fd) {
|
||||
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
|
||||
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
|
||||
@@ -2101,6 +2172,10 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi.sa_lock = uwsgi_rwlock_init("sharedarea");
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
uwsgi.snmp_lock = uwsgi_lock_init("snmp");
|
||||
#endif
|
||||
|
||||
// setup queue
|
||||
if (uwsgi.queue_size > 0) {
|
||||
uwsgi_init_queue();
|
||||
@@ -2149,7 +2224,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
|
||||
// initialize request plugin only if workers or master are available
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode || uwsgi.loop) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->init) {
|
||||
uwsgi.p[i]->init();
|
||||
@@ -2165,7 +2240,7 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
|
||||
// again check for workers/sockets...
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode || uwsgi.loop) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_init) {
|
||||
uwsgi.p[i]->post_init();
|
||||
@@ -2193,7 +2268,7 @@ int uwsgi_start(void *v_argv) {
|
||||
pthread_mutex_init(&uwsgi.lock_static, NULL);
|
||||
|
||||
// again check for workers/sockets...
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode) {
|
||||
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server || uwsgi.command_mode || uwsgi.loop) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->enable_threads)
|
||||
uwsgi.p[i]->enable_threads();
|
||||
@@ -2202,6 +2277,11 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// users of the --loop option should know what they are doing... really...
|
||||
#ifndef UWSGI_DEBUG
|
||||
if (uwsgi.loop) goto unsafe;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor && !uwsgi.command_mode) {
|
||||
#else
|
||||
@@ -2225,6 +2305,10 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi.to_hell = 1;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_DEBUG
|
||||
unsafe:
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
int so_bufsize;
|
||||
@@ -2337,7 +2421,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
// initialize locks and socket as soon as possibile, as the master could enqueue tasks
|
||||
if (uwsgi.spoolers != NULL && uwsgi.sockets) {
|
||||
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
|
||||
create_signal_pipe(uwsgi.shared->spooler_signal_pipe);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
@@ -2463,7 +2547,7 @@ next:
|
||||
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spoolers != NULL && uwsgi.sockets) {
|
||||
if (uwsgi.spoolers != NULL && (uwsgi.sockets || uwsgi.loop)) {
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
while (uspool) {
|
||||
if (uspool->mode == UWSGI_SPOOLER_EXTERNAL) goto next2;
|
||||
@@ -2576,6 +2660,14 @@ next2:
|
||||
// set default wsgi_req (for loading apps);
|
||||
uwsgi.wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[0].req;
|
||||
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
uwsgi.offload_thread = uwsgi_offload_thread_start();
|
||||
if (!uwsgi.offload_thread) {
|
||||
uwsgi_log("unable to offload static file serving !!!\n");
|
||||
uwsgi.static_offload_to_thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// must be run before running apps
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
@@ -2706,6 +2798,16 @@ wait_for_call_of_duty:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
// create a pthread key, storing per-thread wsgi_request structure
|
||||
if (uwsgi.threads > 1) {
|
||||
if (pthread_key_create(&uwsgi.tur_key, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (uwsgi.loop) {
|
||||
void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop);
|
||||
@@ -2720,29 +2822,14 @@ wait_for_call_of_duty:
|
||||
uwsgi_log("your loop engine died. R.I.P.\n");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.threads > 1) {
|
||||
#ifdef UWSGI_THREADING
|
||||
if (pthread_key_create(&uwsgi.tur_key, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 1; i < uwsgi.threads; i++) {
|
||||
long j = i;
|
||||
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, simple_loop, (void *) j);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
long y = 0;
|
||||
simple_loop((void *) y);
|
||||
simple_loop();
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
else {
|
||||
async_loop(NULL);
|
||||
async_loop();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (uwsgi.snapshot) {
|
||||
@@ -2896,7 +2983,7 @@ void uwsgi_stdin_sendto(char *socket_name, uint8_t modifier1, uint8_t modifier2)
|
||||
#endif
|
||||
ptr += rlen;
|
||||
delta -= rlen;
|
||||
if (delta <= 0)
|
||||
if (delta == 0)
|
||||
break;
|
||||
rlen = read(0, ptr, delta);
|
||||
}
|
||||
@@ -3160,6 +3247,17 @@ void uwsgi_opt_add_regexp_list(char *opt, char *value, void *list) {
|
||||
struct uwsgi_regexp_list **ptr = (struct uwsgi_regexp_list **) list;
|
||||
uwsgi_regexp_new_list(ptr, value);
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_regexp_custom_list(char *opt, char *value, void *list) {
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid custom regexp syntax: must be <custom> <regexp>\n");
|
||||
exit(1);
|
||||
}
|
||||
char *custom = uwsgi_concat2n(value, space-value, "", 0);
|
||||
struct uwsgi_regexp_list **ptr = (struct uwsgi_regexp_list **) list;
|
||||
uwsgi_regexp_custom_new_list(ptr, space+1, custom);
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_shared_socket(char *opt, char *value, void *protocol) {
|
||||
@@ -3168,6 +3266,7 @@ void uwsgi_opt_add_shared_socket(char *opt, char *value, void *protocol) {
|
||||
|
||||
void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
|
||||
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
|
||||
uwsgi_sock->proto_name = protocol;
|
||||
}
|
||||
|
||||
@@ -3193,6 +3292,10 @@ void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_ssa(char *opt, char *value, void *foobar) {
|
||||
uwsgi_subscription_set_algo(value);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_scd(char *opt, char *value, void *foobar) {
|
||||
// openssl could not be initialized
|
||||
@@ -3275,10 +3378,6 @@ void uwsgi_opt_set_unshare(char *opt, char *value, void *none) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_daemon_new(&uwsgi.daemons, value);
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_env(char *opt, char *value, void *none) {
|
||||
if (putenv(value)) {
|
||||
uwsgi_error("putenv()");
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80
|
||||
|
||||
/*
|
||||
write(arg1);
|
||||
|
||||
wait_for_fd()
|
||||
|
||||
get_data() == 200
|
||||
*/
|
||||
@@ -1 +0,0 @@
|
||||
// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031
|
||||
@@ -2,6 +2,36 @@ import uwsgi
|
||||
if uwsgi.loop == 'gevent':
|
||||
import gevent
|
||||
|
||||
from threading import Thread
|
||||
import time
|
||||
from uwsgidecorators import postfork
|
||||
|
||||
def foobar():
|
||||
while True:
|
||||
time.sleep(3)
|
||||
print "threee second elapsed in worker %d" % uwsgi.worker_id()
|
||||
|
||||
@postfork
|
||||
def spawn_thread():
|
||||
t = Thread(target=foobar)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
@postfork
|
||||
def spawn_thread2():
|
||||
t = Thread(target=foobar)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def gl_func():
|
||||
while True:
|
||||
gevent.sleep(2)
|
||||
print "i am a greenltet running in worker %d" % uwsgi.worker_id()
|
||||
|
||||
@postfork
|
||||
def spawn_greenlet():
|
||||
gevent.spawn(gl_func)
|
||||
|
||||
print uwsgi.version
|
||||
print uwsgi.workers()
|
||||
try:
|
||||
|
||||
@@ -11,5 +11,6 @@ uwsgi_param SERVER_PROTOCOL $server_protocol;
|
||||
|
||||
uwsgi_param REMOTE_ADDR $remote_addr;
|
||||
uwsgi_param REMOTE_PORT $remote_port;
|
||||
uwsgi_param SERVER_ADDR $server_addr;
|
||||
uwsgi_param SERVER_PORT $server_port;
|
||||
uwsgi_param SERVER_NAME $server_name;
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_alarm_curl_config {
|
||||
int first;
|
||||
char *arg;
|
||||
char *subject;
|
||||
char *to;
|
||||
};
|
||||
|
||||
struct uwsgi_alarm_curl_opt {
|
||||
char *name;
|
||||
CURLoption option;
|
||||
void (*func)(CURL *, CURLoption, char *, struct uwsgi_alarm_curl_config*);
|
||||
};
|
||||
|
||||
|
||||
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->to = arg;
|
||||
struct curl_slist *list = NULL;
|
||||
char *items = uwsgi_str(arg);
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(items, ",", &ctx);
|
||||
while(p) {
|
||||
list = curl_slist_append(list, p);
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
curl_easy_setopt(curl, option, list);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_ssl(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
curl_easy_setopt(curl, option, (long)CURLUSESSL_ALL);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_int(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
curl_easy_setopt(curl, option, atoi(arg));
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
|
||||
uacc->subject = arg;
|
||||
}
|
||||
|
||||
static struct uwsgi_alarm_curl_opt uaco[] = {
|
||||
{"url", CURLOPT_URL, NULL},
|
||||
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
|
||||
{"mail_from", CURLOPT_MAIL_FROM, NULL},
|
||||
{"subject", 0, uwsgi_alarm_curl_set_subject},
|
||||
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
|
||||
{"auth_user", CURLOPT_USERNAME, NULL},
|
||||
{"auth_pass", CURLOPT_PASSWORD, NULL},
|
||||
{"method", CURLOPT_CUSTOMREQUEST, NULL},
|
||||
{"timeout", CURLOPT_TIMEOUT, uwsgi_alarm_curl_int},
|
||||
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_alarm_curl_int},
|
||||
{NULL, 0, NULL},
|
||||
};
|
||||
|
||||
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
|
||||
struct uwsgi_alarm_curl_opt *o = uaco;
|
||||
char *equal = strchr(opt,'=');
|
||||
if (!equal) {
|
||||
if (!uacc->first) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, opt);
|
||||
uacc->first = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
uacc->first = 1;
|
||||
*equal = 0;
|
||||
while(o->name) {
|
||||
if (!strcmp(o->name, opt)) {
|
||||
if (o->func) {
|
||||
o->func(curl, o->option, equal+1, uacc);
|
||||
}
|
||||
else {
|
||||
curl_easy_setopt(curl, o->option, equal+1);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
o++;
|
||||
}
|
||||
end:
|
||||
*equal = '=';
|
||||
}
|
||||
|
||||
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
|
||||
size_t full_size = size * nmemb;
|
||||
size_t remains = ut->len - ut->pos;
|
||||
struct uwsgi_alarm_curl_config *uacc = ut->data;
|
||||
|
||||
if (remains == 0) return 0;
|
||||
|
||||
if (ut->custom0 == 0) {
|
||||
size_t newline = 0;
|
||||
size_t required = 1;
|
||||
char *addr = ptr;
|
||||
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
|
||||
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
|
||||
if (required > full_size) goto skip;
|
||||
|
||||
|
||||
if (uacc->to) {
|
||||
memcpy(addr, "To: ", 4); addr+=4;
|
||||
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
}
|
||||
|
||||
if (uacc->subject) {
|
||||
memcpy(addr, "Subject: ", 9); addr+=9;
|
||||
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
|
||||
*addr ++= '\n';
|
||||
newline = 1;
|
||||
}
|
||||
skip:
|
||||
if (newline > 0) {
|
||||
*addr = '\n';
|
||||
}
|
||||
ut->custom0 = 1;
|
||||
return required;
|
||||
}
|
||||
|
||||
if (full_size < remains) {
|
||||
remains = full_size;
|
||||
}
|
||||
|
||||
memcpy(ptr, ut->buf + ut->pos, remains);
|
||||
ut->pos += remains;
|
||||
|
||||
return remains;
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
|
||||
int interesting_fd;
|
||||
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
// ARGH !!!
|
||||
if (!curl) return;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
|
||||
|
||||
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
|
||||
char *opts = uwsgi_str(uacc->arg);
|
||||
|
||||
// fill curl options
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
|
||||
if (ret <= 0) continue;
|
||||
if (interesting_fd != ut->pipe[1]) continue;
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
ut->pos = 0;
|
||||
ut->len = (size_t) rlen;
|
||||
ut->custom0 = 0;
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
|
||||
uacc->arg = uai->arg;
|
||||
ut->data = uacc;
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_curl_load(void) {
|
||||
uwsgi_register_alarm("curl", uwsgi_alarm_curl_init, uwsgi_alarm_curl_func);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin alarm_curl_plugin = {
|
||||
.name = "alarm_curl",
|
||||
.on_load = uwsgi_alarm_curl_load,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='alarm_curl'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lcurl']
|
||||
GCC_LIST = ['alarm_curl_plugin']
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "../../uwsgi.h"
|
||||
#import "Foundation/NSString.h"
|
||||
#import "AppKit/NSSpeechSynthesizer.h"
|
||||
|
||||
@interface uWSGIAlarmSpeaker : NSObject {
|
||||
NSSpeechSynthesizer *synth;
|
||||
}
|
||||
|
||||
-(void)speak: (NSString *)phrase;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation uWSGIAlarmSpeaker
|
||||
|
||||
- (uWSGIAlarmSpeaker *) init {
|
||||
self = [super init];
|
||||
synth = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)speak:(NSString *)phrase {
|
||||
[synth startSpeakingString:phrase];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// generate a uwsgi signal on alarm
|
||||
void uwsgi_alarm_speech_init(struct uwsgi_alarm_instance *uai) {
|
||||
uai->data_ptr = [[uWSGIAlarmSpeaker alloc] init];
|
||||
}
|
||||
|
||||
void uwsgi_alarm_speech_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
uWSGIAlarmSpeaker *say = (uWSGIAlarmSpeaker *) uai->data_ptr;
|
||||
NSString *phrase = [[NSString alloc] initWithBytes:msg
|
||||
length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
[say speak:phrase];
|
||||
[phrase release];
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_speech_load(void) {
|
||||
uwsgi_register_alarm("speech", uwsgi_alarm_speech_init, uwsgi_alarm_speech_func);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin alarm_speech_plugin = {
|
||||
.name = "alarm_speech",
|
||||
.on_load = uwsgi_alarm_speech_load,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='alarm_speech'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-framework appkit']
|
||||
GCC_LIST = ['alarm_speech.m']
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
|
||||
|
||||
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
|
||||
|
||||
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
|
||||
if (!ut) return;
|
||||
uai->data_ptr = ut;
|
||||
ut->data = uai->arg;
|
||||
}
|
||||
|
||||
// pipe the message into the thread;
|
||||
static void uwsgi_alarm_xmpp_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
|
||||
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
|
||||
ut->rlen = write(ut->pipe[0], msg, len);
|
||||
}
|
||||
|
||||
static void uwsgi_alarm_xmpp_load(void) {
|
||||
uwsgi_register_alarm("xmpp", uwsgi_alarm_xmpp_init, uwsgi_alarm_xmpp_func);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin alarm_xmpp_plugin = {
|
||||
.name = "alarm_xmpp",
|
||||
.on_load = uwsgi_alarm_xmpp_load,
|
||||
};
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <gloox/client.h>
|
||||
#include <gloox/message.h>
|
||||
#include <gloox/connectionlistener.h>
|
||||
#include <gloox/connectiontcpclient.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
using namespace gloox;
|
||||
|
||||
class Jabbo : public ConnectionListener{
|
||||
|
||||
public:
|
||||
|
||||
Jabbo(struct uwsgi_thread *ut, char *jab_username, char *jab_password, char *dests) {
|
||||
|
||||
u_thread = ut;
|
||||
dest = NULL;
|
||||
|
||||
char *ctx = NULL;
|
||||
char *p = strtok_r(dests, ",", &ctx);
|
||||
while(p) {
|
||||
uwsgi_string_new_list(&dest, p);
|
||||
p = strtok_r(NULL, ",", &ctx);
|
||||
}
|
||||
|
||||
JID jid(jab_username);
|
||||
client = new Client( jid, jab_password );
|
||||
client->registerConnectionListener(this);
|
||||
u_connected = 0;
|
||||
client->connect(false);
|
||||
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
|
||||
}
|
||||
|
||||
~Jabbo() {
|
||||
delete client;
|
||||
}
|
||||
|
||||
void send(char *buf, size_t len) {
|
||||
struct uwsgi_string_list *usl = dest;
|
||||
while(usl) {
|
||||
JID jid(usl->value);
|
||||
std::string text(buf, len);
|
||||
Message msg(Message::Chat, jid, text);
|
||||
client->send(msg);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onConnect() {
|
||||
event_queue_add_fd_read(u_thread->queue, fd);
|
||||
event_queue_add_fd_read(u_thread->queue, u_thread->pipe[1]);
|
||||
u_connected = 1;
|
||||
}
|
||||
|
||||
virtual void onDisconnect(ConnectionError e) {
|
||||
if (u_connected) {
|
||||
event_queue_del_fd(u_thread->queue, fd, event_queue_read());
|
||||
event_queue_del_fd(u_thread->queue, u_thread->pipe[1], event_queue_read());
|
||||
}
|
||||
sleep(1);
|
||||
u_connected = 0;
|
||||
client->connect(false);
|
||||
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
|
||||
}
|
||||
|
||||
virtual bool onTLSConnect(const CertInfo& info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Client* client;
|
||||
int fd;
|
||||
int u_connected;
|
||||
struct uwsgi_thread *u_thread;
|
||||
struct uwsgi_string_list *dest;
|
||||
};
|
||||
|
||||
|
||||
extern "C" void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *ut) {
|
||||
|
||||
int interesting_fd;
|
||||
|
||||
ut->buf = (char *) uwsgi_malloc(uwsgi.log_master_bufsize);
|
||||
|
||||
char *xmpp_username = (char *) "";
|
||||
char *xmpp_password = (char *) "";
|
||||
char *xmpp_dests = (char *) "";
|
||||
|
||||
// 0 -> username, 1 -> password, 2-> dest list
|
||||
int opt_state = 0;
|
||||
// fill xmpp options
|
||||
char *ctx = NULL;
|
||||
char *opts = uwsgi_str((char *)ut->data);
|
||||
char *p = strtok_r(opts, ";", &ctx);
|
||||
while(p) {
|
||||
switch(opt_state) {
|
||||
case 0:
|
||||
xmpp_username = p;
|
||||
opt_state = 1;
|
||||
break;
|
||||
case 1:
|
||||
xmpp_password = p;
|
||||
opt_state = 2;
|
||||
break;
|
||||
case 2:
|
||||
xmpp_dests = p;
|
||||
opt_state = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p = strtok_r(NULL, ";", &ctx);
|
||||
}
|
||||
|
||||
// do not process loglines til the jabber account is connected
|
||||
event_queue_del_fd(ut->queue, ut->pipe[1], event_queue_read());
|
||||
|
||||
Jabbo j(ut, xmpp_username, xmpp_password, xmpp_dests);
|
||||
|
||||
int timeout = 0;
|
||||
|
||||
for(;;) {
|
||||
if (j.u_connected) {
|
||||
timeout = -1;
|
||||
}
|
||||
else {
|
||||
timeout = 0;
|
||||
}
|
||||
int ret = event_queue_wait(ut->queue, timeout, &interesting_fd);
|
||||
if (ret < 0) continue;
|
||||
|
||||
if (ret > 0 && interesting_fd == ut->pipe[1]) {
|
||||
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
|
||||
if (rlen <= 0) continue;
|
||||
if (j.u_connected) {
|
||||
j.send(ut->buf, rlen);
|
||||
}
|
||||
}
|
||||
else if (ret == 0 || (ret > 0 && j.fd > -1 && interesting_fd == j.fd)) {
|
||||
j.client->recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='alarm_xmpp'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lgloox']
|
||||
GCC_LIST = ['alarm_xmpp_plugin', 'gloox.cc']
|
||||
@@ -185,7 +185,7 @@ void carbon_push_stats(int retry_cycle) {
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
total_vsz += uwsgi.workers[i].vsz_size;
|
||||
|
||||
total_harakiri += uwsgi.workers[i].harakiri_count/2;
|
||||
total_harakiri += uwsgi.workers[i].harakiri_count;
|
||||
}
|
||||
|
||||
//skip per worker metrics when disabled
|
||||
@@ -209,7 +209,7 @@ void carbon_push_stats(int retry_cycle) {
|
||||
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) worker_busyness, (unsigned long long) uwsgi.current_time);
|
||||
if (!wok) goto clear;
|
||||
|
||||
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count/2, (unsigned long long) uwsgi.current_time);
|
||||
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count, (unsigned long long) uwsgi.current_time);
|
||||
if (!wok) goto clear;
|
||||
|
||||
}
|
||||
|
||||
+305
-35
@@ -127,7 +127,7 @@ void uwsgi_opt_corerouter_ss(char *opt, char *value, void *cr) {
|
||||
ucr->has_subscription_sockets++;
|
||||
|
||||
// this is the subscription hash table
|
||||
ucr->subscriptions = uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
|
||||
ucr->subscriptions = uwsgi_subscription_init_ht();
|
||||
|
||||
ucr->has_backends++;
|
||||
|
||||
@@ -199,6 +199,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
}
|
||||
else if (cr_session->timed_out) {
|
||||
if (cr_session->instance_address_len > 0) {
|
||||
/*
|
||||
if (cr_session->status == COREROUTER_STATUS_CONNECTING) {
|
||||
if (!ucr->quiet)
|
||||
uwsgi_log("unable to connect() to uwsgi instance \"%.*s\": timeout\n", (int) cr_session->instance_address_len, cr_session->instance_address);
|
||||
@@ -206,6 +207,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
else if (cr_session->status == COREROUTER_STATUS_RESPONSE) {
|
||||
uwsgi_log("timeout waiting for instance \"%.*s\"\n", (int) cr_session->instance_address_len, cr_session->instance_address);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +275,7 @@ void corerouter_close_session(struct uwsgi_corerouter *ucr, struct corerouter_se
|
||||
|
||||
ucr->cr_table[cr_session->instance_fd] = cr_session;
|
||||
|
||||
cr_session->status = COREROUTER_STATUS_CONNECTING;
|
||||
//cr_session->status = COREROUTER_STATUS_CONNECTING;
|
||||
ucr->cr_table[cr_session->instance_fd] = cr_session;
|
||||
event_queue_add_fd_write(ucr->queue, cr_session->instance_fd);
|
||||
return;
|
||||
@@ -297,24 +299,15 @@ end:
|
||||
free(cr_session->buf_file_name);
|
||||
}
|
||||
|
||||
if (cr_session->write_queue)
|
||||
free(cr_session->write_queue);
|
||||
|
||||
if (cr_session->instance_write_queue)
|
||||
free(cr_session->instance_write_queue);
|
||||
|
||||
// could be used to free additional resources
|
||||
if (cr_session->close)
|
||||
cr_session->close(ucr, cr_session);
|
||||
|
||||
if (cr_session->keepalive) {
|
||||
cr_session->keepalive = 0;
|
||||
return;
|
||||
}
|
||||
cr_session->close(cr_session);
|
||||
|
||||
close(cr_session->fd);
|
||||
ucr->cr_table[cr_session->fd] = NULL;
|
||||
|
||||
uwsgi_buffer_destroy(cr_session->buffer);
|
||||
|
||||
cr_del_timeout(ucr, cr_session);
|
||||
free(cr_session);
|
||||
}
|
||||
@@ -340,7 +333,10 @@ static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
|
||||
cr_session->timed_out = 1;
|
||||
if (cr_session->retry) {
|
||||
cr_session->retry = 0;
|
||||
/*
|
||||
TODO allows retry
|
||||
ucr->switch_events(ucr, cr_session, -1);
|
||||
*/
|
||||
if (cr_session->retry) {
|
||||
cr_del_timeout(ucr, cr_session);
|
||||
cr_session->timeout = cr_add_fake_timeout(ucr, cr_session);
|
||||
@@ -359,23 +355,235 @@ static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_hook_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_read) goto unchanged;
|
||||
// if there is a write event defined, le'ts modify it
|
||||
if (cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
// simply remove the read event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_read())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if write is not defined, simply add a single monitor
|
||||
if (cs->event_hook_write == NULL) {
|
||||
if (!cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_read(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_read set to %p for %d\n", hook, cs->fd);
|
||||
#endif
|
||||
cs->event_hook_read = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_write) goto unchanged;
|
||||
// if there is a read event defined, le'ts modify it
|
||||
if (cs->event_hook_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
// simply remove the write event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->fd, event_queue_write())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if read is not defined, simply add a single monitor
|
||||
if (cs->event_hook_read == NULL) {
|
||||
if (!cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_write(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->fd);
|
||||
#endif
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_write set to %p for %d\n", hook, cs->fd);
|
||||
#endif
|
||||
cs->event_hook_write = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_instance_read(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_instance_read) goto unchanged;
|
||||
// if there is a write event defined, le'ts modify it
|
||||
if (cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_write() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_write(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
// simply remove the read event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_read())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if write is not defined, simply add a single monitor
|
||||
if (cs->event_hook_instance_write == NULL) {
|
||||
if (!cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_read() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_read(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_write_to_readwrite() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_write_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_instance_read set to %p for %d\n", hook, cs->instance_fd);
|
||||
#endif
|
||||
cs->event_hook_instance_read = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_hook_instance_write(struct corerouter_session *cs, ssize_t (*hook)(struct corerouter_session *)) {
|
||||
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
|
||||
// first check the case of event removal
|
||||
if (hook == NULL) {
|
||||
// nothing changed
|
||||
if (!cs->event_hook_instance_write) goto unchanged;
|
||||
// if there is a read event defined, le'ts modify it
|
||||
if (cs->event_hook_instance_read) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_readwrite_to_read() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_readwrite_to_read(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
// simply remove the write event
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_del_fd() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_del_fd(ucr->queue, cs->instance_fd, event_queue_write())) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// set the hook
|
||||
// if read is not defined, simply add a single monitor
|
||||
if (cs->event_hook_instance_read == NULL) {
|
||||
if (!cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_add_fd_write() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_add_fd_write(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!cs->event_hook_instance_write) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_queue_fd_read_to_readwrite() for %d\n", cs->instance_fd);
|
||||
#endif
|
||||
if (event_queue_fd_read_to_readwrite(ucr->queue, cs->instance_fd)) return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unchanged:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("event_hook_instance_write set to %p for %d\n", hook, cs->instance_fd);
|
||||
#endif
|
||||
cs->event_hook_instance_write = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, int new_connection, struct sockaddr *cr_addr, socklen_t cr_addr_len) {
|
||||
|
||||
ucr->cr_table[new_connection] = uwsgi_calloc(ucr->session_size);
|
||||
ucr->cr_table[new_connection]->fd = new_connection;
|
||||
ucr->cr_table[new_connection]->instance_fd = -1;
|
||||
ucr->cr_table[new_connection]->status = COREROUTER_STATUS_RECV_HDR;
|
||||
|
||||
ucr->cr_table[new_connection]->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
// map courerouter and socket
|
||||
ucr->cr_table[new_connection]->corerouter = ucr;
|
||||
ucr->cr_table[new_connection]->ugs = ugs;
|
||||
|
||||
ucr->cr_table[new_connection]->recv = uwsgi_cr_simple_recv;
|
||||
ucr->cr_table[new_connection]->send = uwsgi_cr_simple_send;
|
||||
ucr->cr_table[new_connection]->instance_recv = uwsgi_cr_simple_instance_recv;
|
||||
ucr->cr_table[new_connection]->instance_send = uwsgi_cr_simple_instance_send;
|
||||
// set initial timeout
|
||||
ucr->cr_table[new_connection]->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
|
||||
|
||||
// create dynamic buffer
|
||||
ucr->cr_table[new_connection]->buffer = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
// here we prepare the real session and set the hooks
|
||||
ucr->alloc_session(ucr, ugs, ucr->cr_table[new_connection], cr_addr, cr_addr_len);
|
||||
event_queue_add_fd_read(ucr->queue, new_connection);
|
||||
|
||||
return ucr->cr_table[new_connection];
|
||||
}
|
||||
@@ -479,6 +687,9 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
}
|
||||
else if (ucr->has_subscription_sockets) {
|
||||
ucr->mapper = uwsgi_cr_map_use_subscription;
|
||||
if (uwsgi.subscription_dotsplit) {
|
||||
ucr->mapper = uwsgi_cr_map_use_subscription_dotsplit;
|
||||
}
|
||||
}
|
||||
else if (ucr->base) {
|
||||
ucr->mapper = uwsgi_cr_map_use_base;
|
||||
@@ -501,6 +712,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
|
||||
for (;;) {
|
||||
|
||||
// set timeouts and harakiri
|
||||
min_timeout = uwsgi_min_rb_timer(ucr->timeouts);
|
||||
if (min_timeout == NULL) {
|
||||
delta = -1;
|
||||
@@ -517,6 +729,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
ushared->gateways_harakiri[id] = 0;
|
||||
}
|
||||
|
||||
// wait for events
|
||||
nevents = event_queue_wait_multi(ucr->queue, delta, events, ucr->nevents);
|
||||
|
||||
if (uwsgi.master_process && ucr->harakiri > 0) {
|
||||
@@ -529,25 +742,33 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
|
||||
// get the interesting fd
|
||||
interesting_fd = event_queue_interesting_fd(events, i);
|
||||
// something bad happened
|
||||
if (interesting_fd < 0) continue;
|
||||
|
||||
// check if the interesting_fd matches a gateway socket
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
int taken = 0;
|
||||
while (ugs) {
|
||||
if (ugs->gateway == &ushared->gateways[id] && interesting_fd == ugs->fd) {
|
||||
if (!ugs->subscription) {
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
new_connection = accept4(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len, SOCK_NONBLOCK);
|
||||
if (new_connection < 0) {
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
new_connection = accept(interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, interesting_fd);
|
||||
#endif
|
||||
if (new_connection < 0) {
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// set socket in non-blocking mode, on non-linux platforms, clients get the server mode
|
||||
#ifdef __linux__
|
||||
uwsgi_socket_nb(new_connection);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
corerouter_alloc_session(ucr, ugs, new_connection, (struct sockaddr *) &cr_addr, cr_addr_len);
|
||||
@@ -568,9 +789,11 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// manage internal subscription
|
||||
if (interesting_fd == ushared->gateways[id].internal_subscription_pipe[1]) {
|
||||
uwsgi_corerouter_manage_internal_subscription(ucr, interesting_fd);
|
||||
}
|
||||
// manage a stats request
|
||||
else if (interesting_fd == ucr->cr_stats_server) {
|
||||
corerouter_send_stats(ucr);
|
||||
}
|
||||
@@ -581,17 +804,56 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
if (cr_session == NULL)
|
||||
continue;
|
||||
|
||||
// on error, destroy the session
|
||||
if (event_queue_interesting_fd_has_error(events, i)) {
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
if (interesting_fd == cr_session->instance_fd) {
|
||||
cr_session->instance_failed = 1;
|
||||
}
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
|
||||
|
||||
// implementation specific cycle;
|
||||
ucr->switch_events(ucr, cr_session, interesting_fd);
|
||||
|
||||
// set timeout
|
||||
cr_session->timeout = corerouter_reset_timeout(ucr, cr_session);
|
||||
// call event hook
|
||||
ssize_t (*hook)(struct corerouter_session *) = NULL;
|
||||
if (interesting_fd == cr_session->fd) {
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
hook = cr_session->event_hook_read;
|
||||
}
|
||||
else if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
hook = cr_session->event_hook_write;
|
||||
}
|
||||
}
|
||||
else if (interesting_fd == cr_session->instance_fd) {
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
hook = cr_session->event_hook_instance_read;
|
||||
}
|
||||
else if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
hook = cr_session->event_hook_instance_write;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hook) {
|
||||
uwsgi_log("[uwsgi-corerouter] BUG, unexpected event received !!!\n");
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
// reset errno (as we use it for internal signalling)
|
||||
errno = 0;
|
||||
ssize_t ret = hook(cr_session);
|
||||
// connection closed
|
||||
if (ret == 0) {
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
if (errno == EINPROGRESS) continue;
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -668,14 +930,18 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
socklen_t client_src_len = 0;
|
||||
|
||||
int client_fd = accept(ucr->cr_stats_server, (struct sockaddr *) &client_src, &client_src_len);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, ucr->cr_stats_server);
|
||||
#endif
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi.stats_http) {
|
||||
if (uwsgi_send_http_stats(client_fd)) {
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_stats *us = uwsgi_stats_new(8192);
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION)) goto end;
|
||||
@@ -773,6 +1039,10 @@ void corerouter_send_stats(struct uwsgi_corerouter *ucr) {
|
||||
size_t remains = us->pos;
|
||||
off_t pos = 0;
|
||||
while(remains > 0) {
|
||||
int ret = uwsgi_waitfd_write(client_fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (ret <= 0) {
|
||||
goto end0;
|
||||
}
|
||||
ssize_t res = write(client_fd, us->base + pos, remains);
|
||||
if (res <= 0) {
|
||||
if (res < 0) {
|
||||
|
||||
+31
-33
@@ -9,6 +9,12 @@
|
||||
#define cr_del_check_timeout(x) rb_erase(&x->rbt, timeouts);
|
||||
#define cr_del_timeout(u, x) rb_erase(&x->timeout->rbt, u->timeouts); free(x->timeout);
|
||||
|
||||
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
|
||||
errno = EINPROGRESS;\
|
||||
return -1;\
|
||||
}
|
||||
|
||||
|
||||
struct corerouter_session;
|
||||
|
||||
struct uwsgi_corerouter {
|
||||
@@ -19,7 +25,6 @@ struct uwsgi_corerouter {
|
||||
|
||||
void (*alloc_session)(struct uwsgi_corerouter *, struct uwsgi_gateway_socket *, struct corerouter_session *, struct sockaddr *, socklen_t);
|
||||
int (*mapper)(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
void (*switch_events)(struct uwsgi_corerouter *, struct corerouter_session *, int);
|
||||
|
||||
int has_sockets;
|
||||
int has_backends;
|
||||
@@ -60,7 +65,6 @@ struct uwsgi_corerouter {
|
||||
int use_cluster;
|
||||
|
||||
struct uwsgi_subscribe_slot **subscriptions;
|
||||
int subscription_regexp;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
@@ -87,15 +91,13 @@ struct corerouter_session {
|
||||
|
||||
int fd;
|
||||
int instance_fd;
|
||||
int instance_stopped;
|
||||
int status;
|
||||
|
||||
uint8_t h_pos;
|
||||
|
||||
uint16_t pos;
|
||||
|
||||
// corerouter related to this session
|
||||
struct uwsgi_corerouter *corerouter;
|
||||
// gateway socket related to this session
|
||||
struct uwsgi_gateway_socket *ugs;
|
||||
|
||||
// parsed hostname
|
||||
char *hostname;
|
||||
uint16_t hostname_len;
|
||||
|
||||
@@ -111,13 +113,10 @@ struct corerouter_session {
|
||||
int soopt;
|
||||
int timed_out;
|
||||
|
||||
// used for tracking required event
|
||||
int fd_state;
|
||||
int instance_fd_state;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
|
||||
// check content_length
|
||||
size_t post_cl;
|
||||
size_t post_remains;
|
||||
|
||||
@@ -126,30 +125,29 @@ struct corerouter_session {
|
||||
char *buf_file_name;
|
||||
FILE *buf_file;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
char *tmp_socket_name;
|
||||
|
||||
// store the client address
|
||||
struct sockaddr_un addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
int keepalive;
|
||||
// async hooks:
|
||||
// the session is watiting for this fd
|
||||
ssize_t (*event_hook_read)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_write)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_instance_read)(struct corerouter_session *);
|
||||
ssize_t (*event_hook_instance_write)(struct corerouter_session *);
|
||||
|
||||
char *write_queue;
|
||||
size_t write_queue_len;
|
||||
int write_queue_close;
|
||||
void (*close)(struct corerouter_session *);
|
||||
|
||||
char *instance_write_queue;
|
||||
size_t instance_write_queue_len;
|
||||
struct uwsgi_buffer *buffer;
|
||||
size_t buffer_len;
|
||||
off_t buffer_pos;
|
||||
|
||||
void (*close)(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
|
||||
ssize_t (*recv)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
ssize_t (*send)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
|
||||
ssize_t (*instance_recv)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
ssize_t (*instance_send)(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
struct uwsgi_header uh;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
};
|
||||
|
||||
void uwsgi_opt_corerouter(char *, char *, void *);
|
||||
@@ -177,6 +175,7 @@ int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *, struct corerouter_session
|
||||
int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_cluster(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
int uwsgi_cr_map_use_to(struct uwsgi_corerouter *, struct corerouter_session *);
|
||||
@@ -184,8 +183,7 @@ int uwsgi_cr_map_use_static_nodes(struct uwsgi_corerouter *, struct corerouter_s
|
||||
|
||||
int uwsgi_courerouter_has_has_backends(struct uwsgi_corerouter *);
|
||||
|
||||
ssize_t uwsgi_cr_simple_recv(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
ssize_t uwsgi_cr_simple_send(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
|
||||
ssize_t uwsgi_cr_simple_instance_recv(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
ssize_t uwsgi_cr_simple_instance_send(struct uwsgi_corerouter *, struct corerouter_session *, char *, size_t);
|
||||
int uwsgi_cr_hook_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_instance_read(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
int uwsgi_cr_hook_instance_write(struct corerouter_session *, ssize_t (*)(struct corerouter_session *));
|
||||
|
||||
+18
-213
@@ -10,197 +10,6 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include "cr.h"
|
||||
|
||||
ssize_t uwsgi_cr_simple_recv(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
ssize_t ret = recv(cs->fd, buf, len, 0);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_error("recv()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_cr_simple_instance_recv(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
ssize_t ret = recv(cs->instance_fd, buf, len, 0);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_error("recv()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_cr_simple_send(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
ssize_t ret = -1;
|
||||
char *tmp_buf;
|
||||
off_t pos = 0;
|
||||
|
||||
size_t partial_len = len;
|
||||
off_t partial_pos = 0;
|
||||
|
||||
if (cs->write_queue_len > 0) {
|
||||
ret = send(cs->fd, cs->write_queue, cs->write_queue_len, 0);
|
||||
if (ret > 0) {
|
||||
cs->write_queue_len-=ret;
|
||||
pos = ret;
|
||||
if (cs->write_queue_len == 0) {
|
||||
free(cs->write_queue);
|
||||
cs->write_queue = NULL;
|
||||
if (cs->fd_state) {
|
||||
event_queue_fd_write_to_read(uc->queue, cs->fd);
|
||||
cs->fd_state = 0;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
goto blocking;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto blocking;
|
||||
}
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
if (len == 0) goto end;
|
||||
|
||||
ret = send(cs->fd, buf, len, 0);
|
||||
if (ret > 0) {
|
||||
if ((size_t)ret == len) return len;
|
||||
partial_len-=ret;
|
||||
partial_pos = ret;
|
||||
goto blocking;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto blocking;
|
||||
}
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
|
||||
end:
|
||||
if (cs->write_queue_close) {
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
|
||||
blocking:
|
||||
// wait for write
|
||||
if (!cs->fd_state) {
|
||||
event_queue_fd_read_to_write(uc->queue, cs->fd);
|
||||
cs->fd_state = 1;
|
||||
}
|
||||
// add new datas to the buffer
|
||||
tmp_buf = malloc(cs->write_queue_len+partial_len);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("malloc()");
|
||||
return -1;
|
||||
}
|
||||
if (cs->write_queue_len>0) {
|
||||
memcpy(tmp_buf, cs->write_queue+pos, cs->write_queue_len);
|
||||
free(cs->write_queue);
|
||||
}
|
||||
memcpy(tmp_buf+cs->write_queue_len, buf+partial_pos, partial_len);
|
||||
cs->write_queue = tmp_buf;
|
||||
cs->write_queue_len+=partial_len;
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_cr_simple_instance_send(struct uwsgi_corerouter *uc, struct corerouter_session *cs, char *buf, size_t len) {
|
||||
ssize_t ret;
|
||||
char *tmp_buf;
|
||||
off_t pos = 0;
|
||||
|
||||
size_t partial_len = len;
|
||||
off_t partial_pos = 0;
|
||||
|
||||
if (cs->instance_write_queue_len > 0) {
|
||||
ret = send(cs->instance_fd, cs->instance_write_queue, cs->instance_write_queue_len, 0);
|
||||
if (ret > 0) {
|
||||
cs->instance_write_queue_len-=ret;
|
||||
pos=ret;
|
||||
if (cs->instance_write_queue_len == 0) {
|
||||
free(cs->instance_write_queue);
|
||||
cs->instance_write_queue = NULL;
|
||||
if (cs->instance_fd_state) {
|
||||
event_queue_fd_write_to_read(uc->queue, cs->instance_fd);
|
||||
cs->instance_fd_state = 0;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
goto blocking;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto blocking;
|
||||
}
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
ret = send(cs->instance_fd, buf, len, 0);
|
||||
if (ret > 0) {
|
||||
if ((size_t)ret == len) return len;
|
||||
partial_len-=ret;
|
||||
partial_pos = ret;
|
||||
goto blocking;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
goto blocking;
|
||||
}
|
||||
uwsgi_error("send()");
|
||||
return -1;
|
||||
|
||||
blocking:
|
||||
// wait for write
|
||||
if (!cs->instance_fd_state) {
|
||||
event_queue_fd_read_to_write(uc->queue, cs->instance_fd);
|
||||
cs->instance_fd_state = 1;
|
||||
}
|
||||
// add new datas to the buffer
|
||||
tmp_buf = malloc(cs->instance_write_queue_len+partial_len);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("malloc()");
|
||||
return -1;
|
||||
}
|
||||
if (cs->instance_write_queue_len>0) {
|
||||
memcpy(tmp_buf, cs->instance_write_queue+pos, cs->instance_write_queue_len);
|
||||
free(cs->instance_write_queue);
|
||||
}
|
||||
memcpy(tmp_buf+cs->instance_write_queue_len, buf+partial_pos, partial_len);
|
||||
cs->instance_write_queue = tmp_buf;
|
||||
cs->instance_write_queue_len+=partial_len;
|
||||
errno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
@@ -208,24 +17,24 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
|
||||
if (!strcmp(ucr->name, ugs->owner)) {
|
||||
if (!ugs->subscription) {
|
||||
if (ugs->name[0] == '=') {
|
||||
int shared_socket = atoi(ugs->name+1);
|
||||
if (shared_socket >= 0) {
|
||||
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
int shared_socket = atoi(ugs->name + 1);
|
||||
if (shared_socket >= 0) {
|
||||
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
|
||||
ugs->shared = 1;
|
||||
if (ugs->fd == -1) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
if (ugs->fd == -1) {
|
||||
uwsgi_log("unable to use shared socket %d\n", shared_socket);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
|
||||
int fd_socket = atoi(ugs->name+5);
|
||||
else if (!uwsgi_startswith("fd://", ugs->name, 5)) {
|
||||
int fd_socket = atoi(ugs->name + 5);
|
||||
if (fd_socket >= 0) {
|
||||
ugs->fd = fd_socket;
|
||||
ugs->name = uwsgi_getsockname(ugs->fd);
|
||||
if (!ugs->name) {
|
||||
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
|
||||
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -295,9 +104,6 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, ugs->fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
|
||||
@@ -309,7 +115,7 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr, ucr->subscription_regexp) && ucr->i_am_cheap) {
|
||||
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr) && ucr->i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, ucr->name) && !ugs->subscription) {
|
||||
@@ -323,12 +129,14 @@ void uwsgi_corerouter_manage_subscription(struct uwsgi_corerouter *ucr, int id,
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ucr->subscription_regexp);
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len);
|
||||
if (node && node->len) {
|
||||
#ifdef UWSGI_SSL
|
||||
if (uwsgi.subscriptions_sign_check_dir) {
|
||||
if (usr.sign_len == 0 || usr.base_len == 0) return;
|
||||
if (usr.unix_check <= node->unix_check) return ;
|
||||
if (usr.sign_len == 0 || usr.base_len == 0)
|
||||
return;
|
||||
if (usr.unix_check <= node->unix_check)
|
||||
return;
|
||||
if (!uwsgi_subscription_sign_check(node->slot, &usr)) {
|
||||
return;
|
||||
}
|
||||
@@ -369,16 +177,13 @@ void uwsgi_corerouter_manage_internal_subscription(struct uwsgi_corerouter *ucr,
|
||||
char bbuf[4096];
|
||||
|
||||
ssize_t len = recv(fd, bbuf, 4096, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, fd);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
|
||||
uwsgi_hooked_parse(bbuf + 4, len - 4, corerouter_manage_subscription, &usr);
|
||||
|
||||
// subscribe request ?
|
||||
if (bbuf[3] == 0) {
|
||||
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr, ucr->subscription_regexp) && ucr->i_am_cheap) {
|
||||
if (uwsgi_add_subscribe_node(ucr->subscriptions, &usr) && ucr->i_am_cheap) {
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
|
||||
while (ugs) {
|
||||
if (!strcmp(ugs->owner, ucr->name) && !ugs->subscription) {
|
||||
@@ -392,7 +197,7 @@ void uwsgi_corerouter_manage_internal_subscription(struct uwsgi_corerouter *ucr,
|
||||
}
|
||||
//unsubscribe
|
||||
else {
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, ucr->subscription_regexp);
|
||||
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(ucr->subscriptions, usr.key, usr.keylen, usr.address, usr.address_len);
|
||||
if (node && node->len) {
|
||||
if (node->death_mark == 0)
|
||||
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", ucr->name, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
|
||||
|
||||
@@ -31,7 +31,7 @@ int uwsgi_cr_map_use_pattern(struct uwsgi_corerouter *ucr, struct corerouter_ses
|
||||
|
||||
int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, cr_session->hostname, cr_session->hostname_len, ucr->subscription_regexp);
|
||||
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, cr_session->hostname, cr_session->hostname_len);
|
||||
if (cr_session->un && cr_session->un->len) {
|
||||
cr_session->instance_address = cr_session->un->name;
|
||||
cr_session->instance_address_len = cr_session->un->len;
|
||||
@@ -44,6 +44,38 @@ int uwsgi_cr_map_use_subscription(struct uwsgi_corerouter *ucr, struct coreroute
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_cr_map_use_subscription_dotsplit(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
char *name = cr_session->hostname;
|
||||
uint16_t name_len = cr_session->hostname_len;
|
||||
|
||||
split:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("trying with %.*s\n", name_len, name);
|
||||
#endif
|
||||
cr_session->un = uwsgi_get_subscribe_node(ucr->subscriptions, name, name_len);
|
||||
if (!cr_session->un) {
|
||||
char *next = memchr(name+1, '.', name_len-1);
|
||||
if (next) {
|
||||
name_len -= next - name;
|
||||
name = next;
|
||||
goto split;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr_session->un && cr_session->un->len) {
|
||||
cr_session->instance_address = cr_session->un->name;
|
||||
cr_session->instance_address_len = cr_session->un->len;
|
||||
cr_session->modifier1 = cr_session->un->modifier1;
|
||||
}
|
||||
else if (ucr->cheap && !ucr->i_am_cheap && uwsgi_no_subscriptions(ucr->subscriptions)) {
|
||||
uwsgi_gateway_go_cheap(ucr->name, ucr->queue, &ucr->i_am_cheap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_cr_map_use_base(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
|
||||
|
||||
int tmp_socket_name_len = 0;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// global variables for configuration
|
||||
static uint8_t dumbloop_modifier1 = 0;
|
||||
static char *dumbloop_code = "";
|
||||
static char *dumbloop_function = "dumbloop";
|
||||
|
||||
struct uwsgi_option dumbloop_options[] = {
|
||||
{"dumbloop-modifier1", required_argument, 0, "set the modifier1 for the code_string", uwsgi_opt_set_int, &dumbloop_modifier1, 0},
|
||||
{"dumbloop-code", required_argument, 0, "set the script to load for the code_string", uwsgi_opt_set_str, &dumbloop_code, 0},
|
||||
{"dumbloop-function", required_argument, 0, "set the function to run for the code_string", uwsgi_opt_set_str, &dumbloop_function, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
// this function is executed for each thread
|
||||
static void *dumb_loop_run(void *arg1) {
|
||||
|
||||
// get the core id (pthreads take a void pointer as argument, so we need this ugly trick)
|
||||
long core_id = (long) arg1;
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
// complete threads setup (this is required for fixing things like UNIX signal handling)
|
||||
if (uwsgi.threads > 1) {
|
||||
// wsgi_request mapped to the core
|
||||
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
|
||||
// fix it
|
||||
uwsgi_setup_thread_req(core_id, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
// this strign will be passed to the code_string function
|
||||
char *str_core = uwsgi_num2str(core_id);
|
||||
// ok we are ready, let's run custom code
|
||||
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
if (uwsgi.p[dumbloop_modifier1]->code_string) {
|
||||
// "uwsgi_dumbloop" is the name of the module (will be used while importing the file, if needed)
|
||||
uwsgi.p[dumbloop_modifier1]->code_string("uwsgi_dumbloop", dumbloop_code, dumbloop_function, str_core, strlen(str_core));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("the requested plugin does not support code_string hook\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dumb_loop() {
|
||||
// this run the dumb_loop_run in each thread (core)
|
||||
uwsgi_loop_cores_run(dumb_loop_run);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// register the new loop engine
|
||||
static void dumbloop_register() {
|
||||
uwsgi_register_loop( (char *) "dumb", dumb_loop);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin dumbloop_plugin = {
|
||||
.name = "dumbloop",
|
||||
.on_load = dumbloop_register,
|
||||
.options = dumbloop_options,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='dumbloop'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['dumb']
|
||||
@@ -244,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
}
|
||||
|
||||
void erlang_loop(int id) {
|
||||
void erlang_loop(int id, void *data) {
|
||||
|
||||
ErlConnect econn;
|
||||
//ErlMessage em;
|
||||
@@ -422,7 +422,7 @@ int erlang_init() {
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop, NULL) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+300
-16
@@ -2,35 +2,37 @@
|
||||
|
||||
uWSGI fastrouter
|
||||
|
||||
requires:
|
||||
|
||||
- async
|
||||
- caching
|
||||
- pcre (optional)
|
||||
|
||||
*/
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include "../corerouter/cr.h"
|
||||
|
||||
struct uwsgi_fastrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
} ufr;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
struct uwsgi_fastrouter ufr;
|
||||
|
||||
struct fastrouter_session {
|
||||
struct corerouter_session crs;
|
||||
struct uwsgi_buffer *post_buf;
|
||||
size_t post_buf_max;
|
||||
size_t post_buf_len;
|
||||
off_t post_buf_pos;
|
||||
};
|
||||
|
||||
struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter", required_argument, 0, "run the fastrouter on the specified port", uwsgi_opt_corerouter, &ufr, 0},
|
||||
{"fastrouter-processes", required_argument, 0, "prefork the specified number of fastrouter processes", uwsgi_opt_set_int, &ufr.cr.processes, 0},
|
||||
{"fastrouter-workers", required_argument, 0, "prefork the specified number of fastrouter processes", uwsgi_opt_set_int, &ufr.cr.processes, 0},
|
||||
{"fastrouter-zerg", required_argument, 0, "attach the fastrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufr, 0 },
|
||||
{"fastrouter-zerg", required_argument, 0, "attach the fastrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufr, 0},
|
||||
{"fastrouter-use-cache", no_argument, 0, "use uWSGI cache as hostname->server mapper for the fastrouter", uwsgi_opt_true, &ufr.cr.use_cache, 0},
|
||||
|
||||
{"fastrouter-use-pattern", required_argument, 0, "use a pattern for fastrouter hostname->server mapping", uwsgi_opt_corerouter_use_pattern, &ufr, 0},
|
||||
{"fastrouter-use-base", required_argument, 0, "use a base dir for fastrouter hostname->server mapping", uwsgi_opt_corerouter_use_base, &ufr, 0},
|
||||
|
||||
{"fastrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufr.cr.fallback, 0},
|
||||
|
||||
|
||||
{"fastrouter-use-cluster", no_argument, 0, "load balance to nodes subscribed to the cluster", uwsgi_opt_true, &ufr.cr.use_cluster, 0},
|
||||
|
||||
{"fastrouter-use-code-string", required_argument, 0, "use code string as hostname->server mapper for the fastrouter", uwsgi_opt_corerouter_cs, &ufr, 0},
|
||||
@@ -42,7 +44,6 @@ struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-cheap", no_argument, 0, "run the fastrouter in cheap mode", uwsgi_opt_true, &ufr.cr.cheap, 0},
|
||||
{"fastrouter-subscription-server", required_argument, 0, "run the fastrouter subscription server on the spcified address", uwsgi_opt_corerouter_ss, &ufr, 0},
|
||||
{"fastrouter-subscription-slot", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "useless thanks to the new implementation", 0},
|
||||
{"fastrouter-subscription-use-regexp", no_argument, 0, "enable regexp for subscription system", uwsgi_opt_true, &ufr.cr.subscription_regexp, 0},
|
||||
|
||||
{"fastrouter-timeout", required_argument, 0, "set fastrouter timeout", uwsgi_opt_set_int, &ufr.cr.socket_timeout, 0},
|
||||
{"fastrouter-post-buffering", required_argument, 0, "enable fastrouter post buffering", uwsgi_opt_set_64bit, &ufr.cr.post_buffering, 0},
|
||||
@@ -51,19 +52,302 @@ struct uwsgi_option fastrouter_options[] = {
|
||||
{"fastrouter-stats", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-stats-server", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-ss", required_argument, 0, "run the fastrouter stats server", uwsgi_opt_set_str, &ufr.cr.stats_server, 0},
|
||||
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0 },
|
||||
{"fastrouter-harakiri", required_argument, 0, "enable fastrouter harakiri", uwsgi_opt_set_int, &ufr.cr.harakiri, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
ssize_t fr_recv_uwsgi_header(struct corerouter_session *);
|
||||
ssize_t fr_instance_read_response(struct corerouter_session *);
|
||||
ssize_t fr_read_body(struct corerouter_session *);
|
||||
|
||||
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
// here i use directly corerouter_session
|
||||
struct corerouter_session *cs = (struct corerouter_session *) data;
|
||||
|
||||
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !cs->hostname_len) {
|
||||
cs->hostname = val;
|
||||
cs->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !cs->has_key) {
|
||||
cs->hostname = val;
|
||||
cs->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
|
||||
cs->has_key = 1;
|
||||
cs->hostname = val;
|
||||
cs->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
|
||||
cs->post_cl = uwsgi_str_num(val, vallen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fr_write_body(struct corerouter_session * cs) {
|
||||
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
|
||||
ssize_t len = write(cs->instance_fd, fs->post_buf->buf + fs->post_buf_pos, fs->post_buf_len - fs->post_buf_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_write_body()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fs->post_buf_pos += len;
|
||||
|
||||
// the body chunk has been sent, start again reading from client and instance
|
||||
if (fs->post_buf_pos == (ssize_t) fs->post_buf_len) {
|
||||
uwsgi_cr_hook_instance_write(cs, NULL);
|
||||
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
|
||||
uwsgi_cr_hook_read(cs, fr_read_body);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
ssize_t fr_read_body(struct corerouter_session * cs) {
|
||||
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
|
||||
ssize_t len = read(cs->fd, fs->post_buf->buf, fs->post_buf_max);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_read_body()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// connection closed
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
fs->post_buf_len = len;
|
||||
fs->post_buf_pos = 0;
|
||||
|
||||
// ok we have a body, stop reading from the client and the instance and start writing to the instance
|
||||
uwsgi_cr_hook_read(cs, NULL);
|
||||
uwsgi_cr_hook_instance_read(cs, NULL);
|
||||
uwsgi_cr_hook_instance_write(cs, fr_write_body);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_write_response(struct corerouter_session * cs) {
|
||||
ssize_t len = write(cs->fd, cs->buffer->buf + cs->buffer_pos, cs->buffer_len - cs->buffer_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_write_response()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos += len;
|
||||
|
||||
// ok this response chunk is sent, let's wait for another one
|
||||
if (cs->buffer_pos == (ssize_t) cs->buffer_len) {
|
||||
uwsgi_cr_hook_write(cs, NULL);
|
||||
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_instance_read_response(struct corerouter_session * cs) {
|
||||
ssize_t len = read(cs->instance_fd, cs->buffer->buf, cs->buffer->len);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_instance_read_response()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// end of the response
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs->buffer_pos = 0;
|
||||
cs->buffer_len = len;
|
||||
// ok stop reading from the instance, and start writing to the client
|
||||
uwsgi_cr_hook_instance_read(cs, NULL);
|
||||
uwsgi_cr_hook_write(cs, fr_write_response);
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_instance_send_request(struct corerouter_session * cs) {
|
||||
ssize_t len = write(cs->instance_fd, cs->buffer->buf + cs->buffer_pos, cs->uh.pktsize - cs->buffer_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_instance_send_request()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos += len;
|
||||
|
||||
// ok the request is sent, we can start sending client body (if any) and we can start waiting
|
||||
// for response
|
||||
if (cs->buffer_pos == cs->uh.pktsize) {
|
||||
cs->buffer_pos = 0;
|
||||
// stop writing to the instance
|
||||
uwsgi_cr_hook_instance_write(cs, NULL);
|
||||
// start reading from the instance
|
||||
uwsgi_cr_hook_instance_read(cs, fr_instance_read_response);
|
||||
// re-start reading from the client (for body or connection close)
|
||||
struct fastrouter_session *fs = (struct fastrouter_session *) cs;
|
||||
// allocate a buffer for client body (could be delimited or dynamic)
|
||||
fs->post_buf_max = UMAX16;
|
||||
if (cs->post_cl > 0) {
|
||||
fs->post_buf_max = UMIN(UMAX16, cs->post_cl);
|
||||
}
|
||||
fs->post_buf = uwsgi_buffer_new(fs->post_buf_max);
|
||||
if (!fs->post_buf)
|
||||
return -1;
|
||||
uwsgi_cr_hook_read(cs, fr_read_body);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_instance_send_request_header(struct corerouter_session * cs) {
|
||||
ssize_t len = write(cs->instance_fd, &cs->uh + cs->buffer_pos, 4 - cs->buffer_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_instance_send_request_header()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos += len;
|
||||
|
||||
// ok the request is sent, we can start sending client body (if any) and we can start waiting
|
||||
// for response
|
||||
if (cs->buffer_pos == 4) {
|
||||
cs->buffer_pos = 0;
|
||||
uwsgi_cr_hook_instance_write(cs, fr_instance_send_request);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_instance_connected(struct corerouter_session * cs) {
|
||||
|
||||
socklen_t solen = sizeof(int);
|
||||
|
||||
// first check for errors
|
||||
if (getsockopt(cs->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&cs->soopt), &solen) < 0) {
|
||||
uwsgi_error("fr_instance_connected()/getsockopt()");
|
||||
cs->instance_failed = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cs->soopt) {
|
||||
cs->instance_failed = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos = 0;
|
||||
|
||||
// ok instance is connected, wait for write again
|
||||
if (cs->un) cs->un->requests++;
|
||||
uwsgi_cr_hook_instance_write(cs, fr_instance_send_request_header);
|
||||
// return a value > 0
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t fr_recv_uwsgi_vars(struct corerouter_session * cs) {
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(cs->buffer, cs->uh.pktsize))
|
||||
return -1;
|
||||
ssize_t len = read(cs->fd, cs->buffer->buf + cs->buffer_pos, cs->uh.pktsize - cs->buffer_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_recv_uwsgi_vars()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos += len;
|
||||
|
||||
// headers received, ready to choose the instance
|
||||
if (cs->buffer_pos == cs->uh.pktsize) {
|
||||
struct uwsgi_corerouter *ucr = cs->corerouter;
|
||||
// find the hostname
|
||||
if (uwsgi_hooked_parse(cs->buffer->buf, cs->uh.pktsize, fr_get_hostname, (void *) cs)) {
|
||||
return -1;
|
||||
}
|
||||
// check the hostname;
|
||||
if (cs->hostname_len == 0)
|
||||
return -1;
|
||||
// find an instance using the key
|
||||
if (cs->corerouter->mapper(cs->corerouter, cs))
|
||||
return -1;
|
||||
// check instance
|
||||
if (cs->instance_address_len == 0) {
|
||||
// if fallback nodes are configured, trigger them
|
||||
if (ucr->fallback) {
|
||||
cs->instance_failed = 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// stop receiving from the client
|
||||
uwsgi_cr_hook_read(cs, NULL);
|
||||
|
||||
// start async connect
|
||||
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
|
||||
if (cs->instance_fd < 0) {
|
||||
cs->instance_failed = 1;
|
||||
cs->soopt = errno;
|
||||
return -1;
|
||||
}
|
||||
// map the instance
|
||||
cs->corerouter->cr_table[cs->instance_fd] = cs;
|
||||
// wait for connection
|
||||
uwsgi_cr_hook_instance_write(cs, fr_instance_connected);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t fr_recv_uwsgi_header(struct corerouter_session * cs) {
|
||||
ssize_t len = read(cs->fd, cs->buffer->buf + cs->buffer_pos, 4 - cs->buffer_pos);
|
||||
if (len < 0) {
|
||||
cr_try_again;
|
||||
uwsgi_error("fr_recv_uwsgi_header()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs->buffer_pos += len;
|
||||
|
||||
// header ready
|
||||
if (cs->buffer_pos == 4) {
|
||||
memcpy(&cs->uh, cs->buffer->buf, 4);
|
||||
cs->buffer_pos = 0;
|
||||
uwsgi_cr_hook_read(cs, fr_recv_uwsgi_vars);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void fr_session_close(struct corerouter_session *cs) {
|
||||
struct fastrouter_session *fr = (struct fastrouter_session *) cs;
|
||||
if (fr->post_buf) {
|
||||
uwsgi_buffer_destroy(fr->post_buf);
|
||||
}
|
||||
}
|
||||
|
||||
void fastrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
cs->close = fr_session_close;
|
||||
// set the first hook
|
||||
uwsgi_cr_hook_read(cs, fr_recv_uwsgi_header);
|
||||
}
|
||||
|
||||
int fastrouter_init() {
|
||||
|
||||
ufr.cr.session_size = sizeof(struct fastrouter_session);
|
||||
ufr.cr.switch_events = uwsgi_fastrouter_switch_events;
|
||||
ufr.cr.alloc_session = fastrouter_alloc_session;
|
||||
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufr);
|
||||
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "../corerouter/cr.h"
|
||||
|
||||
#define FASTROUTER_STATUS_RECV_VARS 10
|
||||
#define FASTROUTER_STATUS_BUFFERING 11
|
||||
|
||||
struct uwsgi_fastrouter {
|
||||
|
||||
struct uwsgi_corerouter cr;
|
||||
|
||||
};
|
||||
|
||||
struct fastrouter_session {
|
||||
|
||||
struct corerouter_session crs;
|
||||
struct uwsgi_header uh;
|
||||
char buffer[UMAX16];
|
||||
};
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct uwsgi_corerouter *, struct corerouter_session *, int interesting_fd);
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
|
||||
|
||||
// here i use directly corerouter_session
|
||||
struct corerouter_session *fr_session = (struct corerouter_session *) data;
|
||||
|
||||
//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
|
||||
if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !fr_session->hostname_len) {
|
||||
fr_session->hostname = val;
|
||||
fr_session->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr_session->has_key) {
|
||||
fr_session->hostname = val;
|
||||
fr_session->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
|
||||
fr_session->has_key = 1;
|
||||
fr_session->hostname = val;
|
||||
fr_session->hostname_len = vallen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ufr.cr.post_buffering > 0) {
|
||||
if (!uwsgi_strncmp("CONTENT_LENGTH", 14, key, keylen)) {
|
||||
fr_session->post_cl = uwsgi_str_num(val, vallen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_session *cs, int interesting_fd) {
|
||||
|
||||
struct fastrouter_session *fr_session = (struct fastrouter_session *) cs;
|
||||
|
||||
socklen_t solen = sizeof(int);
|
||||
struct iovec iov[2];
|
||||
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} msg_control;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ssize_t len;
|
||||
char *post_tmp_buf[UMAX16];
|
||||
|
||||
switch (cs->status) {
|
||||
|
||||
case COREROUTER_STATUS_RECV_HDR:
|
||||
len = recv(cs->fd, (char *) (&fr_session->uh) + cs->h_pos, 4 - cs->h_pos, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, cs->fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
cs->h_pos += len;
|
||||
if (cs->h_pos == 4) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
|
||||
#endif
|
||||
cs->status = FASTROUTER_STATUS_RECV_VARS;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FASTROUTER_STATUS_RECV_VARS:
|
||||
|
||||
if (interesting_fd == -1) {
|
||||
goto choose_node;
|
||||
}
|
||||
|
||||
len = recv(cs->fd, fr_session->buffer + cs->pos, fr_session->uh.pktsize - cs->pos, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, cs->fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
cs->pos += len;
|
||||
if (cs->pos == fr_session->uh.pktsize) {
|
||||
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cs->hostname_len == 0) {
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// the mapper hook
|
||||
choose_node:
|
||||
if (ucr->mapper(ucr, cs))
|
||||
break;
|
||||
|
||||
// no address found
|
||||
if (!cs->instance_address_len) {
|
||||
// if fallback nodes are configured, trigger them
|
||||
if (ucr->fallback) {
|
||||
cs->instance_failed = 1;
|
||||
}
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ucr->post_buffering > 0 && cs->post_cl > ucr->post_buffering) {
|
||||
cs->status = FASTROUTER_STATUS_BUFFERING;
|
||||
cs->buf_file_name = uwsgi_tmpname(ucr->pb_base_dir, "uwsgiXXXXX");
|
||||
if (!cs->buf_file_name) {
|
||||
uwsgi_error("tempnam()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
cs->post_remains = cs->post_cl;
|
||||
|
||||
// 2 + UWSGI_POSTFILE + 2 + cs->buf_file_name
|
||||
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(cs->buf_file_name)) > UMAX16) {
|
||||
uwsgi_log("unable to buffer request body to file %s: not enough space\n", cs->buf_file_name);
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
|
||||
uint16_t bfn_len = strlen(cs->buf_file_name);
|
||||
*ptr++ = 14;
|
||||
*ptr++ = 0;
|
||||
memcpy(ptr, "UWSGI_POSTFILE", 14);
|
||||
ptr += 14;
|
||||
*ptr++ = (char) (bfn_len & 0xff);
|
||||
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
|
||||
memcpy(ptr, cs->buf_file_name, bfn_len);
|
||||
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
|
||||
|
||||
|
||||
cs->buf_file = fopen(cs->buf_file_name, "w");
|
||||
if (!cs->buf_file) {
|
||||
uwsgi_error_open(cs->buf_file_name);
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
cs->pass_fd = is_unix(cs->instance_address, cs->instance_address_len);
|
||||
|
||||
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
|
||||
|
||||
if (cs->instance_fd < 0) {
|
||||
cs->instance_failed = 1;
|
||||
cs->soopt = errno;
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
cs->status = COREROUTER_STATUS_CONNECTING;
|
||||
ucr->cr_table[cs->instance_fd] = cs;
|
||||
event_queue_add_fd_write(ucr->queue, cs->instance_fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case COREROUTER_STATUS_CONNECTING:
|
||||
|
||||
if (interesting_fd == cs->instance_fd) {
|
||||
|
||||
if (getsockopt(cs->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&cs->soopt), &solen) < 0) {
|
||||
uwsgi_error("getsockopt()");
|
||||
cs->instance_failed = 1;
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cs->soopt) {
|
||||
cs->instance_failed = 1;
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->uh.modifier1 = cs->modifier1;
|
||||
|
||||
iov[0].iov_base = &fr_session->uh;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = fr_session->buffer;
|
||||
iov[1].iov_len = fr_session->uh.pktsize;
|
||||
|
||||
// increment node requests counter
|
||||
if (cs->un)
|
||||
cs->un->requests++;
|
||||
|
||||
// fd passing: PERFORMANCE EXTREME BOOST !!!
|
||||
if (cs->pass_fd && !uwsgi.no_fd_passing) {
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &cs->fd, sizeof(int));
|
||||
|
||||
if (sendmsg(cs->instance_fd, &msg, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (writev(cs->instance_fd, iov, 2) < 0) {
|
||||
uwsgi_error("writev()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
event_queue_fd_write_to_read(ucr->queue, cs->instance_fd);
|
||||
cs->status = COREROUTER_STATUS_RESPONSE;
|
||||
}
|
||||
|
||||
break;
|
||||
case COREROUTER_STATUS_RESPONSE:
|
||||
|
||||
// data from instance
|
||||
if (interesting_fd == cs->instance_fd) {
|
||||
len = recv(cs->instance_fd, fr_session->buffer, UMAX16, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, cs->instance_fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(cs->fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
// update transfer statistics
|
||||
if (cs->un)
|
||||
cs->un->transferred += len;
|
||||
}
|
||||
// body from client
|
||||
else if (interesting_fd == cs->fd) {
|
||||
|
||||
//uwsgi_log("receiving body...\n");
|
||||
len = recv(cs->fd, fr_session->buffer, UMAX16, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, cs->fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
len = send(cs->instance_fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FASTROUTER_STATUS_BUFFERING:
|
||||
len = recv(cs->fd, post_tmp_buf, UMIN(UMAX16, cs->post_remains), 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(ucr->queue, cs->fd);
|
||||
#endif
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fwrite(post_tmp_buf, len, 1, cs->buf_file) != 1) {
|
||||
uwsgi_error("fwrite()");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
cs->post_remains -= len;
|
||||
|
||||
if (cs->post_remains == 0) {
|
||||
// close the buf_file ASAP
|
||||
fclose(cs->buf_file);
|
||||
cs->buf_file = NULL;
|
||||
|
||||
cs->pass_fd = is_unix(cs->instance_address, cs->instance_address_len);
|
||||
|
||||
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
|
||||
|
||||
if (cs->instance_fd < 0) {
|
||||
cs->instance_failed = 1;
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
}
|
||||
|
||||
cs->status = COREROUTER_STATUS_CONNECTING;
|
||||
ucr->cr_table[cs->instance_fd] = cs;
|
||||
event_queue_add_fd_write(ucr->queue, cs->instance_fd);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
// fallback to destroy !!!
|
||||
default:
|
||||
uwsgi_log("unknown event: closing session\n");
|
||||
corerouter_close_session(ucr, cs);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,4 @@ LIBS = []
|
||||
|
||||
REQUIRES = ['corerouter']
|
||||
|
||||
GCC_LIST = ['fastrouter', 'fr_events']
|
||||
GCC_LIST = ['fastrouter']
|
||||
|
||||
+234
-7
@@ -10,6 +10,10 @@ extern struct uwsgi_python up;
|
||||
if (ret) { Py_DECREF(ret); }\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
#define stop_the_watchers_and_clear stop_the_watchers\
|
||||
Py_DECREF(current); Py_DECREF(current_greenlet);\
|
||||
Py_DECREF(watcher);\
|
||||
Py_DECREF(timer);
|
||||
|
||||
|
||||
struct uwsgi_gevent {
|
||||
@@ -32,6 +36,9 @@ void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 30;
|
||||
}
|
||||
// set loop engine
|
||||
uwsgi.loop = "gevent";
|
||||
|
||||
@@ -173,9 +180,13 @@ edge:
|
||||
goto edge;
|
||||
}
|
||||
goto clear;
|
||||
|
||||
}
|
||||
|
||||
// on linux we need to set the socket in non-blocking as it is not inherited
|
||||
#ifdef __linux__
|
||||
uwsgi_socket_nb(wsgi_req->poll.fd);
|
||||
#endif
|
||||
|
||||
// hack to easily pass wsgi_req pointer to the greenlet
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
|
||||
|
||||
@@ -195,6 +206,210 @@ clear:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_buf, size_t remains, size_t *tmp_pos) {
|
||||
|
||||
/// create a watcher for reads
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) return -1;
|
||||
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) {
|
||||
Py_DECREF(watcher);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
while(remains) {
|
||||
|
||||
PyObject *ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
wsgi_req->switches++;
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (ret == timer) {
|
||||
stop_the_watchers_and_clear
|
||||
return 0;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
ssize_t rlen = read(wsgi_req->poll.fd, tmp_buf+*tmp_pos, remains);
|
||||
if (rlen <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
*tmp_pos += rlen;
|
||||
remains -= rlen;
|
||||
UWSGI_GET_GIL
|
||||
stop_the_watchers
|
||||
}
|
||||
|
||||
return *tmp_pos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_gevent_hook_input_readline(struct wsgi_request *wsgi_req, char *readline, size_t max_size) {
|
||||
ssize_t rlen = 0;
|
||||
|
||||
/// create a watcher for reads
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) return -1;
|
||||
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) {
|
||||
Py_DECREF(watcher);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
PyObject *ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
wsgi_req->switches++;
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (ret == timer) {
|
||||
stop_the_watchers_and_clear
|
||||
return 0;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
if (max_size > 0 && max_size < UWSGI_PY_READLINE_BUFSIZE) {
|
||||
rlen = read(wsgi_req->poll.fd, readline, max_size);
|
||||
}
|
||||
else {
|
||||
rlen = read(wsgi_req->poll.fd, readline, UWSGI_PY_READLINE_BUFSIZE);
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
stop_the_watchers_and_clear
|
||||
return rlen;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_gevent_nb_write(struct wsgi_request *wsgi_req, PyObject *str) {
|
||||
PyObject *ret;
|
||||
char *content = PyString_AsString(str);
|
||||
size_t content_len = PyString_Size(str);
|
||||
/// create a watcher for writes
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 2);
|
||||
if (!watcher) goto error;
|
||||
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) {
|
||||
Py_DECREF(watcher);
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
char *ptr = content;
|
||||
size_t remains = content_len;
|
||||
|
||||
// this is the main writing cycle, wait for writability and send...
|
||||
for(;;) {
|
||||
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
wsgi_req->switches++;
|
||||
if (!ret) {
|
||||
stop_the_watchers_and_clear
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (ret == timer) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// ok we can write a chunk to the socket
|
||||
UWSGI_RELEASE_GIL
|
||||
ssize_t len = write(wsgi_req->poll.fd, ptr, remains);
|
||||
UWSGI_GET_GIL
|
||||
if (len > 0) {
|
||||
ptr += len;
|
||||
remains -= len;
|
||||
wsgi_req->response_size += len;
|
||||
if (remains == 0) {
|
||||
break;
|
||||
}
|
||||
stop_the_watchers
|
||||
continue;
|
||||
}
|
||||
else if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
stop_the_watchers
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
stop_the_watchers_and_clear
|
||||
goto error;
|
||||
}
|
||||
|
||||
stop_the_watchers
|
||||
Py_DECREF(current); Py_DECREF(current_greenlet);
|
||||
Py_DECREF(watcher);
|
||||
Py_DECREF(timer);
|
||||
return ;
|
||||
|
||||
error:
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
wsgi_req->write_errors++;
|
||||
}
|
||||
|
||||
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
|
||||
|
||||
PyObject *ret;
|
||||
@@ -237,7 +452,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) goto clear1;
|
||||
|
||||
// a timer to implement timeoit (thanks Denis)
|
||||
// a timer to implement timeout (thanks Denis)
|
||||
timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) goto clear0;
|
||||
|
||||
@@ -246,6 +461,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
for(;;) {
|
||||
// wait for data in the socket
|
||||
ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
|
||||
wsgi_req->switches++;
|
||||
if (!ret) goto clear_and_stop;
|
||||
|
||||
// we can safely decref here as watcher and timer has got a +1 for start() method
|
||||
@@ -316,6 +532,13 @@ PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
|
||||
|
||||
void gil_gevent_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
}
|
||||
|
||||
void gil_gevent_release() {
|
||||
PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key));
|
||||
}
|
||||
|
||||
void gevent_loop() {
|
||||
|
||||
@@ -323,12 +546,15 @@ void gevent_loop() {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) {
|
||||
uwsgi_log("!!! Running gevent with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
|
||||
}
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ..then reset GIL subsystem as noop (gevent IO will take care of it...)
|
||||
up.gil_get = gil_fake_get;
|
||||
up.gil_release = gil_fake_release;
|
||||
up.gil_get = gil_gevent_get;
|
||||
up.gil_release = gil_gevent_release;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
@@ -338,6 +564,9 @@ void gevent_loop() {
|
||||
}
|
||||
|
||||
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
|
||||
up.hook_write_string = uwsgi_gevent_nb_write;
|
||||
up.hook_wsgi_input_read = uwsgi_gevent_hook_input_read;
|
||||
up.hook_wsgi_input_readline = uwsgi_gevent_hook_input_readline;
|
||||
|
||||
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
|
||||
if (!gevent_dict) uwsgi_pyexit;
|
||||
@@ -350,8 +579,6 @@ void gevent_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
|
||||
if (!ugevent.spawn) uwsgi_pyexit;
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void (*uwsgi_go_helper_post_fork_c)();
|
||||
void (*uwsgi_go_helper_post_init_c)();
|
||||
void * (*uwsgi_go_helper_env_new_c)(struct wsgi_request *);
|
||||
void (*uwsgi_go_helper_env_add_c)(void *, char *, int, char *, int);
|
||||
void (*uwsgi_go_helper_request_c)(void *, struct wsgi_request *);
|
||||
int (*uwsgi_go_helper_signal_handler_c)(int, void *);
|
||||
void (*uwsgi_go_helper_run_core_c)(int);
|
||||
|
||||
void uwsgi_go_post_fork() {
|
||||
uwsgi_go_helper_post_fork_c();
|
||||
}
|
||||
|
||||
void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_go_options[] = {
|
||||
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
#define uwsgi_go_get_symbol(x) x ## _c = dlsym(RTLD_DEFAULT, #x);\
|
||||
if (!x ## _c) {\
|
||||
uwsgi_log("[uwsgi-go] unable to load " #x " function\n"); exit(1);\
|
||||
}
|
||||
|
||||
int uwsgi_go_init() {
|
||||
|
||||
// build the functions table
|
||||
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_post_fork)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_post_init)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_env_new)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_env_add)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_request)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_signal_handler)
|
||||
uwsgi_go_get_symbol(uwsgi_go_helper_run_core)
|
||||
|
||||
// call PostInit()
|
||||
uwsgi_go_helper_post_init_c();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_go_request(struct wsgi_request *wsgi_req) {
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log("Invalid GO request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsgi_req->async_environ = uwsgi_go_helper_env_new_c(wsgi_req);
|
||||
int i;
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
uwsgi_go_helper_env_add_c(wsgi_req->async_environ, 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);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
uwsgi_go_helper_request_c(wsgi_req->async_environ, wsgi_req);
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
void uwsgi_go_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
log_request(wsgi_req);
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_go_signal_handler(uint8_t signum, void *handler) {
|
||||
return uwsgi_go_helper_signal_handler_c((int)signum, handler);
|
||||
}
|
||||
|
||||
void goroutines_loop() {
|
||||
int i;
|
||||
for (i = 1; i < uwsgi.async; i++) {
|
||||
uwsgi_go_helper_run_core_c(i);
|
||||
}
|
||||
simple_loop_run_int(0);
|
||||
}
|
||||
|
||||
void uwsgi_go_on_load() {
|
||||
uwsgi_register_loop("goroutines", goroutines_loop);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin go_plugin = {
|
||||
.name = "go",
|
||||
.modifier1 = 11,
|
||||
.request = uwsgi_go_request,
|
||||
.after_request = uwsgi_go_after_request,
|
||||
.post_fork = uwsgi_go_post_fork,
|
||||
.init = uwsgi_go_init,
|
||||
.signal_handler = uwsgi_go_signal_handler,
|
||||
.on_load = uwsgi_go_on_load,
|
||||
.options = uwsgi_go_options,
|
||||
};
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
uWSGI go integration package
|
||||
*/
|
||||
|
||||
package uwsgi
|
||||
|
||||
/*
|
||||
#include <uwsgi.h>
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// commodity functions to simulate argc/argv
|
||||
|
||||
static char ** uwsgi_go_helper_create_argv(int len) {
|
||||
return uwsgi_calloc(sizeof(char *) * len);
|
||||
}
|
||||
|
||||
static void uwsgi_go_helper_set_argv(char **argv, int pos, char *item) {
|
||||
argv[pos] = item;
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"os"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"unsafe"
|
||||
"strings"
|
||||
"strconv"
|
||||
"io"
|
||||
)
|
||||
|
||||
// this stores the modifier used by the go plugin (default 11)
|
||||
var uwsgi_modifier1 int = -1;
|
||||
// the following to objects are used to implement a sort of GC to avoid request environ and
|
||||
// signal handlers to be garbage collected
|
||||
var uwsgi_env_gc = make(map[*C.struct_wsgi_request](*map[string]string))
|
||||
var uwsgi_signals_gc = make([]*func(int), 256)
|
||||
|
||||
var uwsgi_default_handler func(http.ResponseWriter, *http.Request) = nil
|
||||
var uwsgi_post_fork_hook func() = nil
|
||||
var uwsgi_post_init_hook func() = nil
|
||||
|
||||
|
||||
/*
|
||||
|
||||
uWSGI api functions
|
||||
|
||||
*/
|
||||
|
||||
// raise a uWSGI signal
|
||||
func Signal(signum int) {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return
|
||||
}
|
||||
C.uwsgi_signal_send(C.uwsgi.signal_socket, C.uint8_t(signum))
|
||||
}
|
||||
|
||||
// set a user lock
|
||||
func Lock(num int) {
|
||||
C.uwsgi_user_lock(C.int(num));
|
||||
}
|
||||
|
||||
// unset a user lock
|
||||
func Unlock(num int) {
|
||||
C.uwsgi_user_unlock(C.int(num));
|
||||
}
|
||||
|
||||
// add a timer
|
||||
func AddTimer(signum int, seconds int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_add_timer(C.uint8_t(signum), C.int(seconds))) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// add a red black timer
|
||||
func AddRbTimer(signum int, seconds int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_signal_add_rb_timer(C.uint8_t(signum), C.int(seconds), C.int(0))) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// check if a signal is registered
|
||||
func SignalRegistered(signum int) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if int(C.uwsgi_signal_registered(C.uint8_t(signum))) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// register a signal
|
||||
func RegisterSignal(signum int, who string, handler func(int)) bool {
|
||||
if C.uwsgi.master_process == 0 {
|
||||
return false
|
||||
}
|
||||
if uwsgi_modifier1 == -1 {
|
||||
c_go := C.CString("go")
|
||||
defer C.free(unsafe.Pointer(c_go))
|
||||
uwsgi_modifier1 = int(C.uwsgi_plugin_modifier1(c_go))
|
||||
if uwsgi_modifier1 == -1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
c_who := C.CString(who)
|
||||
defer C.free(unsafe.Pointer(c_who))
|
||||
if int(C.uwsgi_register_signal(C.uint8_t(signum), c_who, unsafe.Pointer(&handler), C.uint8_t(uwsgi_modifier1))) == 0 {
|
||||
uwsgi_signals_gc[signum] = &handler
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// get an item from the cache
|
||||
func CacheGet(key string) []byte {
|
||||
if int(C.uwsgi_cache_enabled()) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
var vl C.uint64_t = C.uint64_t(0)
|
||||
|
||||
C.uwsgi_cache_rlock()
|
||||
|
||||
c_value := C.uwsgi_cache_get(k, C.uint16_t(kl), &vl)
|
||||
|
||||
var p []byte
|
||||
|
||||
if vl > 0 {
|
||||
p = C.GoBytes((unsafe.Pointer)(c_value), C.int(vl))
|
||||
} else {
|
||||
p = nil
|
||||
}
|
||||
|
||||
C.uwsgi_cache_rwunlock()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// remove an intem from the cache
|
||||
func CacheDel(key string) bool {
|
||||
if int(C.uwsgi_cache_enabled()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
|
||||
C.uwsgi_cache_wlock()
|
||||
|
||||
if int(C.uwsgi_cache_del(k, C.uint16_t(kl), C.uint64_t(0))) < 0 {
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return true
|
||||
}
|
||||
|
||||
// check if an item exists in the cache
|
||||
func CacheExists(key string) bool {
|
||||
if int(C.uwsgi_cache_enabled()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
|
||||
C.uwsgi_cache_rlock()
|
||||
|
||||
if int(C.uwsgi_cache_exists(k, C.uint16_t(kl))) > 0 {
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return false
|
||||
}
|
||||
|
||||
// put an item in the cache
|
||||
func CacheSetFlags(key string, p []byte, expires uint64, flags int) bool {
|
||||
|
||||
if int(C.uwsgi_cache_enabled()) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
k := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(k))
|
||||
kl := len(key)
|
||||
v := unsafe.Pointer(&p[0])
|
||||
vl := len(p)
|
||||
|
||||
C.uwsgi_cache_wlock()
|
||||
|
||||
if int(C.uwsgi_cache_set(k, C.uint16_t(kl), (*C.char)(v), C.uint64_t(vl), C.uint64_t(expires), C.uint16_t(flags))) < 0 {
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
C.uwsgi_cache_rwunlock();
|
||||
return true
|
||||
}
|
||||
|
||||
func CacheSet(key string, p []byte, expires uint64) bool {
|
||||
return CacheSetFlags(key, p, expires, 0);
|
||||
}
|
||||
|
||||
func CacheUpdate(key string, p []byte, expires uint64) bool {
|
||||
return CacheSetFlags(key, p, expires, 2);
|
||||
}
|
||||
|
||||
// get the current worker id
|
||||
func WorkerId() int {
|
||||
return int(C.uwsgi.mywid)
|
||||
}
|
||||
|
||||
// get the current mule id
|
||||
func MuleId() int {
|
||||
return int(C.uwsgi.muleid)
|
||||
}
|
||||
|
||||
// get the current logsize (if available)
|
||||
func LogSize() int64 {
|
||||
return int64(C.uwsgi.shared.logsize)
|
||||
}
|
||||
|
||||
func PostFork(hook func()) {
|
||||
uwsgi_post_fork_hook = hook
|
||||
}
|
||||
|
||||
func PostInit(hook func()) {
|
||||
uwsgi_post_init_hook = hook
|
||||
}
|
||||
|
||||
func RequestHandler(hook func(http.ResponseWriter, *http.Request)) {
|
||||
uwsgi_default_handler = hook
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
C -> go and go -> C bridges
|
||||
|
||||
*/
|
||||
|
||||
//export uwsgi_go_helper_post_fork
|
||||
func uwsgi_go_helper_post_fork() {
|
||||
if uwsgi_post_fork_hook != nil {
|
||||
uwsgi_post_fork_hook()
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_post_init
|
||||
func uwsgi_go_helper_post_init() {
|
||||
if uwsgi_post_init_hook != nil {
|
||||
uwsgi_post_init_hook()
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_env_new
|
||||
func uwsgi_go_helper_env_new(wsgi_req *C.struct_wsgi_request) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
// track env to avoid it being garbage collected...
|
||||
uwsgi_env_gc[wsgi_req] = &env
|
||||
return &env
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_env_add
|
||||
func uwsgi_go_helper_env_add(env *map[string]string, k *C.char, kl C.int, v *C.char, vl C.int) {
|
||||
var mk string = C.GoStringN(k, kl)
|
||||
var mv string = C.GoStringN(v, vl)
|
||||
(*env)[mk] = mv
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
http.* implementations
|
||||
|
||||
*/
|
||||
|
||||
type ResponseWriter struct {
|
||||
r *http.Request
|
||||
wsgi_req *C.struct_wsgi_request
|
||||
headers http.Header
|
||||
wroteHeader bool
|
||||
headers_chunk string
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Write(p []byte) (n int, err error) {
|
||||
if !w.wroteHeader {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
m := len(p)
|
||||
C.uwsgi_simple_response_write(w.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m))
|
||||
return m+n, err
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) WriteHeader(status int) {
|
||||
proto := "HTTP/1.0"
|
||||
if w.r.ProtoAtLeast(1, 1) {
|
||||
proto = "HTTP/1.1"
|
||||
}
|
||||
codestring := http.StatusText(status)
|
||||
w.headers_chunk += proto + " " + strconv.Itoa(status) + " " + codestring + "\r\n"
|
||||
C.uwsgi_simple_set_status(w.wsgi_req, C.int(status))
|
||||
if w.headers.Get("Content-Type") == "" {
|
||||
w.headers.Set("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
for k := range w.headers {
|
||||
for _, v := range w.headers[k] {
|
||||
v = strings.NewReplacer("\n", " ", "\r", " ").Replace(v)
|
||||
v = strings.TrimSpace(v)
|
||||
w.headers_chunk += k + ": " + v + "\r\n"
|
||||
C.uwsgi_simple_inc_headers(w.wsgi_req)
|
||||
}
|
||||
}
|
||||
w.headers_chunk += "\r\n"
|
||||
c_h_chunk := C.CString(w.headers_chunk)
|
||||
defer C.free(unsafe.Pointer(c_h_chunk))
|
||||
C.uwsgi_simple_response_write_header(w.wsgi_req, c_h_chunk, C.size_t(len(w.headers_chunk)))
|
||||
w.wroteHeader = true
|
||||
}
|
||||
|
||||
func (w *ResponseWriter) Header() http.Header {
|
||||
return w.headers
|
||||
}
|
||||
|
||||
|
||||
type BodyReader struct {
|
||||
wsgi_req *C.struct_wsgi_request
|
||||
}
|
||||
|
||||
// there is no close in request body
|
||||
func (br *BodyReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (br *BodyReader) Read(p []byte) (n int, err error) {
|
||||
m := len(p)
|
||||
rlen := int(C.uwsgi_simple_request_read(br.wsgi_req, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(m)))
|
||||
if rlen < 0 {
|
||||
err = io.ErrUnexpectedEOF
|
||||
rlen = 0
|
||||
} else if rlen == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
return rlen, err
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_request
|
||||
func uwsgi_go_helper_request(env *map[string]string, wsgi_req *C.struct_wsgi_request) {
|
||||
httpReq, err := cgi.RequestFromMap(*env)
|
||||
if err != nil {
|
||||
} else {
|
||||
httpReq.Body = &BodyReader{wsgi_req}
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false, ""}
|
||||
if uwsgi_default_handler != nil {
|
||||
uwsgi_default_handler(&w, httpReq)
|
||||
} else {
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_signal_handler
|
||||
func uwsgi_go_helper_signal_handler(signum int, handler *func(int)) int {
|
||||
(*handler)(signum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//export uwsgi_go_helper_run_core
|
||||
func uwsgi_go_helper_run_core(core_id int) {
|
||||
go C.simple_loop_run_int(C.int(core_id))
|
||||
}
|
||||
|
||||
/*
|
||||
the main function, running the uWSGI server via libuwsgi.so
|
||||
*/
|
||||
func Run() {
|
||||
argc := len(os.Args)
|
||||
argv := C.uwsgi_go_helper_create_argv(C.int(argc))
|
||||
for i, s := range os.Args {
|
||||
C.uwsgi_go_helper_set_argv(argv, C.int(i), C.CString(s))
|
||||
}
|
||||
C.uwsgi_init(C.int(argc), argv, nil)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
NAME='go'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['go_plugin']
|
||||
|
||||
def post_build(config):
|
||||
os.environ['GOPATH'] = 'plugins/go'
|
||||
cflags = ['-I'+os.getcwd()]
|
||||
for c in config.cflags:
|
||||
if not c.startswith('-DUWSGI_BUILD_DATE') and not c.startswith('-DUWSGI_CFLAGS'):
|
||||
cflags.append(c)
|
||||
|
||||
cflags.append('-Wno-implicit-function-declaration')
|
||||
cflags.append('-Wno-implicit-int')
|
||||
cflags.append('-Wno-unused-function')
|
||||
cflags.append('-Wno-unused-variable')
|
||||
|
||||
os.environ['CGO_CFLAGS'] = ' '.join(cflags).replace('\\"', '')
|
||||
base = os.path.dirname(config.get('bin_name'))
|
||||
if not base:
|
||||
base = "."
|
||||
os.environ['CGO_LDFLAGS'] = '-L' + base + ' -L'+os.getcwd() + ' -luwsgi'
|
||||
if os.system("go install uwsgi") != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi go module available in $GOPATH %s/plugins/go ***" % os.getcwd())
|
||||
+782
-745
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
ul->fd = open(ul->arg, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (ul->fd >= 0) {
|
||||
ul->configured = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ul->fd >= 0) {
|
||||
return write(ul->fd, message, len);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_file_logger_register() {
|
||||
uwsgi_register_logger("file", uwsgi_file_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logfile_plugin = {
|
||||
|
||||
.name = "logfile",
|
||||
.on_load = uwsgi_file_logger_register,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logfile'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logfile']
|
||||
+27
-60
@@ -13,6 +13,8 @@ struct uwsgi_lua {
|
||||
} ulua;
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
#define response_append(x, y) if (uwsgi_buffer_append(status_and_headers, x, y)) { uwsgi_buffer_destroy(status_and_headers); lua_pushvalue(L, -1); goto clear;}
|
||||
#define response_append_header(x, y) if (uwsgi_buffer_append(status_and_headers, x, y)) { uwsgi_buffer_destroy(status_and_headers); lua_pop(L, 2); lua_pushvalue(L, -1); goto clear;}
|
||||
|
||||
struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
@@ -391,7 +393,6 @@ void uwsgi_lua_app() {
|
||||
int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
int raw;
|
||||
const char *http;
|
||||
size_t slen;
|
||||
ssize_t rlen;
|
||||
@@ -467,38 +468,24 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
//uwsgi_log("%d %s %s %s\n",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1)));
|
||||
|
||||
raw = 0;
|
||||
// this buffer will contains the whole headers (+status)
|
||||
struct uwsgi_buffer *status_and_headers = uwsgi_buffer_new(4096);
|
||||
|
||||
// send status
|
||||
if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
|
||||
http = lua_tolstring(L, -3, &slen);
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len)) != wsgi_req->protocol_len) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, " ", 1)) != 1) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
// a performance hack
|
||||
ptrbuf = (char *) http;
|
||||
ptrbuf[3] = 0;
|
||||
wsgi_req->status = atoi(ptrbuf);
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
|
||||
response_append(wsgi_req->protocol, wsgi_req->protocol_len);
|
||||
response_append(" ", 1);
|
||||
response_append((char *) http, slen);
|
||||
response_append("\r\n", 2);
|
||||
|
||||
// transform the first 3 bytes of the string in a number
|
||||
wsgi_req->status = uwsgi_str3_num((char *)http);
|
||||
}
|
||||
else {
|
||||
raw = 1;
|
||||
wsgi_req->status = -1;
|
||||
uwsgi_log("[uwsgi-lua] invalid response status !!!\n");
|
||||
// let's continue
|
||||
}
|
||||
|
||||
// send headers
|
||||
@@ -506,42 +493,23 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -3) != 0) {
|
||||
http = lua_tolstring(L, -2, &slen);
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, ": ", 2)) != 2) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
|
||||
response_append_header((char *)http, slen);
|
||||
response_append_header(": ", 2);
|
||||
|
||||
http = lua_tolstring(L, -1, &slen);
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, (char *)http, slen)) != (ssize_t) slen) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pop(L, 2);
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
|
||||
response_append_header((char *)http, slen);
|
||||
response_append_header("\r\n", 2);
|
||||
|
||||
lua_pop(L, 1);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
|
||||
if (!raw) {
|
||||
if ( (rlen = wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2)) != 2) {
|
||||
lua_pushvalue(L, -1);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->headers_size += rlen;
|
||||
}
|
||||
response_append("\r\n", 2);
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, status_and_headers->buf, status_and_headers->pos);
|
||||
uwsgi_buffer_destroy(status_and_headers);
|
||||
|
||||
// send body with coroutine
|
||||
lua_pushvalue(L, -1);
|
||||
@@ -566,7 +534,6 @@ int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
lua_pop(L, 4);
|
||||
clear2:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import os,sys
|
||||
try:
|
||||
LUALIB = os.environ['UWSGICONFIG_LUALIB']
|
||||
except:
|
||||
LUALIB = 'lua'
|
||||
LUALIB = 'lua5.1'
|
||||
|
||||
try:
|
||||
LUAINC = os.environ['UWSGICONFIG_LUAINC']
|
||||
|
||||
@@ -18,6 +18,7 @@ static sapi_module_struct uwsgi_sapi_module;
|
||||
struct uwsgi_php {
|
||||
struct uwsgi_string_list *allowed_docroot;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *allowed_scripts;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *set;
|
||||
struct uwsgi_string_list *append_config;
|
||||
@@ -45,6 +46,7 @@ struct uwsgi_option uwsgi_php_options[] = {
|
||||
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
|
||||
{"php-allowed-docroot", required_argument, 0, "list the allowed document roots", uwsgi_opt_add_string_list, &uphp.allowed_docroot, 0},
|
||||
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
|
||||
{"php-allowed-script", required_argument, 0, "list the allowed php scripts (require absolute path)", uwsgi_opt_add_string_list, &uphp.allowed_scripts, 0},
|
||||
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
|
||||
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
|
||||
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
|
||||
@@ -208,7 +210,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
{
|
||||
uint read_bytes = 0;
|
||||
size_t len;
|
||||
ssize_t len;
|
||||
int fd = -1;
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
@@ -874,6 +876,22 @@ secure2:
|
||||
wsgi_req->file = real_filename;
|
||||
wsgi_req->file_len = strlen(wsgi_req->file);
|
||||
|
||||
if (uphp.allowed_scripts) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_scripts;
|
||||
while(usl) {
|
||||
if (!uwsgi_strncmp(wsgi_req->file, wsgi_req->file_len, usl->value, usl->len)) {
|
||||
goto secure3;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_php_403(wsgi_req);
|
||||
uwsgi_log("PHP security error: %s is not an allowed script\n", real_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secure3:
|
||||
|
||||
|
||||
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
|
||||
}
|
||||
|
||||
@@ -370,9 +370,9 @@ int uwsgi_perl_init(){
|
||||
}
|
||||
|
||||
#ifdef PERL_VERSION_STRING
|
||||
uwsgi_log("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
|
||||
uwsgi_log_initial("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
|
||||
#else
|
||||
uwsgi_log("initialized Perl main interpreter at %p\n", uperl.main[0]);
|
||||
uwsgi_log_initial("initialized Perl main interpreter at %p\n", uperl.main[0]);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -13,9 +13,7 @@ extern struct uwsgi_python up;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
|
||||
@@ -331,10 +329,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
#endif
|
||||
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
// prepare sendfile() for WSGI app
|
||||
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
wi->eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL);
|
||||
|
||||
@@ -9,6 +9,12 @@ extern struct http_status_codes hsc[];
|
||||
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
void python_simple_hook_write_string(struct wsgi_request *wsgi_req, PyObject *str) {
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(str), PyString_Size(str));
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
|
||||
|
||||
int i;
|
||||
@@ -71,6 +77,8 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"pyhome", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
|
||||
{"py-programname", required_argument, 0, "set python program name", uwsgi_opt_set_str, &up.programname, 0},
|
||||
{"py-program-name", required_argument, 0, "set python program name", uwsgi_opt_set_str, &up.programname, 0},
|
||||
|
||||
{"pythonpath", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
|
||||
{"python-path", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
|
||||
@@ -169,6 +177,16 @@ int uwsgi_python_init() {
|
||||
|
||||
if (up.home != NULL) {
|
||||
#ifdef PYTHREE
|
||||
// check for PEP 405 virtualenv (starting from python 3.3)
|
||||
char *pep405_env = uwsgi_concat2(up.home, "/pyvenv.cfg");
|
||||
if (uwsgi_file_exists(pep405_env)) {
|
||||
uwsgi_log("PEP 405 virtualenv detected: %s\n", up.home);
|
||||
free(pep405_env);
|
||||
goto pep405;
|
||||
}
|
||||
free(pep405_env);
|
||||
|
||||
// build the PYTHONHOME wchar path
|
||||
wchar_t *wpyhome;
|
||||
size_t len = strlen(up.home) + 1;
|
||||
wpyhome = uwsgi_calloc(sizeof(wchar_t) * len );
|
||||
@@ -180,19 +198,30 @@ int uwsgi_python_init() {
|
||||
Py_SetPythonHome(wpyhome);
|
||||
// do not free this memory !!!
|
||||
//free(wpyhome);
|
||||
pep405:
|
||||
#else
|
||||
Py_SetPythonHome(up.home);
|
||||
#endif
|
||||
uwsgi_log("Set PythonHome to %s\n", up.home);
|
||||
}
|
||||
|
||||
char *program_name = up.programname;
|
||||
if (!program_name) {
|
||||
program_name = uwsgi.binary_path;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t pname[6];
|
||||
mbstowcs(pname, "uWSGI", 6);
|
||||
if (!up.programname) {
|
||||
if (up.home) {
|
||||
program_name = uwsgi_concat2(up.home, "/bin/python");
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(program_name)+1));
|
||||
mbstowcs(pname, program_name, strlen(program_name)+1);
|
||||
Py_SetProgramName(pname);
|
||||
#else
|
||||
Py_SetProgramName("uWSGI");
|
||||
Py_SetProgramName(program_name);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -203,12 +232,16 @@ int uwsgi_python_init() {
|
||||
Py_Initialize();
|
||||
|
||||
if (!uwsgi.has_threads) {
|
||||
uwsgi_log("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
|
||||
uwsgi_log_initial("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
|
||||
}
|
||||
|
||||
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
|
||||
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
|
||||
|
||||
up.hook_write_string = python_simple_hook_write_string;
|
||||
up.hook_wsgi_input_read = uwsgi_python_hook_simple_input_read;
|
||||
up.hook_wsgi_input_readline = uwsgi_python_hook_simple_input_readline;
|
||||
|
||||
up.main_thread = PyThreadState_Get();
|
||||
|
||||
// by default set a fake GIL (little impact on performance)
|
||||
@@ -279,8 +312,9 @@ realstuff:
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi.has_threads)
|
||||
PyGILState_Ensure();
|
||||
// always call it
|
||||
PyGILState_Ensure();
|
||||
|
||||
// no need to worry about freeing memory
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
@@ -1306,6 +1340,7 @@ int uwsgi_check_python_mtime(PyObject *times_dict, char *filename) {
|
||||
}
|
||||
|
||||
PyObject *uwsgi_python_setup_thread(char *name) {
|
||||
|
||||
// block signals on this thread
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
|
||||
@@ -28,10 +28,12 @@ char *uwsgi_python_get_thread_name(PyObject *thread_id) {
|
||||
PyObject *thread_name = PyObject_GetAttrString(threads_list_next, "name");
|
||||
if (!thread_name) goto clear2;
|
||||
char *name = PyString_AsString(thread_name);
|
||||
Py_DECREF(threads_list_next);
|
||||
Py_DECREF(threads_list_iter);
|
||||
Py_DECREF(threads_list);
|
||||
return name;
|
||||
}
|
||||
Py_DECREF(threads_list_next);
|
||||
threads_list_next = PyIter_Next(threads_list_iter);
|
||||
}
|
||||
|
||||
@@ -110,22 +112,23 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
|
||||
PyObject *arg_tuple = PyTuple_New(1);
|
||||
PyTuple_SetItem(arg_tuple, 0, stack);
|
||||
Py_INCREF(stack);
|
||||
PyObject *stacktrace = PyEval_CallObject( extract_stack, arg_tuple);
|
||||
Py_DECREF(arg_tuple);
|
||||
if (!stacktrace) goto next2;
|
||||
|
||||
PyObject *stacktrace_iter = PyObject_GetIter(stacktrace);
|
||||
if (!stacktrace_iter) goto next2;
|
||||
if (!stacktrace_iter) { Py_DECREF(stacktrace); goto next2;}
|
||||
|
||||
PyObject *st_items = PyIter_Next(stacktrace_iter);
|
||||
// we have the first traceback item
|
||||
while(st_items) {
|
||||
PyObject *st_filename = PyTuple_GetItem(st_items, 0);
|
||||
if (!st_filename) goto next;
|
||||
if (!st_filename) { Py_DECREF(st_items); goto next; }
|
||||
PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
|
||||
if (!st_lineno) goto next;
|
||||
if (!st_lineno) {Py_DECREF(st_items); goto next;}
|
||||
PyObject *st_name = PyTuple_GetItem(st_items, 2);
|
||||
if (!st_name) goto next;
|
||||
if (!st_name) {Py_DECREF(st_items); goto next;}
|
||||
|
||||
PyObject *st_line = PyTuple_GetItem(st_items, 3);
|
||||
|
||||
@@ -178,6 +181,7 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
|
||||
// free the line_no
|
||||
free(iov[5].iov_base);
|
||||
Py_DECREF(st_items);
|
||||
st_items = PyIter_Next(stacktrace_iter);
|
||||
}
|
||||
if (write(client_fd, "\n", 1) < 0) {
|
||||
@@ -185,10 +189,13 @@ void *uwsgi_python_tracebacker_thread(void *foobar) {
|
||||
}
|
||||
next:
|
||||
Py_DECREF(stacktrace_iter);
|
||||
Py_DECREF(stacktrace);
|
||||
next2:
|
||||
Py_DECREF(frame);
|
||||
frame = PyIter_Next(frames_iter);
|
||||
}
|
||||
|
||||
Py_DECREF(frames_iter);
|
||||
end4:
|
||||
Py_DECREF(frames_ret);
|
||||
end3:
|
||||
|
||||
+267
-13
@@ -10,7 +10,7 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
int wait_for_specific_signal = 0;
|
||||
uint8_t uwsgi_signal = 0;
|
||||
uint8_t received_signal;
|
||||
int received_signal;
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
@@ -30,6 +30,11 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
|
||||
if (received_signal < 0) {
|
||||
UWSGI_GET_GIL;
|
||||
return PyErr_Format(PyExc_SystemError, "error waiting for signal");
|
||||
}
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
@@ -778,7 +783,36 @@ PyObject *py_uwsgi_send(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_offload_transfer(PyObject * self, PyObject * args) {
|
||||
size_t len = 0;
|
||||
char *filename = NULL;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s|i:offload_transfer", &filename, &len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!wsgi_req->socket->can_offload) {
|
||||
return PyErr_Format(PyExc_ValueError, "The current socket does not support offloading");
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (uwsgi_python_do_send_headers(wsgi_req)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to send headers before offload transfer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_offload_request_do(wsgi_req, filename, len)) {
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_ValueError, "Unable to offload the request");
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyString_FromString("");
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *what;
|
||||
@@ -870,7 +904,6 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
|
||||
@@ -3171,9 +3204,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"rpc", py_uwsgi_rpc, METH_VARARGS, ""},
|
||||
{"rpc_list", py_uwsgi_rpc_list, METH_VARARGS, ""},
|
||||
{"call", py_uwsgi_call, METH_VARARGS, ""},
|
||||
#ifdef UWSGI_SENDFILE
|
||||
{"sendfile", py_uwsgi_advanced_sendfile, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"offload_transfer", py_uwsgi_offload_transfer, METH_VARARGS, ""},
|
||||
{"set_warning_message", py_uwsgi_warning, METH_VARARGS, ""},
|
||||
{"mem", py_uwsgi_mem, METH_VARARGS, ""},
|
||||
{"has_hook", py_uwsgi_has_hook, METH_VARARGS, ""},
|
||||
@@ -3892,7 +3924,7 @@ void init_uwsgi_module_sharedarea(PyObject * current_uwsgi_module) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SNMP
|
||||
PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
|
||||
PyObject *py_snmp_set_counter32(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
@@ -3904,9 +3936,15 @@ PyObject *py_snmp_counter32(PyObject * self, PyObject * args) {
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
@@ -3916,7 +3954,7 @@ clear:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
|
||||
PyObject *py_snmp_set_counter64(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 0;
|
||||
@@ -3928,9 +3966,15 @@ PyObject *py_snmp_counter64(PyObject * self, PyObject * args) {
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
@@ -3940,7 +3984,7 @@ clear:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
|
||||
PyObject *py_snmp_set_gauge(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 0;
|
||||
@@ -3952,9 +3996,15 @@ PyObject *py_snmp_gauge(PyObject * self, PyObject * args) {
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
@@ -3964,7 +4014,205 @@ clear:
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_community(PyObject * self, PyObject * args) {
|
||||
PyObject *py_snmp_incr_counter32(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_counter32", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_counter32", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val + oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_incr_counter64(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_counter64", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_counter64", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val + oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_incr_gauge(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_gauge", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_gauge", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val + oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_decr_counter32(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint32_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_counter32", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_counter32", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER32;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val - oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_decr_counter64(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_counter64", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_counter64", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_COUNTER64;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val - oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_decr_gauge(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t oid_num;
|
||||
uint64_t oid_val = 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "bI:snmp_incr_gauge", &oid_num, &oid_val)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "b:snmp_incr_gauge", &oid_num)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (oid_num > 100 || oid_num < 1)
|
||||
goto clear;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.snmp_lock);
|
||||
|
||||
uwsgi.shared->snmp_value[oid_num - 1].type = SNMP_GAUGE;
|
||||
uwsgi.shared->snmp_value[oid_num - 1].val = uwsgi.shared->snmp_value[oid_num - 1].val - oid_val;
|
||||
|
||||
uwsgi_rwunlock(uwsgi.snmp_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear:
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_snmp_set_community(PyObject * self, PyObject * args) {
|
||||
|
||||
char *snmp_community;
|
||||
|
||||
@@ -3987,10 +4235,16 @@ PyObject *py_snmp_community(PyObject * self, PyObject * args) {
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_snmp_methods[] = {
|
||||
{"snmp_set_counter32", py_snmp_counter32, METH_VARARGS, ""},
|
||||
{"snmp_set_counter64", py_snmp_counter64, METH_VARARGS, ""},
|
||||
{"snmp_set_gauge", py_snmp_gauge, METH_VARARGS, ""},
|
||||
{"snmp_set_community", py_snmp_community, METH_VARARGS, ""},
|
||||
{"snmp_set_counter32", py_snmp_set_counter32, METH_VARARGS, ""},
|
||||
{"snmp_set_counter64", py_snmp_set_counter64, METH_VARARGS, ""},
|
||||
{"snmp_set_gauge", py_snmp_set_gauge, METH_VARARGS, ""},
|
||||
{"snmp_incr_counter32", py_snmp_incr_counter32, METH_VARARGS, ""},
|
||||
{"snmp_incr_counter64", py_snmp_incr_counter64, METH_VARARGS, ""},
|
||||
{"snmp_incr_gauge", py_snmp_incr_gauge, METH_VARARGS, ""},
|
||||
{"snmp_decr_counter32", py_snmp_decr_counter32, METH_VARARGS, ""},
|
||||
{"snmp_decr_counter64", py_snmp_decr_counter64, METH_VARARGS, ""},
|
||||
{"snmp_decr_gauge", py_snmp_decr_gauge, METH_VARARGS, ""},
|
||||
{"snmp_set_community", py_snmp_set_community, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -186,6 +186,11 @@ struct uwsgi_python {
|
||||
char *pyrun;
|
||||
int start_response_nodelay;
|
||||
|
||||
void (*hook_write_string)(struct wsgi_request *, PyObject *);
|
||||
ssize_t (*hook_wsgi_input_read)(struct wsgi_request *, char *, size_t, size_t *);
|
||||
ssize_t (*hook_wsgi_input_readline)(struct wsgi_request *, char *, size_t);
|
||||
|
||||
char *programname;
|
||||
};
|
||||
|
||||
|
||||
@@ -210,9 +215,7 @@ int manage_python_response(struct wsgi_request *);
|
||||
int uwsgi_python_call(struct wsgi_request *, PyObject *, PyObject *);
|
||||
PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_write(PyObject *, PyObject *);
|
||||
PyObject *py_uwsgi_spit(PyObject *, PyObject *);
|
||||
@@ -278,6 +281,9 @@ int uwsgi_python_do_send_headers(struct wsgi_request *);
|
||||
void *uwsgi_python_tracebacker_thread(void *);
|
||||
PyObject *uwsgi_python_setup_thread(char *);
|
||||
|
||||
ssize_t uwsgi_python_hook_simple_input_read(struct wsgi_request *, char *, size_t, size_t *);
|
||||
ssize_t uwsgi_python_hook_simple_input_readline(struct wsgi_request *, char *, size_t);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,24 @@ PyObject *uwsgi_Input_iter(PyObject *self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_python_hook_simple_input_readline(struct wsgi_request *wsgi_req, char *readline, size_t max_size) {
|
||||
ssize_t rlen = 0;
|
||||
UWSGI_RELEASE_GIL;
|
||||
if (uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_size > 0 && max_size < UWSGI_PY_READLINE_BUFSIZE) {
|
||||
rlen = read(wsgi_req->poll.fd, readline, max_size);
|
||||
}
|
||||
else {
|
||||
rlen = read(wsgi_req->poll.fd, readline, UWSGI_PY_READLINE_BUFSIZE);
|
||||
}
|
||||
UWSGI_GET_GIL;
|
||||
return rlen;
|
||||
}
|
||||
|
||||
PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
|
||||
size_t i;
|
||||
ssize_t rlen;
|
||||
@@ -40,29 +58,18 @@ PyObject *uwsgi_Input_getline(uwsgi_Input *self) {
|
||||
}
|
||||
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
if (uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
rlen = up.hook_wsgi_input_readline(wsgi_req, self->readline, self->readline_max_size);
|
||||
if (rlen < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "error reading for wsgi.input data (readline/getline)");
|
||||
}
|
||||
else if (rlen == 0) {
|
||||
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data (readline/getline)");
|
||||
}
|
||||
|
||||
if (self->readline_max_size > 0 && self->readline_max_size < UWSGI_PY_READLINE_BUFSIZE) {
|
||||
rlen = read(wsgi_req->poll.fd, self->readline, self->readline_max_size);
|
||||
}
|
||||
else {
|
||||
rlen = read(wsgi_req->poll.fd, self->readline, UWSGI_PY_READLINE_BUFSIZE);
|
||||
}
|
||||
if (rlen <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data (readline/getline)");
|
||||
}
|
||||
|
||||
self->readline_size = rlen;
|
||||
self->readline_pos = 0;
|
||||
self->pos += rlen;
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
for(i=0;i<(size_t)rlen;i++) {
|
||||
if (self->readline[i] == '\n') {
|
||||
res = PyString_FromStringAndSize(self->readline, i+1);
|
||||
@@ -91,11 +98,35 @@ static void uwsgi_Input_free(uwsgi_Input *self) {
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
ssize_t uwsgi_python_hook_simple_input_read(struct wsgi_request *wsgi_req, char *tmp_buf, size_t remains, size_t *tmp_pos) {
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
while(remains) {
|
||||
if (uwsgi_waitfd(wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t rlen = read(wsgi_req->poll.fd, tmp_buf+*tmp_pos, remains);
|
||||
if (rlen <= 0) {
|
||||
UWSGI_GET_GIL
|
||||
return -1;
|
||||
}
|
||||
*tmp_pos += rlen;
|
||||
remains -= rlen;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
return *tmp_pos;
|
||||
|
||||
}
|
||||
|
||||
static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
|
||||
|
||||
long len = 0;
|
||||
size_t remains, tmp_pos = 0;
|
||||
ssize_t rlen;
|
||||
size_t remains;
|
||||
size_t tmp_pos = 0;
|
||||
char *tmp_buf;
|
||||
PyObject *res;
|
||||
|
||||
@@ -144,28 +175,18 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
|
||||
return res;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
tmp_buf = uwsgi_malloc(remains);
|
||||
|
||||
while(remains) {
|
||||
if (uwsgi_waitfd(self->wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
|
||||
free(tmp_buf);
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains + tmp_pos, (unsigned long long) tmp_pos);
|
||||
}
|
||||
|
||||
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
|
||||
if (rlen <= 0) {
|
||||
free(tmp_buf);
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains + tmp_pos, (unsigned long long) tmp_pos);
|
||||
}
|
||||
tmp_pos += rlen;
|
||||
remains -= rlen;
|
||||
ssize_t rlen = up.hook_wsgi_input_read(self->wsgi_req, tmp_buf, remains, &tmp_pos);
|
||||
if (rlen < 0) {
|
||||
free(tmp_buf);
|
||||
return PyErr_Format(PyExc_IOError, "error reading for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) (remains + tmp_pos), (unsigned long long) tmp_pos);
|
||||
}
|
||||
else if (tmp_pos == 0) {
|
||||
free(tmp_buf);
|
||||
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) (remains + tmp_pos), (unsigned long long) tmp_pos);
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
self->pos += tmp_pos;
|
||||
res = PyString_FromStringAndSize(tmp_buf, tmp_pos);
|
||||
free(tmp_buf);
|
||||
@@ -395,7 +416,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( (wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 0)) == -1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
if (uwsgi.no_default_app) {
|
||||
@@ -433,6 +453,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
up.swap_ts(wsgi_req, wi);
|
||||
|
||||
|
||||
if (wi->chdir[0] != 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -452,8 +473,10 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
// create WSGI environ
|
||||
wsgi_req->async_environ = up.wsgi_env_create(wsgi_req, wi);
|
||||
|
||||
|
||||
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
|
||||
|
||||
|
||||
if (wsgi_req->async_result) {
|
||||
|
||||
|
||||
@@ -555,7 +578,6 @@ void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
@@ -580,7 +602,6 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
|
||||
Py_INCREF((PyObject *) wsgi_req->sendfile_obj);
|
||||
return (PyObject *) wsgi_req->sendfile_obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
void threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
|
||||
@@ -35,6 +35,13 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->headers = NULL;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (wsgi_req->gc_tracker) {
|
||||
Py_DECREF((PyObject *)wsgi_req->gc_tracker);
|
||||
wsgi_req->gc_tracker = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// this must be done before headers management
|
||||
if (PyTuple_Size(args) > 2) {
|
||||
exc_info = PyTuple_GetItem(args, 2);
|
||||
@@ -72,6 +79,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_TypeError, "http status must be a string");
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
// this list maintains reference to encoded strings.. ugly hack, i know, but it works...
|
||||
wsgi_req->gc_tracker = (void *) PyList_New(0);
|
||||
#endif
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
|
||||
base = 4;
|
||||
@@ -89,7 +100,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[1].iov_len = 1;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[2].iov_base = PyBytes_AsString(head);
|
||||
@@ -110,7 +124,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[0].iov_len = 8;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(head);
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[1].iov_base = PyBytes_AsString(head);
|
||||
@@ -181,7 +198,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_key));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_key);
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[j].iov_base = PyBytes_AsString(h_key);
|
||||
@@ -195,7 +215,10 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
|
||||
#ifdef PYTHREE
|
||||
if (self != Py_None) {
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
|
||||
PyObject *zero = PyUnicode_AsASCIIString(h_value);
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(zero);
|
||||
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(h_value);
|
||||
@@ -288,6 +311,13 @@ int uwsgi_python_do_send_headers(struct wsgi_request *wsgi_req) {
|
||||
wsgi_req->headers = NULL;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (wsgi_req->gc_tracker) {
|
||||
Py_DECREF((PyObject *)wsgi_req->gc_tracker);
|
||||
wsgi_req->gc_tracker = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance && !uwsgi.disable_write_exception) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return -1;
|
||||
|
||||
@@ -6,6 +6,7 @@ extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
|
||||
PyObject *zero;
|
||||
int i;
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
@@ -69,9 +70,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
@@ -157,22 +156,17 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
#ifdef UWSGI_SENDFILE
|
||||
ssize_t sf_len = 0;
|
||||
#endif
|
||||
|
||||
// return or yield ?
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
char *content = PyString_AsString(wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size(wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size((PyObject *)wsgi_req->async_result);
|
||||
if (content_len > 0 && !wsgi_req->headers_sent) {
|
||||
if (uwsgi_python_do_send_headers(wsgi_req)) {
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
up.hook_write_string(wsgi_req, (PyObject *) wsgi_req->async_result);
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
@@ -180,7 +174,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
#ifdef __FreeBSD__
|
||||
if ( ((wsgi_req->sendfile_obj == wsgi_req->async_result) || ( wsgi_req->sendfile_fd_size > 0 && wsgi_req->response_size < wsgi_req->sendfile_fd_size)) && wsgi_req->sendfile_fd != -1) {
|
||||
#else
|
||||
@@ -202,8 +195,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
#endif
|
||||
goto clear;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
@@ -241,16 +232,13 @@ exception:
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
if (content_len > 0 && !wsgi_req->headers_sent) {
|
||||
if (uwsgi_python_do_send_headers(wsgi_req)) {
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
up.hook_write_string(wsgi_req, pychunk);
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
Py_DECREF(pychunk);
|
||||
@@ -258,7 +246,6 @@ exception:
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
|
||||
// send the headers if not already sent
|
||||
if (!wsgi_req->headers_sent && wsgi_req->headers_hvec > 0) {
|
||||
@@ -268,7 +255,6 @@ exception:
|
||||
if (sf_len < 1) goto clear;
|
||||
wsgi_req->response_size += sf_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
|
||||
+13
-2
@@ -488,6 +488,7 @@ VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
Check_Type(arg1, T_FIXNUM);
|
||||
@@ -522,6 +523,7 @@ VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -535,6 +537,7 @@ VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
Check_Type(arg, T_FIXNUM);
|
||||
@@ -548,6 +551,7 @@ VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
VALUE uwsgi_ruby_masterpid(VALUE *class) {
|
||||
|
||||
@@ -573,7 +577,7 @@ 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;
|
||||
int received_signal;
|
||||
|
||||
wsgi_req->signal_received = -1;
|
||||
|
||||
@@ -590,7 +594,12 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
|
||||
received_signal = uwsgi_signal_wait(-1);
|
||||
}
|
||||
|
||||
wsgi_req->signal_received = received_signal;
|
||||
if (received_signal < 0) {
|
||||
rb_raise(rb_eRuntimeError, "unable to call rpc function");
|
||||
}
|
||||
else {
|
||||
wsgi_req->signal_received = received_signal;
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
@@ -868,9 +877,11 @@ 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);
|
||||
#ifdef UWSGI_ASYNC
|
||||
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);
|
||||
#endif
|
||||
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);
|
||||
|
||||
+46
-50
@@ -18,6 +18,12 @@ struct uwsgi_option uwsgi_rack_options[] = {
|
||||
{"rubyrequire", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
{"require", required_argument, 0, "import/require a ruby module/script", uwsgi_opt_add_string_list, &ur.rbrequire, 0},
|
||||
|
||||
{"shared-rb-require", required_argument, 0, "import/require a ruby module/script (shared)", uwsgi_opt_add_string_list, &ur.shared_rbrequire, 0},
|
||||
{"shared-ruby-require", required_argument, 0, "import/require a ruby module/script (shared)", uwsgi_opt_add_string_list, &ur.shared_rbrequire, 0},
|
||||
{"shared-rbrequire", required_argument, 0, "import/require a ruby module/script (shared)", uwsgi_opt_add_string_list, &ur.shared_rbrequire, 0},
|
||||
{"shared-rubyrequire", required_argument, 0, "import/require a ruby module/script (shared)", uwsgi_opt_add_string_list, &ur.shared_rbrequire, 0},
|
||||
{"shared-require", required_argument, 0, "import/require a ruby module/script (shared)", uwsgi_opt_add_string_list, &ur.shared_rbrequire, 0},
|
||||
|
||||
{"gemset", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
|
||||
{"rvm", required_argument, 0, "load the specified gemset (rvm)", uwsgi_opt_set_str, &ur.gemset, 0},
|
||||
|
||||
@@ -29,7 +35,6 @@ struct uwsgi_option uwsgi_rack_options[] = {
|
||||
{"rb-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
|
||||
{"rbthreads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
|
||||
{"ruby-threads", required_argument, 0, "set the number of ruby threads to run", uwsgi_opt_set_int, &ur.rb_threads, 0},
|
||||
{"rb-patch-rack-bodyproxy", no_argument, 0, "some specific (old) combos of ruby 1.9+rack could require that hack...", uwsgi_opt_true, &ur.patch_bodyproxy, 0},
|
||||
#endif
|
||||
|
||||
{0, 0, 0, 0, 0, 0 ,0},
|
||||
@@ -129,7 +134,7 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
struct wsgi_request *wsgi_req;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
VALUE chunk;
|
||||
unsigned int chunk_size;
|
||||
long chunk_size;
|
||||
|
||||
/*
|
||||
When EOF is reached, this method returns nil if length is given and not nil, or "" if length is not given or is nil.
|
||||
@@ -154,7 +159,16 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
}
|
||||
// size specified
|
||||
else if (RARRAY_LEN(args) > 0) {
|
||||
chunk_size = NUM2UINT(RARRAY_PTR(args)[0]);
|
||||
if (RARRAY_PTR(args)[0] == Qnil) {
|
||||
chunk_size = wsgi_req->post_cl;
|
||||
}
|
||||
else {
|
||||
chunk_size = NUM2LONG(RARRAY_PTR(args)[0]);
|
||||
// hack to tolerate broken middlewares
|
||||
if (chunk_size <= 0) {
|
||||
chunk_size = wsgi_req->post_cl;
|
||||
}
|
||||
}
|
||||
char *tmp_chunk = uwsgi_malloc(chunk_size);
|
||||
size_t rlen = fread(tmp_chunk, 1, chunk_size, (FILE *) wsgi_req->async_post);
|
||||
// error, return Qnil
|
||||
@@ -165,8 +179,6 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
// push in the specified buffer
|
||||
if (RARRAY_LEN(args) > 1) {
|
||||
rb_str_cat(RARRAY_PTR(args)[1], tmp_chunk, rlen);
|
||||
free(tmp_chunk);
|
||||
return RARRAY_PTR(args)[1];
|
||||
}
|
||||
// return a new string
|
||||
chunk = rb_str_new(tmp_chunk, rlen);
|
||||
@@ -197,14 +209,21 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
return chunk;
|
||||
}
|
||||
else if (RARRAY_LEN(args) > 0) {
|
||||
chunk_size = NUM2UINT(RARRAY_PTR(args)[0]);
|
||||
if (RARRAY_PTR(args)[0] == Qnil) {
|
||||
chunk_size = wsgi_req->post_cl;
|
||||
}
|
||||
else {
|
||||
chunk_size = NUM2LONG(RARRAY_PTR(args)[0]);
|
||||
// hack to tolerate broken middlewares
|
||||
if (chunk_size <= 0) {
|
||||
chunk_size = wsgi_req->post_cl;
|
||||
}
|
||||
}
|
||||
if (wsgi_req->buf_pos+chunk_size > wsgi_req->post_cl) {
|
||||
chunk_size = wsgi_req->post_cl-wsgi_req->buf_pos;
|
||||
}
|
||||
if (RARRAY_LEN(args) > 1) {
|
||||
rb_str_cat(RARRAY_PTR(args)[1], wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
|
||||
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;
|
||||
@@ -458,6 +477,20 @@ int uwsgi_rack_init(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_rack_preinit_apps() {
|
||||
|
||||
struct uwsgi_string_list *usl = ur.shared_rbrequire;
|
||||
while(usl) {
|
||||
int error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VALUE uwsgi_rb_call_new(VALUE obj) {
|
||||
return rb_funcall(obj, rb_intern("new"), 0);
|
||||
}
|
||||
@@ -975,44 +1008,6 @@ 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;
|
||||
@@ -1029,11 +1024,10 @@ VALUE init_rack_app( VALUE script ) {
|
||||
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
|
||||
#ifdef RUBY19
|
||||
if (ur.patch_bodyproxy) {
|
||||
VALUE ret = rb_protect(uwsgi_rack_patch_body_proxy, rack, &error);
|
||||
if (!error && ret != Qnil) {
|
||||
if (rb_eval_string("module Rack;class BodyProxy;def each(&block);@body.each(&block);end;end;end")) {
|
||||
if (uwsgi.mywid <= 1) {
|
||||
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1252,6 +1246,8 @@ struct uwsgi_plugin rack_plugin = {
|
||||
|
||||
.spooler = uwsgi_rack_spooler,
|
||||
|
||||
.preinit_apps = uwsgi_rack_preinit_apps,
|
||||
|
||||
.init_apps = uwsgi_rack_init_apps,
|
||||
.mount_app = uwsgi_rack_mount_app,
|
||||
|
||||
|
||||
@@ -4,23 +4,7 @@
|
||||
|
||||
#ifndef RUBY19
|
||||
#include <st.h>
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
#define RUBY_GVL_LOCK
|
||||
#define RUBY_GVL_UNLOCK
|
||||
#else
|
||||
void fiber_loop(void);
|
||||
#ifdef UWSGI_THREADING
|
||||
#define RUBY_GVL_LOCK if (uwsgi.threads > 1) {\
|
||||
pthread_mutex_lock(&ur.gvl);\
|
||||
}
|
||||
|
||||
#define RUBY_GVL_UNLOCK if (uwsgi.threads > 1) {\
|
||||
pthread_mutex_unlock(&ur.gvl);\
|
||||
}
|
||||
#else
|
||||
#define RUBY_GVL_LOCK
|
||||
#define RUBY_GVL_UNLOCK
|
||||
#endif
|
||||
#define rb_errinfo() ruby_errinfo
|
||||
#endif
|
||||
|
||||
#ifndef RARRAY_LEN
|
||||
@@ -67,14 +51,12 @@ struct uwsgi_rack {
|
||||
int unprotected;
|
||||
|
||||
struct uwsgi_string_list *rbrequire;
|
||||
struct uwsgi_string_list *shared_rbrequire;
|
||||
struct uwsgi_string_list *rvm_path;
|
||||
|
||||
char *gemset;
|
||||
|
||||
int rb_threads;
|
||||
#ifdef RUBY19
|
||||
int patch_bodyproxy;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ struct uwsgi_option rawrouter_options[] = {
|
||||
{"rawrouter-quiet", required_argument, 0, "do not report failed connections to instances", uwsgi_opt_true, &urr.cr.quiet, 0},
|
||||
{"rawrouter-cheap", no_argument, 0, "run the rawrouter in cheap mode", uwsgi_opt_true, &urr.cr.cheap, 0},
|
||||
{"rawrouter-subscription-server", required_argument, 0, "run the rawrouter subscription server on the spcified address", uwsgi_opt_corerouter_ss, &urr, 0},
|
||||
{"rawrouter-subscription-use-regexp", no_argument, 0, "enable regexp for subscription system", uwsgi_opt_true, &urr.cr.subscription_regexp, 0},
|
||||
|
||||
{"rawrouter-timeout", required_argument, 0, "set rawrouter timeout", uwsgi_opt_set_int, &urr.cr.socket_timeout, 0},
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <tcpd.h>
|
||||
|
||||
/*
|
||||
|
||||
by Colin Ligertwood
|
||||
|
||||
syntax:
|
||||
|
||||
route = /^foobar access:action=hosts,daemon=uwsgi
|
||||
route = /^foobar access:action=allow,daemon=uwsgi,addr=127.0.0.1
|
||||
route = /^foobar access:action=deny,daemon=uwsgi2,addr=192.168.*
|
||||
route = /^foobar access:action=deny,daemon=uwsgi3,addr=192.168.0.0/24
|
||||
|
||||
TODO only the 'hosts' action is supported
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_access_conf {
|
||||
char *action;
|
||||
char *daemon;
|
||||
char *addr;
|
||||
};
|
||||
|
||||
static int uwsgi_routing_func_access(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
int pass = 0;
|
||||
struct uwsgi_router_access_conf *urac = (struct uwsgi_router_access_conf *) ur->data2;
|
||||
|
||||
if (!urac) {
|
||||
urac = uwsgi_calloc(sizeof(struct uwsgi_router_access_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"action", &urac->action,
|
||||
"daemon", &urac->daemon,
|
||||
"addr", &urac->addr, NULL)) {
|
||||
free(urac);
|
||||
goto forbidden;
|
||||
}
|
||||
if (!urac->action) urac->action = "hosts";
|
||||
if (!urac->daemon) urac->action = "uwsgi";
|
||||
ur->data2 = urac;
|
||||
}
|
||||
|
||||
char *addr = uwsgi_concat2n(wsgi_req->remote_addr, wsgi_req->remote_addr_len, "", 0);
|
||||
|
||||
if (!strcmp(urac->action, "hosts")){
|
||||
pass = hosts_ctl(urac->daemon, STRING_UNKNOWN, addr, STRING_UNKNOWN);
|
||||
}
|
||||
else if (!strcmp(urac->action, "allow") && urac->addr){
|
||||
// unimplemented
|
||||
}
|
||||
else if (!strcmp(urac->action, "deny") && urac->addr){
|
||||
// unimplemented
|
||||
}
|
||||
|
||||
free(addr);
|
||||
|
||||
if (pass) return UWSGI_ROUTE_NEXT;
|
||||
|
||||
forbidden:
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/html\r\n\r\n", 51);
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req,"<h1>403 Forbidden</h1>", 23);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
static int uwsgi_router_access(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_access;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_access_register() {
|
||||
uwsgi_register_router("access", uwsgi_router_access);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_access_plugin = {
|
||||
.name = "router_access",
|
||||
.on_load = router_access_register,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='router_access'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lwrap']
|
||||
|
||||
REQUIRES = ['']
|
||||
|
||||
GCC_LIST = ['router_access']
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
by Unbit
|
||||
|
||||
syntax:
|
||||
|
||||
route = /^foobar1 cache:key=PATH_INFO,type=body
|
||||
route = /^foobar2 cache:key=REQUEST_URI,type=full
|
||||
route = /^foobar3 cache:key=REQUEST_URI,type=body,content_type=text/html
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_cache_conf {
|
||||
char *key;
|
||||
char *type;
|
||||
|
||||
long key_offset;
|
||||
long key_offset_len;
|
||||
|
||||
char *content_type;
|
||||
size_t content_type_len;
|
||||
|
||||
// 0 -> full, 1 -> body
|
||||
int type_num;
|
||||
|
||||
};
|
||||
|
||||
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
|
||||
|
||||
if (!uwsgi.cache_max_items) return UWSGI_ROUTE_NEXT;
|
||||
|
||||
if (!urcc) {
|
||||
urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"key", &urcc->key,
|
||||
"content_type", &urcc->content_type,
|
||||
"type", &urcc->type, NULL)) {
|
||||
free(urcc);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
if (!urcc->key) urcc->key = "REQUEST_URI";
|
||||
if (!urcc->type) urcc->type = "full";
|
||||
if (!urcc->content_type) urcc->content_type = "text/html";
|
||||
|
||||
urcc->content_type_len = strlen(urcc->content_type);
|
||||
|
||||
if (!strcmp(urcc->key, "REQUEST_URI")) {
|
||||
urcc->key_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->key_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
else if (!strcmp(urcc->key, "PATH_INFO")) {
|
||||
urcc->key_offset = offsetof(struct wsgi_request, path_info);
|
||||
urcc->key_offset_len = offsetof(struct wsgi_request, path_info_len);
|
||||
}
|
||||
else {
|
||||
urcc->key_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->key_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
|
||||
if (!strcmp(urcc->type, "body")) {
|
||||
urcc->type_num = 1;
|
||||
}
|
||||
|
||||
ur->data2 = urcc;
|
||||
}
|
||||
|
||||
char **key = (char **) (((char *) wsgi_req) + urcc->key_offset);
|
||||
uint16_t *keylen = (uint16_t *) (((char *) wsgi_req) + urcc->key_offset_len);
|
||||
|
||||
uint64_t valsize = 0;
|
||||
char *value = uwsgi_cache_get(*key, *keylen, &valsize);
|
||||
if (value) {
|
||||
// body only
|
||||
if (urcc->type_num == 1) {
|
||||
wsgi_req->status = 200;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: ", 50);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, urcc->content_type, urcc->content_type_len);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n\r\n", 4);
|
||||
wsgi_req->header_cnt = 2;
|
||||
}
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, value, valsize);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_cache;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_cache_register() {
|
||||
uwsgi_register_router("cache", uwsgi_router_cache);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin router_cache_plugin = {
|
||||
.name = "router_cache",
|
||||
.on_load = router_cache_register,
|
||||
};
|
||||
|
||||
#else
|
||||
struct uwsgi_plugin router_cache_plugin = {
|
||||
.name = "router_cache",
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='router_cache'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['router_cache']
|
||||
@@ -20,7 +20,7 @@ int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_route *u
|
||||
}
|
||||
|
||||
// convert the wsgi_request to an http proxy request
|
||||
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req);
|
||||
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len);
|
||||
if (!ub) {
|
||||
uwsgi_log("unable to generate http request for %s\n", addr);
|
||||
close(http_fd);
|
||||
@@ -73,6 +73,14 @@ int uwsgi_router_http(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_http;
|
||||
ur->data = (void *) args;
|
||||
ur->data_len = strlen(args);
|
||||
|
||||
char *comma = strchr(ur->data, ',');
|
||||
if (comma) {
|
||||
*comma = 0;
|
||||
ur->data_len = strlen(ur->data);
|
||||
ur->data2 = comma+1;
|
||||
ur->data2_len = strlen(ur->data2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *, char *, size_t);
|
||||
|
||||
static void stats_pusher_mongodb_init(void) {
|
||||
uwsgi_register_stats_pusher("mongodb", stats_pusher_mongodb);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin stats_pusher_mongodb_plugin = {
|
||||
|
||||
.name = "stats_pusher_mongodb",
|
||||
.on_load = stats_pusher_mongodb_init,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// one for each mongodb stats pusher
|
||||
struct stats_pusher_mongodb_conf {
|
||||
char *address;
|
||||
char *collection;
|
||||
char *freq;
|
||||
};
|
||||
|
||||
|
||||
extern "C" void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
|
||||
|
||||
struct stats_pusher_mongodb_conf *spmc = (struct stats_pusher_mongodb_conf *) uspi->data;
|
||||
if (!uspi->configured) {
|
||||
spmc = (struct stats_pusher_mongodb_conf *) uwsgi_calloc(sizeof(struct stats_pusher_mongodb_conf));
|
||||
if (uspi->arg) {
|
||||
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=',
|
||||
"addr", &spmc->address,
|
||||
"address", &spmc->address,
|
||||
"collection", &spmc->collection,
|
||||
"freq", &spmc->freq, NULL)) {
|
||||
free(spmc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!spmc->address) spmc->address = (char *) "127.0.0.1:27017";
|
||||
if (!spmc->collection) spmc->collection = (char *) "uwsgi.statistics";
|
||||
if (spmc->freq) uspi->freq = atoi(spmc->freq);
|
||||
uspi->data = spmc;
|
||||
uspi->configured = 1;
|
||||
}
|
||||
|
||||
try {
|
||||
int j_len = (int) json_len;
|
||||
mongo::BSONObj b = mongo::fromjson(json, &j_len);
|
||||
// the connection object (will be automatically destroyed at each cycle)
|
||||
mongo::DBClientConnection c;
|
||||
// set the socket timeout
|
||||
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
// connect
|
||||
c.connect(spmc->address);
|
||||
c.insert(spmc->collection, b);
|
||||
}
|
||||
catch ( mongo::DBException &e ) {
|
||||
uwsgi_log("[stats-pusher-mongodb] ERROR(%s/%s): %s\n", spmc->address, spmc->collection, e.what());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
NAME='stats_pusher_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
GCC_LIST = ['plugin', 'stats_pusher_mongodb.cc']
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
ssize_t uwsgi_systemd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
// split multiline log messages to multiple journal lines
|
||||
size_t i;
|
||||
char *base = message;
|
||||
for(i=0;i<len;i++) {
|
||||
if (message[i] == '\n') {
|
||||
message[i] = 0;
|
||||
sd_journal_print(LOG_INFO, base);
|
||||
base = message+i+1;
|
||||
}
|
||||
}
|
||||
|
||||
// last \n is missing...
|
||||
if (base < message+len) {
|
||||
sd_journal_print(LOG_INFO, "%.*s", (int) ((message+len) - base), base);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_systemd_logger_register() {
|
||||
uwsgi_register_logger("systemd", uwsgi_systemd_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin systemd_logger_plugin = {
|
||||
|
||||
.name = "systemd_logger",
|
||||
.on_load = uwsgi_systemd_logger_register,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
NAME='systemd_logger'
|
||||
|
||||
CFLAGS = os.popen('pkg-config --cflags libsystemd-journal').read().rstrip().split()
|
||||
LDFLAGS = []
|
||||
LIBS = os.popen('pkg-config --libs libsystemd-journal').read().rstrip().split()
|
||||
GCC_LIST = ['systemd_logger']
|
||||
+17
-4
@@ -137,6 +137,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *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);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
@@ -158,6 +160,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *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);
|
||||
wsgi_req->path_info = (wsgi_req->buffer + wsgi_req->uh.pktsize) - (ptr - base);
|
||||
wsgi_req->path_info_len = ptr - base;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("not enough space in wsgi_req http proto_parser_buf to encode PATH_INFO, consider tuning it with --buffer-size\n");
|
||||
@@ -389,7 +393,7 @@ void uwsgi_httpize_var(char *buf, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, uint16_t host_len) {
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
|
||||
|
||||
@@ -397,10 +401,8 @@ struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto clear;
|
||||
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto clear;
|
||||
|
||||
if (uwsgi_buffer_append(ub, wsgi_req->protocol, wsgi_req->protocol_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, " HTTP/1.0\r\n", 11)) goto clear;
|
||||
|
||||
int i;
|
||||
char *x_forwarded_for = NULL;
|
||||
@@ -413,6 +415,8 @@ struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req) {
|
||||
char *header = wsgi_req->hvec[i].iov_base+5;
|
||||
size_t header_len = wsgi_req->hvec[i].iov_len-5;
|
||||
|
||||
if (host && !uwsgi_strncmp(header, header_len, "HOST", 4)) goto next;
|
||||
|
||||
if (!uwsgi_strncmp(header, header_len, "CONNECTION", 10)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "KEEP_ALIVE", 10)) goto next;
|
||||
if (!uwsgi_strncmp(header, header_len, "X_FORWARDED_FOR", 15)) {
|
||||
@@ -435,10 +439,19 @@ next:
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
// append custom Host (if needed)
|
||||
if (host) {
|
||||
if (uwsgi_buffer_append(ub, "Host: ", 6)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, host, host_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
|
||||
}
|
||||
|
||||
// append required headers
|
||||
if (uwsgi_buffer_append(ub, "Connection: close\r\n", 19)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, "X-Forwarded-For: ", 17)) goto clear;
|
||||
|
||||
|
||||
if (x_forwarded_for_len > 0) {
|
||||
if (uwsgi_buffer_append(ub, x_forwarded_for, x_forwarded_for_len)) goto clear;
|
||||
if (uwsgi_buffer_append(ub, ", ", 2)) goto clear;
|
||||
|
||||
+7
-7
@@ -1,13 +1,13 @@
|
||||
import uwsgi
|
||||
from os import path
|
||||
|
||||
counter = 0
|
||||
uwsgi.snmp_set_counter64(1, counter)
|
||||
uwsgi.snmp_set_counter64(1, 0) # Number of requests
|
||||
uwsgi.snmp_set_counter64(2, 0) # Number of bytes
|
||||
|
||||
def application(environ, start_response):
|
||||
global counter
|
||||
|
||||
start_response('200 OK', [('Content-Type', 'image/png')])
|
||||
size = path.getsize('logo_uWSGI.png')
|
||||
start_response('200 OK', [('Content-Type', 'image/png'), ('Content-Length', str(size))] )
|
||||
fd = open('logo_uWSGI.png','r')
|
||||
counter = counter+1
|
||||
uwsgi.snmp_set_counter64(1, counter)
|
||||
uwsgi.snmp_incr_counter64(1)
|
||||
uwsgi.snmp_incr_counter64(2, size)
|
||||
return environ['wsgi.file_wrapper'](fd, 4096)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import "uwsgi"
|
||||
import "net/http"
|
||||
import "fmt"
|
||||
|
||||
|
||||
func getHandler(w http.ResponseWriter, r *http.Request) {
|
||||
p := uwsgi.CacheGet("foobar")
|
||||
if p == nil {
|
||||
fmt.Fprintf(w, "<h1>item not found</h1>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "<h1>" + string(p) + "</h1>")
|
||||
}
|
||||
|
||||
func setHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if uwsgi.CacheSet("foobar", []byte("Hello World !"), 0) == false {
|
||||
fmt.Fprintf(w, "<h1>unable to set cache item</h1>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "<h1>item set</h1>")
|
||||
}
|
||||
|
||||
func updateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if uwsgi.CacheUpdate("foobar", []byte("Hello World ! [updated]"), 0) == false {
|
||||
fmt.Fprintf(w, "<h1>unable to update cache item</h1>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "<h1>item updated</h1>")
|
||||
}
|
||||
|
||||
func deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if uwsgi.CacheDel("foobar") == false {
|
||||
fmt.Fprintf(w, "<h1>unable to delete cache item</h1>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "<h1>item deleted</h1>")
|
||||
}
|
||||
|
||||
func checkHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !uwsgi.CacheExists("foobar") {
|
||||
fmt.Fprintf(w, "<h1>item does not exist</h1>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "<h1>item exists</h1>")
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/get/", getHandler)
|
||||
http.HandleFunc("/update/", updateHandler)
|
||||
http.HandleFunc("/set/", setHandler)
|
||||
http.HandleFunc("/delete/", deleteHandler)
|
||||
http.HandleFunc("/check/", checkHandler)
|
||||
uwsgi.Run()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user