mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 07:58:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50954d34db | ||
|
|
ef2d9e781f | ||
|
|
a9bb310a20 | ||
|
|
86f37556da | ||
|
|
a57617c09a | ||
|
|
63ac62cf1d | ||
|
|
ac371730fd | ||
|
|
4ed6588c80 | ||
|
|
81d20edc4c | ||
|
|
a9fc6adccf | ||
|
|
21ad94ba4e | ||
|
|
571b9f27e1 | ||
|
|
cbf9ccf062 | ||
|
|
dd8fd8f19c | ||
|
|
1535b8ee13 | ||
|
|
f2491536dd | ||
|
|
88ce0181b3 | ||
|
|
4ad2658090 | ||
|
|
8d80c5e84d | ||
|
|
bae9235103 | ||
|
|
8ae2d0d00c | ||
|
|
373b89e70c | ||
|
|
c14e18b270 | ||
|
|
68ec3afd1a | ||
|
|
8918e81256 | ||
|
|
469fd697cb | ||
|
|
20844ebfca | ||
|
|
38652076d3 | ||
|
|
f13ae47fc0 | ||
|
|
ad4ee9d5c3 | ||
|
|
03a4e900ea | ||
|
|
b52dbf2aa0 | ||
|
|
c7a22c3b53 | ||
|
|
775aae3f1e | ||
|
|
862731ba91 | ||
|
|
8c302eee51 | ||
|
|
b6d34067c4 | ||
|
|
dbe15195b7 | ||
|
|
5642aa1eb5 | ||
|
|
5dd465ccc1 | ||
|
|
ae78c3007e | ||
|
|
16211d9439 | ||
|
|
515619fe2a | ||
|
|
a7d550165d | ||
|
|
efceacd9e5 | ||
|
|
ea5ebc2d15 | ||
|
|
fba82c203c | ||
|
|
a50516af7a | ||
|
|
6056b51653 | ||
|
|
23a3170c59 | ||
|
|
e136128408 | ||
|
|
fce94e0f54 | ||
|
|
06fa65bc5d | ||
|
|
571ec5ca72 | ||
|
|
39bc0ecd46 | ||
|
|
7a5373360c | ||
|
|
15453ffef6 | ||
|
|
a25747a096 | ||
|
|
bb1ef59b52 | ||
|
|
6bb3af840d | ||
|
|
0223c74ecc | ||
|
|
c7004d7ba4 | ||
|
|
915d2e9192 | ||
|
|
df79b9367b | ||
|
|
ce3d026037 | ||
|
|
d0f6c4130b | ||
|
|
26bcf28182 | ||
|
|
272d1ccc03 | ||
|
|
6c440af24e | ||
|
|
8954520cb9 | ||
|
|
31bde74fab | ||
|
|
13c64a383c | ||
|
|
809028f11b | ||
|
|
dee9d2ba1e | ||
|
|
29d80ce061 | ||
|
|
abcd3242d8 | ||
|
|
f4762299f9 | ||
|
|
107f4309a4 | ||
|
|
d2a8df19ea | ||
|
|
29efd15534 | ||
|
|
e7fb216a8d | ||
|
|
952b96cdcb | ||
|
|
8ee82fc296 | ||
|
|
afe2bfb856 | ||
|
|
5b63e9aea0 | ||
|
|
91f70259e2 | ||
|
|
f120cacc03 | ||
|
|
aff1d782b8 | ||
|
|
b489fd8a24 | ||
|
|
47e0eb68c2 | ||
|
|
9498e25245 | ||
|
|
a33e18b589 | ||
|
|
f2dcdf2289 | ||
|
|
74c53e8a61 | ||
|
|
1feed87c10 | ||
|
|
f89742d81a | ||
|
|
340b9d603e | ||
|
|
1c0fc64243 | ||
|
|
1d5173d923 | ||
|
|
49a8bf0b9b | ||
|
|
0a7e5a41a2 | ||
|
|
43ff563429 | ||
|
|
2daf6f1f66 | ||
|
|
985f56768f | ||
|
|
35278588f5 | ||
|
|
f6545be647 |
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
|
||||
inherit = base
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rados
|
||||
inherit = base
|
||||
+2
-3
@@ -184,8 +184,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
|
||||
// map instances to the log
|
||||
char *list = uwsgi_str(alarms);
|
||||
char *p = strtok(list, ",");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
|
||||
if (!uai) {
|
||||
free(list);
|
||||
@@ -205,7 +205,6 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
|
||||
else {
|
||||
ual->alarms = uall;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
|
||||
@@ -172,6 +172,16 @@ int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
|
||||
uint8_t buf[4];
|
||||
uint32_t *pnum = (uint32_t *) #
|
||||
buf[3] = (uint8_t) (*pnum & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 4);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
|
||||
uint8_t buf[4];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
@@ -195,6 +205,20 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
|
||||
uint8_t buf[8];
|
||||
uint64_t *pnum = (uint64_t *) #
|
||||
buf[7] = (uint8_t) (*pnum & 0xff);
|
||||
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
|
||||
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
|
||||
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
|
||||
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
|
||||
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
|
||||
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
|
||||
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
|
||||
char ip[INET_ADDRSTRLEN];
|
||||
if (!inet_ntop(AF_INET, addr, ip, INET_ADDRSTRLEN)) {
|
||||
|
||||
+6
-9
@@ -1191,26 +1191,23 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) {
|
||||
uc->store = c_store;
|
||||
|
||||
if (c_nodes) {
|
||||
char *p = strtok(c_nodes, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_nodes, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_sync) {
|
||||
char *p = strtok(c_sync, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_sync, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->sync_nodes, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (c_udp_servers) {
|
||||
char *p = strtok(c_udp_servers, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(c_udp_servers, ";", p, ctx) {
|
||||
uwsgi_string_new_list(&uc->udp_servers, p);
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -55,10 +55,9 @@ int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
|
||||
|
||||
int uwsgi_logic_opt_for(char *key, char *value) {
|
||||
|
||||
char *p = strtok(uwsgi.logic_opt_data, " ");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
|
||||
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
+23
-6
@@ -77,8 +77,14 @@ void uwsgi_daemons_smart_check() {
|
||||
else {
|
||||
ud->pidfile_checks++;
|
||||
if (ud->pidfile_checks >= (unsigned int) 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);
|
||||
if (!ud->has_daemonized) {
|
||||
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
|
||||
ud->pidfile_checks = 0;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,10 +105,20 @@ void uwsgi_daemons_smart_check() {
|
||||
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);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
if (ud->pid == diedpid) {
|
||||
if (!ud->pidfile) {
|
||||
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
|
||||
ud->pid = -1;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
if (!ud->has_daemonized) {
|
||||
ud->has_daemonized = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
ud = ud->next;
|
||||
}
|
||||
@@ -251,6 +267,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
ud->has_daemonized = 0;
|
||||
ud->pid = pid;
|
||||
ud->status = 1;
|
||||
ud->pidfile_checks = 0;
|
||||
|
||||
+56
-7
@@ -620,7 +620,7 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
// remove uWSGI instance
|
||||
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_stop()/write()");
|
||||
}
|
||||
|
||||
c_ui->status = 1;
|
||||
@@ -634,7 +634,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
// reload the uWSGI instance
|
||||
if (write(c_ui->pipe[0], "\1", 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
uwsgi_error("emperor_respawn/write()");
|
||||
}
|
||||
|
||||
// push the config to the config pipe (if needed)
|
||||
@@ -862,14 +862,28 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
// once the config is sent we can run hooks (they can fail)
|
||||
// exec hooks have access to all of the currently defined vars + UWSGI_VASSAL_PID, UWSGI_VASSAL_UID, UWSGI_VASSAL_GID, UWSGI_VASSAL_CONFIG
|
||||
uwsgi_hooks_run(uwsgi.hook_as_emperor, "as-emperor", 0);
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_emperor) {
|
||||
uwsgi_log("mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_emperor) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_emperor) {
|
||||
uwsgi_log("running \"%s\" (as-emperor for vassal \"%s\" pid: %d uid: %d gid: %d)...\n", usl->value, n_ui->name, n_ui->pid, n_ui->uid, n_ui->gid);
|
||||
char *argv[4];
|
||||
argv[0] = uwsgi_concat2("UWSGI_VASSAL_CONFIG=", n_ui->name);
|
||||
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", n_ui->pid); argv[1] = argv_pid;
|
||||
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", n_ui->uid); argv[2] = argv_uid;
|
||||
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", n_ui->gid); argv[3] = argv_gid;
|
||||
char argv_pid[17+11]; snprintf(argv_pid, 17 + 11, "UWSGI_VASSAL_PID=%d", (int) n_ui->pid); argv[1] = argv_pid;
|
||||
char argv_uid[17+11]; snprintf(argv_uid, 17 + 11, "UWSGI_VASSAL_UID=%d", (int) n_ui->uid); argv[2] = argv_uid;
|
||||
char argv_gid[17+11]; snprintf(argv_gid, 17 + 11, "UWSGI_VASSAL_GID=%d", (int) n_ui->gid); argv[3] = argv_gid;
|
||||
int ret = uwsgi_run_command_putenv_and_wait(NULL, usl->value, argv, 4);
|
||||
uwsgi_log("command \"%s\" exited with code: %d\n", usl->value, ret);
|
||||
free(argv[0]);
|
||||
@@ -1017,6 +1031,12 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
@@ -1079,6 +1099,15 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
@@ -1131,6 +1160,22 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_vassal, "as-vassal", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_vassal) {
|
||||
uwsgi_log("mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_vassal) {
|
||||
uwsgi_log("un-mounting \"%s\" (as-vassal)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// run exec hooks (cannot fail)
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_vassal) {
|
||||
uwsgi_log("running \"%s\" (as-vassal)...\n", usl->value);
|
||||
@@ -1476,10 +1521,14 @@ void emperor_loop() {
|
||||
while (ui_current) {
|
||||
if (ui_current->last_heartbeat > 0) {
|
||||
if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) {
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, brutally respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat);
|
||||
// set last_heartbeat to 0 avoiding races
|
||||
ui_current->last_heartbeat = 0;
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
if (ui_current->pid > 0) {
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_current = ui_current->ui_next;
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
the --master-fifo option create a unix named pipe (fifo) you can use to send management
|
||||
commands to the master:
|
||||
|
||||
echo r > myfifo
|
||||
|
||||
*/
|
||||
|
||||
// this var can be accessed by plugins and hooks
|
||||
void (*uwsgi_fifo_table[256])(int);
|
||||
|
||||
static char *uwsgi_fifo_by_slot() {
|
||||
int count = 0;
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.master_fifo) {
|
||||
if (count == uwsgi.master_fifo_slot) return usl->value;
|
||||
count++;
|
||||
}
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
|
||||
|
||||
/*
|
||||
|
||||
this is called as soon as possibile allowing plugins (or hooks) to override it
|
||||
|
||||
*/
|
||||
void uwsgi_master_fifo_prepare() {
|
||||
int i;
|
||||
for(i=0;i<256;i++) {
|
||||
uwsgi_fifo_table[i] = NULL;
|
||||
}
|
||||
|
||||
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
|
||||
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
|
||||
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
|
||||
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
|
||||
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
|
||||
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
|
||||
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
|
||||
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
|
||||
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
|
||||
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
|
||||
|
||||
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
|
||||
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
|
||||
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
|
||||
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
|
||||
uwsgi_fifo_table['f'] = uwsgi_refork_master;
|
||||
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
|
||||
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
|
||||
uwsgi_fifo_table['p'] = suspend_resume_them_all;
|
||||
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
|
||||
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
|
||||
uwsgi_fifo_table['Q'] = kill_them_all;
|
||||
uwsgi_fifo_table['r'] = grace_them_all;
|
||||
uwsgi_fifo_table['R'] = reap_them_all;
|
||||
uwsgi_fifo_table['s'] = stats;
|
||||
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
|
||||
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo() {
|
||||
|
||||
char *path = uwsgi_fifo_by_slot();
|
||||
|
||||
unlink(path);
|
||||
|
||||
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_master_fifo()/open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
uwsgi_error("uwsgi_master_fifo_manage()/read()");
|
||||
exit(1);
|
||||
}
|
||||
// fifo destroyed, recreate it
|
||||
else if (rlen == 0) {
|
||||
close(fd);
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uwsgi_fifo_table[(int) cmd]) {
|
||||
uwsgi_fifo_table[(int) cmd](0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
advanced (pluggable) hooks
|
||||
|
||||
they are executed before the other hooks, and can be extended by plugins
|
||||
|
||||
if a plugin tries to register an hook with a name already available in the list, its function
|
||||
will be overridden
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
|
||||
struct uwsgi_hook *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
return uh;
|
||||
}
|
||||
uh = uh->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_hook(char *name, int (*func)(char *)) {
|
||||
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
|
||||
while(uh) {
|
||||
if (!strcmp(uh->name, name)) {
|
||||
uh->func = func;
|
||||
return;
|
||||
}
|
||||
old_uh = uh;
|
||||
uh = uh->next;
|
||||
}
|
||||
|
||||
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
|
||||
uh->name = name;
|
||||
uh->func = func;
|
||||
|
||||
if (old_uh) {
|
||||
old_uh->next = uh;
|
||||
}
|
||||
else {
|
||||
uwsgi.hooks = uh;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_hook_chdir(char *arg) {
|
||||
int ret = chdir(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_chdir()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exec(char *arg) {
|
||||
int ret = uwsgi_run_command_and_wait(NULL, arg);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_exit(char *arg) {
|
||||
int exit_code = 0;
|
||||
if (strlen(arg) > 1) {
|
||||
exit_code = atoi(arg);
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static int uwsgi_hook_print(char *arg) {
|
||||
char *line = uwsgi_concat2(arg, "\n");
|
||||
uwsgi_log(line);
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callint(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(num);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_call(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
func(space + 1);
|
||||
}
|
||||
else {
|
||||
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
func();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_callintret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int num = atoi(space+1);
|
||||
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(num);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callret(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
return func(space + 1);
|
||||
}
|
||||
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", arg);
|
||||
return -1;
|
||||
}
|
||||
return func();
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("mount", uwsgi_mount_hook);
|
||||
uwsgi_register_hook("umount", uwsgi_umount_hook);
|
||||
|
||||
uwsgi_register_hook("call", uwsgi_hook_call);
|
||||
uwsgi_register_hook("callret", uwsgi_hook_callret);
|
||||
|
||||
uwsgi_register_hook("callint", uwsgi_hook_callint);
|
||||
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
|
||||
|
||||
// for testing
|
||||
uwsgi_register_hook("exit", uwsgi_hook_exit);
|
||||
uwsgi_register_hook("print", uwsgi_hook_print);
|
||||
}
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
char *colon = strchr(usl->value, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid hook syntax, must be hook:args\n");
|
||||
exit(1);
|
||||
}
|
||||
*colon = 0;
|
||||
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
|
||||
if (!uh) {
|
||||
uwsgi_log("hook not found: %s\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
*colon = ':';
|
||||
|
||||
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
|
||||
|
||||
int ret = uh->func(colon+1);
|
||||
if (fatal && ret != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-6
@@ -172,6 +172,11 @@ void uwsgi_init_default() {
|
||||
|
||||
// 1 MB default limit
|
||||
uwsgi.chunked_input_limit = 1024*1024;
|
||||
|
||||
// clear reforked status
|
||||
uwsgi.master_is_reforked = 0;
|
||||
|
||||
uwsgi_master_fifo_prepare();
|
||||
}
|
||||
|
||||
void uwsgi_setup_reload() {
|
||||
@@ -216,21 +221,19 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
|
||||
p = original_proc_name;
|
||||
p = strstr(p, "uwsgi_");
|
||||
if (p != NULL) {
|
||||
plugins_requested = strtok(uwsgi_str(p + 6), "_");
|
||||
while (plugins_requested) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
|
||||
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
|
||||
uwsgi_load_plugin(-1, plugins_requested, NULL);
|
||||
plugins_requested = strtok(NULL, "_");
|
||||
}
|
||||
}
|
||||
|
||||
plugins_requested = getenv("UWSGI_PLUGINS");
|
||||
if (plugins_requested) {
|
||||
plugins_requested = uwsgi_concat2(plugins_requested, "");
|
||||
char *p = strtok(plugins_requested, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
|
||||
uwsgi_load_plugin(-1, p, NULL);
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +360,7 @@ void uwsgi_setup_workers() {
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_fixup_routes(uwsgi.routes);
|
||||
uwsgi_fixup_routes(uwsgi.error_routes);
|
||||
uwsgi_fixup_routes(uwsgi.response_routes);
|
||||
uwsgi_fixup_routes(uwsgi.final_routes);
|
||||
#endif
|
||||
|
||||
@@ -451,6 +455,19 @@ void sanitize_args() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* here we try to choose if thunder lock is a good thing */
|
||||
#ifdef UNBIT
|
||||
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
|
||||
|
||||
+35
-6
@@ -493,7 +493,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
if (uwsgi.ftok) {
|
||||
myKey = ftok(uwsgi.ftok, counter);
|
||||
if (myKey < 0) {
|
||||
uwsgi_error("ftok()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
|
||||
exit(1);
|
||||
}
|
||||
counter++;
|
||||
@@ -504,7 +504,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
}
|
||||
|
||||
if (semid < 0) {
|
||||
uwsgi_error("semget()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
|
||||
exit(1);
|
||||
}
|
||||
// do this now, to allows triggering of atexit hook in case of problems
|
||||
@@ -512,7 +512,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
|
||||
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -532,7 +532,13 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,7 +555,13 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
|
||||
retry:
|
||||
if (semop(semid, &sb, 1)) {
|
||||
if (errno == EINTR) goto retry;
|
||||
uwsgi_error("semop()");
|
||||
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
|
||||
#ifdef EIDRM
|
||||
if (errno == EIDRM) {
|
||||
exit(UWSGI_BRUTAL_RELOAD_CODE);
|
||||
}
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -574,6 +586,8 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
|
||||
|
||||
void uwsgi_ipcsem_clear(void) {
|
||||
|
||||
if (uwsgi.persistent_ipcsem) return;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
|
||||
|
||||
if (!uwsgi.workers)
|
||||
@@ -594,12 +608,27 @@ clear:
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("removing sysvipc semaphores...\n");
|
||||
#endif
|
||||
#ifdef GETPID
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
int ret = semctl(semid, 0, GETPID);
|
||||
if (ret > 0) {
|
||||
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
|
||||
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
uli = uwsgi.registered_locks;
|
||||
#endif
|
||||
while (uli) {
|
||||
int semid = 0;
|
||||
memcpy(&semid, uli->lock_ptr, sizeof(int));
|
||||
if (semctl(semid, 0, IPC_RMID)) {
|
||||
uwsgi_error("semctl()");
|
||||
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
|
||||
}
|
||||
uli = uli->next;
|
||||
}
|
||||
|
||||
+542
-74
@@ -120,17 +120,54 @@ void uwsgi_log_verbose(const char *fmt, ...) {
|
||||
|
||||
|
||||
|
||||
static void fix_logpipe_buf(int *fd) {
|
||||
int so_bufsize;
|
||||
socklen_t so_bufsize_len = sizeof(int);
|
||||
|
||||
if (getsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/getsockopt()");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
|
||||
so_bufsize = uwsgi.log_master_bufsize;
|
||||
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &so_bufsize, so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/setsockopt()");
|
||||
}
|
||||
}
|
||||
|
||||
if (getsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/getsockopt()");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)so_bufsize < uwsgi.log_master_bufsize) {
|
||||
so_bufsize = uwsgi.log_master_bufsize;
|
||||
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &so_bufsize, so_bufsize_len)) {
|
||||
uwsgi_error("fix_logpipe_buf()/setsockopt()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create the logpipe
|
||||
void create_logpipe(void) {
|
||||
|
||||
if (uwsgi.log_master_stream) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
fix_logpipe_buf(uwsgi.shared->worker_log_pipe);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
|
||||
@@ -149,13 +186,22 @@ void create_logpipe(void) {
|
||||
}
|
||||
|
||||
if (uwsgi.req_log_master) {
|
||||
if (uwsgi.log_master_req_stream) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if defined(SOCK_SEQPACKET) && defined(__linux__)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
|
||||
#endif
|
||||
uwsgi_error("socketpair()\n");
|
||||
exit(1);
|
||||
uwsgi_error("create_logpipe()/socketpair()\n");
|
||||
exit(1);
|
||||
}
|
||||
fix_logpipe_buf(uwsgi.shared->worker_req_log_pipe);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
|
||||
@@ -287,6 +333,8 @@ void logto(char *logfile) {
|
||||
|
||||
|
||||
void uwsgi_setup_log() {
|
||||
|
||||
uwsgi_setup_log_encoders();
|
||||
|
||||
if (uwsgi.daemonize) {
|
||||
if (uwsgi.has_emperor) {
|
||||
@@ -440,7 +488,6 @@ void uwsgi_logvar_add(struct wsgi_request *wsgi_req, char *key, uint8_t keylen,
|
||||
|
||||
void uwsgi_check_logrotate(void) {
|
||||
|
||||
char message[1024];
|
||||
int need_rotation = 0;
|
||||
int need_reopen = 0;
|
||||
|
||||
@@ -464,70 +511,81 @@ void uwsgi_check_logrotate(void) {
|
||||
}
|
||||
|
||||
if (need_rotation) {
|
||||
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
uwsgi_log_rotate();
|
||||
}
|
||||
else if (need_reopen) {
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
uwsgi_log_reopen();
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_log_rotate() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
char *rot_name = uwsgi.log_backupname;
|
||||
int need_free = 0;
|
||||
if (rot_name == NULL) {
|
||||
char *ts_str = uwsgi_num2str((int) uwsgi_now());
|
||||
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
|
||||
free(ts_str);
|
||||
need_free = 1;
|
||||
}
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
if (rename(uwsgi.logfile, rot_name) == 0) {
|
||||
// reopen logfile dup'it and eventually gracefully reload workers;
|
||||
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
else {
|
||||
if (dup2(fd, uwsgi.original_log_fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
grace_them_all(0);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("unable to rotate log: rename()");
|
||||
}
|
||||
if (need_free)
|
||||
free(rot_name);
|
||||
}
|
||||
|
||||
void uwsgi_log_reopen() {
|
||||
char message[1024];
|
||||
if (!uwsgi.logfile) return;
|
||||
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// reopen logfile;
|
||||
close(uwsgi.original_log_fd);
|
||||
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
if (write(uwsgi.original_log_fd, message, ret) != ret) {
|
||||
// very probably this will never be printed
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
|
||||
void log_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
@@ -1346,6 +1404,45 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_log_func_do(struct uwsgi_string_list *encoders, struct uwsgi_logger *ul, char *msg, size_t len) {
|
||||
struct uwsgi_string_list *usl = encoders;
|
||||
// note: msg must not be freed !!!
|
||||
char *new_msg = msg;
|
||||
size_t new_msg_len = len;
|
||||
while(usl) {
|
||||
struct uwsgi_log_encoder *ule = (struct uwsgi_log_encoder *) usl->custom_ptr;
|
||||
if (ule->use_for) {
|
||||
if (ul && ul->id) {
|
||||
if (strcmp(ule->use_for, ul->id)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
size_t rlen = 0;
|
||||
char *buf = ule->func(ule, new_msg, new_msg_len, &rlen);
|
||||
if (new_msg != msg) {
|
||||
free(new_msg);
|
||||
}
|
||||
new_msg = buf;
|
||||
new_msg_len = rlen;
|
||||
next:
|
||||
usl = usl->next;
|
||||
}
|
||||
if (ul) {
|
||||
ul->func(ul, new_msg, new_msg_len);
|
||||
}
|
||||
else {
|
||||
new_msg_len = (size_t) write(uwsgi.original_log_fd, new_msg, new_msg_len);
|
||||
}
|
||||
if (new_msg != msg) {
|
||||
free(new_msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_master_log(void) {
|
||||
|
||||
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
|
||||
@@ -1379,7 +1476,7 @@ int uwsgi_master_log(void) {
|
||||
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);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
@@ -1397,14 +1494,14 @@ int uwsgi_master_log(void) {
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, 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);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_encoders, NULL, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1423,7 +1520,7 @@ int uwsgi_master_req_log(void) {
|
||||
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);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, ul_route, uwsgi.log_master_buf, rlen);
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
@@ -1441,14 +1538,14 @@ int uwsgi_master_req_log(void) {
|
||||
if (ul->id) {
|
||||
goto next;
|
||||
}
|
||||
ul->func(ul, uwsgi.log_master_buf, rlen);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, 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);
|
||||
uwsgi_log_func_do(uwsgi.requested_log_req_encoders, NULL, uwsgi.log_master_buf, rlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1511,3 +1608,374 @@ void uwsgi_threaded_logger_spawn() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_register_log_encoder(char *name, char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *)) {
|
||||
struct uwsgi_log_encoder *old_ule = NULL, *ule = uwsgi.log_encoders;
|
||||
|
||||
while(ule) {
|
||||
if (!strcmp(ule->name, name)) {
|
||||
ule->func = func;
|
||||
return;
|
||||
}
|
||||
old_ule = ule;
|
||||
ule = ule->next;
|
||||
}
|
||||
|
||||
ule = uwsgi_calloc(sizeof(struct uwsgi_log_encoder));
|
||||
ule->name = name;
|
||||
ule->func = func;
|
||||
|
||||
if (old_ule) {
|
||||
old_ule->next = ule;
|
||||
}
|
||||
else {
|
||||
uwsgi.log_encoders = ule;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_log_encoder *uwsgi_log_encoder_by_name(char *name) {
|
||||
struct uwsgi_log_encoder *ule = uwsgi.log_encoders;
|
||||
while(ule) {
|
||||
if (!strcmp(name, ule->name)) return ule;
|
||||
ule = ule->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_setup_log_encoders() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.requested_log_encoders) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) *space = 0;
|
||||
char *use_for = strchr(usl->value, ':');
|
||||
if (use_for) *use_for = 0;
|
||||
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
|
||||
if (!ule) {
|
||||
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
|
||||
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
|
||||
if (use_for) {
|
||||
ule2->use_for = uwsgi_str(use_for+1);
|
||||
*use_for = ':';
|
||||
}
|
||||
// we use a copy
|
||||
if (space) {
|
||||
*space = ' ';
|
||||
ule2->args = uwsgi_str(space+1);
|
||||
}
|
||||
else {
|
||||
ule2->args = uwsgi_str("");
|
||||
}
|
||||
|
||||
usl->custom_ptr = ule2;
|
||||
uwsgi_log("[log-encoder] registered %s\n", usl->value);
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.requested_log_req_encoders) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) *space = 0;
|
||||
char *use_for = strchr(usl->value, ':');
|
||||
if (use_for) *use_for = 0;
|
||||
struct uwsgi_log_encoder *ule = uwsgi_log_encoder_by_name(usl->value);
|
||||
if (!ule) {
|
||||
uwsgi_log("log encoder \"%s\" not found\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
struct uwsgi_log_encoder *ule2 = uwsgi_malloc(sizeof(struct uwsgi_log_encoder));
|
||||
memcpy(ule2, ule, sizeof(struct uwsgi_log_encoder));
|
||||
if (use_for) {
|
||||
ule2->use_for = uwsgi_str(use_for+1);
|
||||
*use_for = ':';
|
||||
}
|
||||
// we use a copy
|
||||
if (space) {
|
||||
*space = ' ';
|
||||
ule2->args = uwsgi_str(space+1);
|
||||
}
|
||||
else {
|
||||
ule2->args = uwsgi_str("");
|
||||
}
|
||||
usl->custom_ptr = ule2;
|
||||
uwsgi_log("[log-req-encoder] registered %s\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZLIB
|
||||
static char *uwsgi_log_encoder_gzip(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
struct uwsgi_buffer *ub = uwsgi_gzip(msg, len);
|
||||
if (!ub) return NULL;
|
||||
*rlen = ub->pos;
|
||||
// avoid destruction
|
||||
char *buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *uwsgi_log_encoder_compress(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
size_t c_len = (size_t) compressBound(len);
|
||||
uLongf destLen = c_len;
|
||||
char *buf = uwsgi_malloc(c_len);
|
||||
if (compress((Bytef *) buf, &destLen, (Bytef *)msg, (uLong) len) == Z_OK) {
|
||||
*rlen = destLen;
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a prefix
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_prefix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a newline
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_nl(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + 1);
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
if (uwsgi_buffer_byte(ub, '\n')) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
really fast encoder adding only a suffix
|
||||
|
||||
*/
|
||||
static char *uwsgi_log_encoder_suffix(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
if (uwsgi_buffer_append(ub, ule->args, strlen(ule->args))) goto end;
|
||||
*rlen = ub->pos;
|
||||
buf = ub->buf;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
|
||||
char *ptr = ule->args;
|
||||
size_t remains = strlen(ptr);
|
||||
char *base = ptr;
|
||||
size_t base_len = 0;
|
||||
char *var = NULL;
|
||||
size_t var_len = 0;
|
||||
int status = 0; // 1 -> $ 2-> { end -> }
|
||||
while(remains--) {
|
||||
char b = *ptr++;
|
||||
if (status == 1) {
|
||||
if (b == '{') {
|
||||
status = 2;
|
||||
continue;
|
||||
}
|
||||
base_len+=2;
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
else if (status == 2) {
|
||||
if (b == '}') {
|
||||
status = 0;
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
|
||||
struct uwsgi_string_list *usl = uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(var, var_len, "", 0));
|
||||
usl->custom = 1;
|
||||
var = NULL;
|
||||
var_len = 0;
|
||||
base = NULL;
|
||||
base_len = 0;
|
||||
continue;
|
||||
}
|
||||
if (!var) var = (ptr-1);
|
||||
var_len++;
|
||||
continue;
|
||||
}
|
||||
// status == 0
|
||||
if (b == '$') {
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
if (!base) base = (ptr-1);
|
||||
base_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (base) {
|
||||
if (status == 1) {
|
||||
base_len+=2;
|
||||
}
|
||||
else if (status == 2) {
|
||||
base_len+=3;
|
||||
}
|
||||
uwsgi_string_new_list((struct uwsgi_string_list **) &ule->data, uwsgi_concat2n(base, base_len, "", 0));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// format: foo ${var} bar
|
||||
msg (the logline)
|
||||
msgnl (the logine with newline)
|
||||
unix (the time_t value)
|
||||
micros (current microseconds)
|
||||
strftime (strftime)
|
||||
*/
|
||||
static char *uwsgi_log_encoder_format(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
|
||||
if (!ule->configured) {
|
||||
uwsgi_log_encoder_parse_vars(ule);
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
|
||||
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
|
||||
char *buf = NULL;
|
||||
while(usl) {
|
||||
if (usl->custom) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
if (msg[len-1] == '\n') {
|
||||
if (uwsgi_buffer_append(ub, msg, len-1)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
if (uwsgi_buffer_append(ub, msg, len)) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
|
||||
}
|
||||
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9,"", 0);
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
if (uwsgi_buffer_append(ub, sftime, strftime_len)) goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *uwsgi_log_encoder_json(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
|
||||
if (!ule->configured) {
|
||||
uwsgi_log_encoder_parse_vars(ule);
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(strlen(ule->args) + len);
|
||||
struct uwsgi_string_list *usl = (struct uwsgi_string_list *) ule->data;
|
||||
char *buf = NULL;
|
||||
while(usl) {
|
||||
if (usl->custom) {
|
||||
if (!uwsgi_strncmp(usl->value, usl->len, "msg", 3)) {
|
||||
size_t msg_len = len;
|
||||
if (msg[len-1] == '\n') msg_len--;
|
||||
char *e_json = uwsgi_malloc(msg_len * 2);
|
||||
escape_json(msg, msg_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "msgnl", 5)) {
|
||||
char *e_json = uwsgi_malloc(len * 2);
|
||||
escape_json(msg, len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "unix", 4)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_now())) goto end;
|
||||
}
|
||||
else if (!uwsgi_strncmp(usl->value, usl->len, "micros", 6)) {
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto end;
|
||||
}
|
||||
else if (!uwsgi_starts_with(usl->value, usl->len, "strftime:", 9)) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
char *buf = uwsgi_concat2n(usl->value+9, usl->len-9, "", 0);
|
||||
int strftime_len = strftime(sftime, 64, buf, localtime(&now));
|
||||
free(buf);
|
||||
if (strftime_len > 0) {
|
||||
char *e_json = uwsgi_malloc(strftime_len * 2);
|
||||
escape_json(sftime, strftime_len, e_json);
|
||||
if (uwsgi_buffer_append(ub, e_json, strlen(e_json))){
|
||||
free(e_json);
|
||||
goto end;
|
||||
}
|
||||
free(e_json);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_append(ub, usl->value, usl->len)) goto end;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_log_encoders_register_embedded() {
|
||||
uwsgi_register_log_encoder("prefix", uwsgi_log_encoder_prefix);
|
||||
uwsgi_register_log_encoder("suffix", uwsgi_log_encoder_suffix);
|
||||
uwsgi_register_log_encoder("nl", uwsgi_log_encoder_nl);
|
||||
uwsgi_register_log_encoder("format", uwsgi_log_encoder_format);
|
||||
uwsgi_register_log_encoder("json", uwsgi_log_encoder_json);
|
||||
#ifdef UWSGI_ZLIB
|
||||
uwsgi_register_log_encoder("gzip", uwsgi_log_encoder_gzip);
|
||||
uwsgi_register_log_encoder("compress", uwsgi_log_encoder_compress);
|
||||
#endif
|
||||
}
|
||||
|
||||
+82
-41
@@ -222,8 +222,8 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
#elif defined(__FreeBSD__)
|
||||
if (!uwsgi.shared->ti.__tcpi_sacked) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
uwsgi.shared->load = (uint64_t) uwsgi.shared->ti.tcpi_unacked;
|
||||
@@ -242,12 +242,12 @@ int uwsgi_get_tcp_info(int fd) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long ) uwsgi.shared->load);
|
||||
uwsgi_log("asking emperor for reinforcements (backlog: %llu)...\n", (unsigned long long) uwsgi.shared->load);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uwsgi.shared->load >= uwsgi.shared->max_load) {
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long ) uwsgi.shared->load, (unsigned long long ) uwsgi.shared->max_load);
|
||||
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%llu/%llu) ***\n", fd, (unsigned long long) uwsgi.shared->load, (unsigned long long) uwsgi.shared->max_load);
|
||||
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
|
||||
}
|
||||
|
||||
@@ -306,7 +306,6 @@ int master_loop(char **argv, char **environ) {
|
||||
struct uwsgi_rb_timer *min_timeout;
|
||||
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
|
||||
|
||||
|
||||
if (uwsgi.procname_master) {
|
||||
uwsgi_set_processname(uwsgi.procname_master);
|
||||
}
|
||||
@@ -346,6 +345,11 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_signal_pipe[0]);
|
||||
|
||||
if (uwsgi.master_fifo) {
|
||||
uwsgi.master_fifo_fd = uwsgi_master_fifo();
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.spoolers) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
@@ -477,7 +481,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_gracefully_stop);
|
||||
// update exec touches
|
||||
struct uwsgi_string_list *usl = uwsgi.touch_exec;
|
||||
while(usl) {
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
@@ -489,16 +493,16 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_check_touches(uwsgi.touch_exec);
|
||||
// update signal touches
|
||||
usl = uwsgi.touch_signal;
|
||||
while(usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
while (usl) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
usl->len = strlen(usl->value);
|
||||
usl->custom_ptr = space + 1;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_check_touches(uwsgi.touch_signal);
|
||||
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
@@ -741,7 +745,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#endif
|
||||
|
||||
// resubscribe every 10 cycles by default
|
||||
if (( (uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (((uwsgi.subscriptions || uwsgi.subscriptions2) && ((uwsgi.master_cycles % uwsgi.subscribe_freq) == 0 || uwsgi.master_cycles == 1)) && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
uwsgi_subscribe_all(0, 0);
|
||||
}
|
||||
|
||||
@@ -765,40 +769,34 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_workers_reload);
|
||||
if (touched) {
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
continue;
|
||||
}
|
||||
uwsgi_log_verbose("*** %s has been touched... workers reload !!! ***\n", touched);
|
||||
uwsgi_reload_workers();
|
||||
continue;
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_chain_reload);
|
||||
if (touched) {
|
||||
if (uwsgi.status.chain_reloading == 0) {
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... chain reload !!! ***\n", touched);
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
uwsgi_log_verbose("*** %s has been touched... but chain reload is already running ***\n", touched);
|
||||
}
|
||||
}
|
||||
|
||||
// be sure to run it as the last touch check
|
||||
touched = uwsgi_check_touches(uwsgi.touch_exec);
|
||||
if (touched) {
|
||||
if (uwsgi_run_command( touched , NULL, -1) >= 0) {
|
||||
if (uwsgi_run_command(touched, NULL, -1) >= 0) {
|
||||
uwsgi_log_verbose("[uwsgi-touch-exec] running %s\n", touched);
|
||||
}
|
||||
}
|
||||
touched = uwsgi_check_touches(uwsgi.touch_signal);
|
||||
if (touched) {
|
||||
if (touched) {
|
||||
uint8_t signum = atoi(touched);
|
||||
uwsgi_route_signal(signum);
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
uwsgi_log_verbose("[uwsgi-touch-signal] raising %u\n", signum);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -815,12 +813,18 @@ int master_loop(char **argv, char **environ) {
|
||||
// reload gateways and daemons only on normal workflow (+outworld status)
|
||||
if (!uwsgi_instance_is_reloading && !uwsgi_instance_is_dying) {
|
||||
|
||||
if (uwsgi_master_check_emperor_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid)) continue;
|
||||
if (uwsgi_master_check_emperor_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_spoolers_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_mules_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_gateways_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_daemons_death(diedpid))
|
||||
continue;
|
||||
if (uwsgi_master_check_cron_death(diedpid))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -885,8 +889,9 @@ next:
|
||||
// ok, if we are reloading or dying, just continue the master loop
|
||||
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
|
||||
if (!uwsgi.workers[thewid].cursed_at) uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
|
||||
if (!uwsgi.workers[thewid].cursed_at)
|
||||
uwsgi.workers[thewid].cursed_at = uwsgi_now();
|
||||
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now() - uwsgi.workers[thewid].cursed_at));
|
||||
uwsgi.workers[thewid].cursed_at = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -905,6 +910,11 @@ next:
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
|
||||
// noop
|
||||
}
|
||||
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_BRUTAL_RELOAD_CODE) {
|
||||
uwsgi_log("!!! inconsistent state reported by worker %d (pid: %d) !!!\n", thewid, (int) diedpid);
|
||||
reap_them_all(0);
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi.workers[thewid].manage_next_request) {
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
@@ -959,3 +969,34 @@ next:
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
void uwsgi_reload_workers() {
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
|
||||
void uwsgi_chain_reload() {
|
||||
if (!uwsgi.status.chain_reloading) {
|
||||
uwsgi_log_verbose("chain reload starting...\n");
|
||||
uwsgi.status.chain_reloading = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log_verbose("chain reload already running...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_brutally_reload_workers() {
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_log_verbose("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
uwsgi_curse(i, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,17 @@ int uwsgi_master_check_reload(char **argv) {
|
||||
// check for chain reload
|
||||
void uwsgi_master_check_chain() {
|
||||
if (!uwsgi.status.chain_reloading) return;
|
||||
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
|
||||
int i;
|
||||
int needed_procs = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
|
||||
needed_procs++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.status.chain_reloading > needed_procs) {
|
||||
uwsgi.status.chain_reloading = 0;
|
||||
uwsgi_log_verbose("chain reloading complete\n");
|
||||
}
|
||||
int i;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
|
||||
@@ -18,6 +18,10 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
|
||||
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
// stats server ?
|
||||
if (uwsgi.stats && uwsgi.stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.stats_fd) {
|
||||
|
||||
+115
-16
@@ -115,7 +115,43 @@ int uwsgi_calc_cheaper(void) {
|
||||
|
||||
last_check = now;
|
||||
|
||||
int needed_workers = uwsgi.cheaper_algo();
|
||||
int ignore_algo = 0;
|
||||
int needed_workers = 0;
|
||||
|
||||
// first check if memory usage is not exceeded
|
||||
if (uwsgi.cheaper_rss_limit_soft) {
|
||||
unsigned long long total_rss = 0;
|
||||
int i;
|
||||
int active_workers = 0;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (!uwsgi.workers[i].cheaped) {
|
||||
total_rss += uwsgi.workers[i].rss_size;
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
if (uwsgi.cheaper_rss_limit_hard && active_workers > 1 && total_rss >= uwsgi.cheaper_rss_limit_hard) {
|
||||
uwsgi_log("cheaper hard rss memory limit exceeded, cheap one of %d workers\n", active_workers);
|
||||
needed_workers = -1;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
else if (total_rss >= uwsgi.cheaper_rss_limit_soft) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("cheaper soft rss memory limit exceeded, can't spawn more workers\n");
|
||||
#endif
|
||||
ignore_algo = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// then check for fifo
|
||||
if (uwsgi.cheaper_fifo_delta != 0) {
|
||||
if (!ignore_algo) {
|
||||
needed_workers = uwsgi.cheaper_fifo_delta;
|
||||
ignore_algo = 1;
|
||||
}
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
}
|
||||
|
||||
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
@@ -152,6 +188,11 @@ int uwsgi_calc_cheaper(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fake algo to allow control with the fifo
|
||||
int uwsgi_cheaper_algo_manual(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
|
||||
@@ -326,23 +367,30 @@ void uwsgi_reload(char **argv) {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
// 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++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
if (!uwsgi.master_is_reforked) {
|
||||
|
||||
// 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++) {
|
||||
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("fork()'ing uWSGI...\n");
|
||||
}
|
||||
|
||||
// call master cleanup hooks
|
||||
uwsgi_master_cleanup_hooks();
|
||||
|
||||
// call atexit user exec
|
||||
uwsgi_exec_atexit();
|
||||
|
||||
if (uwsgi.exit_on_reload) {
|
||||
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
uwsgi_log("binary reloading uWSGI...\n");
|
||||
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("chdir()");
|
||||
@@ -529,6 +577,7 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
|
||||
}
|
||||
|
||||
|
||||
@@ -1485,3 +1534,53 @@ void uwsgi_add_reload_fds() {
|
||||
add_reload_fds(uwsgi.reload_on_fd, "graceful");
|
||||
add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
|
||||
}
|
||||
|
||||
void uwsgi_refork_master() {
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("uwsgi_refork_master()/fork()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
|
||||
return;
|
||||
}
|
||||
|
||||
// detach from the old master
|
||||
setsid();
|
||||
|
||||
uwsgi.master_is_reforked = 1;
|
||||
uwsgi_reload(uwsgi.argv);
|
||||
// never here
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_increase() {
|
||||
uwsgi.cheaper_fifo_delta++;
|
||||
}
|
||||
|
||||
void uwsgi_cheaper_decrease() {
|
||||
uwsgi.cheaper_fifo_delta--;
|
||||
}
|
||||
|
||||
void uwsgi_go_cheap() {
|
||||
int i;
|
||||
int waitpid_status;
|
||||
if (uwsgi.status.is_cheap) return;
|
||||
uwsgi_log_verbose("going cheap...\n");
|
||||
uwsgi.status.is_cheap = 1;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi.workers[i].cheaped = 1;
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_go_cheap()/waitpid()");
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
}
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
|
||||
|
||||
to simplify setups (expecially because the mount command could not be available in
|
||||
the initial phase of jailing, we need an api to mount/umount filesystems
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, int flags);
|
||||
int uwsgi_umount(char *where, int flags);
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
char *key;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
static struct uwsgi_mount_flag umflags[] = {
|
||||
#ifdef MS_BIND
|
||||
{"bind", MS_BIND},
|
||||
#endif
|
||||
#ifdef MS_DIRSYNC
|
||||
{"dirsync", MS_DIRSYNC},
|
||||
#endif
|
||||
#ifdef MS_MANDLOCK
|
||||
{"mandlock", MS_MANDLOCK},
|
||||
#endif
|
||||
#ifdef MS_MOVE
|
||||
{"move", MS_MOVE},
|
||||
#endif
|
||||
#ifdef MS_NOATIME
|
||||
{"noatime", MS_NOATIME},
|
||||
#endif
|
||||
#ifdef MS_NODEV
|
||||
{"nodev", MS_NODEV},
|
||||
#endif
|
||||
#ifdef MS_NOEXEC
|
||||
{"noexec", MS_NOEXEC},
|
||||
#endif
|
||||
#ifdef MS_RDONLY
|
||||
{"rdonly", MS_RDONLY},
|
||||
{"readonly", MS_RDONLY},
|
||||
{"ro", MS_RDONLY},
|
||||
#endif
|
||||
#ifdef MS_REMOUNT
|
||||
{"remount", MS_REMOUNT},
|
||||
#endif
|
||||
#ifdef MS_SYNCHRONOUS
|
||||
{"sync", MS_SYNCHRONOUS},
|
||||
#endif
|
||||
#ifdef MNT_FORCE
|
||||
{"force", MNT_FORCE},
|
||||
#endif
|
||||
#ifdef MNT_DETACH
|
||||
{"detach", MNT_DETACH},
|
||||
#endif
|
||||
#ifdef MS_REC
|
||||
{"rec", MS_REC},
|
||||
{"recursive", MS_REC},
|
||||
#endif
|
||||
#ifdef MS_PRIVATE
|
||||
{"private", MS_PRIVATE},
|
||||
#endif
|
||||
#ifdef MS_SHARED
|
||||
{"shared", MS_SHARED},
|
||||
#endif
|
||||
#ifdef MNT_RDONLY
|
||||
{"rdonly", MNT_RDONLY},
|
||||
{"readonly", MNT_RDONLY},
|
||||
{"ro", MNT_RDONLY},
|
||||
#endif
|
||||
#ifdef MNT_NOEXEC
|
||||
{"noexec", MNT_NOEXEC},
|
||||
#endif
|
||||
#ifdef MNT_NOSUID
|
||||
{"nosuid", MNT_NOSUID},
|
||||
#endif
|
||||
#ifdef MNT_NOATIME
|
||||
{"noatime", MNT_NOATIME},
|
||||
#endif
|
||||
#ifdef MNT_SNAPSHOT
|
||||
{"snapshot", MNT_SNAPSHOT},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
struct uwsgi_mount_flag *umf = umflags;
|
||||
while(umf->key) {
|
||||
if (!strcmp(umf->key, mflag)) return umf->value;
|
||||
umf++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
#ifdef __FreeBSD__
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown mount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
#elif defined(__FreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
iov[1].iov_base = fs;
|
||||
iov[1].iov_len = strlen(fs) + 1;
|
||||
|
||||
iov[2].iov_base = "fspath";
|
||||
iov[2].iov_len = 7;
|
||||
iov[3].iov_base = where;
|
||||
iov[3].iov_len = strlen(where) + 1;
|
||||
|
||||
iov[4].iov_base = "target";
|
||||
iov[4].iov_len = 7;
|
||||
iov[5].iov_base = what;
|
||||
iov[5].iov_len = strlen(what) + 1;
|
||||
|
||||
return nmount(iov, 6, (int) mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount(char *where, char *flags) {
|
||||
unsigned long mountflags = 0;
|
||||
if (!flags) goto parsed;
|
||||
char *mflags = uwsgi_str(flags);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mflags, ",", p, ctx) {
|
||||
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
|
||||
if (!flag) {
|
||||
uwsgi_log("unknown umount flag \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
mountflags |= flag;
|
||||
}
|
||||
free(mflags);
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
// we need a special case for recursive umount
|
||||
if (mountflags & MS_REC) {
|
||||
mountflags &= ~MS_REC;
|
||||
int unmounted = 1;
|
||||
char *slashed = uwsgi_concat2(where, "/");
|
||||
while (unmounted) {
|
||||
unmounted = 0;
|
||||
FILE *procmounts = fopen("/proc/self/mounts", "r");
|
||||
if (!procmounts) {
|
||||
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
char line[1024];
|
||||
while (fgets(line, 1024, procmounts) != NULL) {
|
||||
char *delim0 = strchr(line, ' ');
|
||||
if (!delim0) continue;
|
||||
delim0++;
|
||||
char *delim1 = strchr(delim0, ' ');
|
||||
if (!delim1) continue;
|
||||
*delim1 = 0;
|
||||
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
|
||||
continue;
|
||||
unmountable:
|
||||
if (!umount2(delim0, mountflags)) unmounted++;
|
||||
}
|
||||
fclose(procmounts);
|
||||
}
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__)
|
||||
return unmount(where, mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_mount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *fs = tmp_arg;
|
||||
char *what = strchr(fs, ' ');
|
||||
if (!what) goto error;
|
||||
*what = 0; what++;
|
||||
char *where = strchr(what, ' ');
|
||||
if (!where) goto error;
|
||||
*where = 0; where++;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_mount(fs, what, where, flags)) {
|
||||
uwsgi_error("uwsgi_mount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
error:
|
||||
free(tmp_arg);
|
||||
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uwsgi_umount_hook(char *arg) {
|
||||
char *tmp_arg = uwsgi_str(arg);
|
||||
char *where = tmp_arg;
|
||||
char *flags = strchr(where, ' ');
|
||||
if (flags) {
|
||||
*flags = 0; flags++;
|
||||
}
|
||||
if (uwsgi_umount(where, flags)) {
|
||||
uwsgi_error("uwsgi_umount()");
|
||||
free(tmp_arg);
|
||||
return -1;
|
||||
}
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
}
|
||||
+2
-4
@@ -453,8 +453,8 @@ void uwsgi_setup_mules_and_farms() {
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
|
||||
|
||||
char *p = strtok(mules_list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(mules_list, ",", p, ctx) {
|
||||
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
|
||||
if (!um) {
|
||||
uwsgi_log("invalid mule id: %s\n", p);
|
||||
@@ -462,8 +462,6 @@ void uwsgi_setup_mules_and_farms() {
|
||||
}
|
||||
|
||||
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
|
||||
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
|
||||
|
||||
|
||||
+3
-1
@@ -14,7 +14,9 @@ static void uwsgi_plugin_parse_section(char *filename) {
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
if (!strcmp(p, "requires")) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
if (!plugin_already_loaded(equal+1)) {
|
||||
uwsgi_load_plugin(-1, equal + 1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
p = strtok_r(NULL, "\n", &ctx);
|
||||
|
||||
+90
-1
@@ -180,6 +180,10 @@ int uwsgi_apply_routes_do(struct uwsgi_route *routes, struct wsgi_request *wsgi_
|
||||
r_goto = &wsgi_req->error_route_goto;
|
||||
r_pc = &wsgi_req->error_route_pc;
|
||||
}
|
||||
else if (routes == uwsgi.response_routes) {
|
||||
r_goto = &wsgi_req->response_route_goto;
|
||||
r_pc = &wsgi_req->response_route_pc;
|
||||
}
|
||||
else if (routes == uwsgi.final_routes) {
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
@@ -306,6 +310,20 @@ int uwsgi_apply_error_routes(struct wsgi_request *wsgi_req) {
|
||||
return uwsgi_apply_routes_do(uwsgi.error_routes, wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
int uwsgi_apply_response_routes(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (!uwsgi.response_routes) return 0;
|
||||
if (wsgi_req->response_routes_applied) return 0;
|
||||
|
||||
// do not forget to check it !!!
|
||||
if (wsgi_req->is_response_routing) return 0;
|
||||
|
||||
wsgi_req->is_response_routing = 1;
|
||||
|
||||
int ret = uwsgi_apply_routes_do(uwsgi.response_routes, wsgi_req, NULL, 0);
|
||||
wsgi_req->response_routes_applied = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
@@ -337,6 +355,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
ur = uwsgi.error_routes;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
|
||||
ur = uwsgi.response_routes;
|
||||
}
|
||||
uint64_t pos = 0;
|
||||
while(ur) {
|
||||
old_ur = ur;
|
||||
@@ -354,6 +375,9 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "error", 5)) {
|
||||
uwsgi.error_routes = ur;
|
||||
}
|
||||
else if (!uwsgi_starts_with(opt, strlen(opt), "response", 8)) {
|
||||
uwsgi.response_routes = ur;
|
||||
}
|
||||
else {
|
||||
uwsgi.routes = ur;
|
||||
}
|
||||
@@ -701,6 +725,11 @@ static int uwsgi_router_goto_func(struct wsgi_request *wsgi_req, struct uwsgi_ro
|
||||
r_goto = &wsgi_req->final_route_goto;
|
||||
r_pc = &wsgi_req->final_route_pc;
|
||||
}
|
||||
else if (wsgi_req->is_response_routing) {
|
||||
routes = uwsgi.response_routes;
|
||||
r_goto = &wsgi_req->response_route_goto;
|
||||
r_pc = &wsgi_req->response_route_pc;
|
||||
}
|
||||
while(routes) {
|
||||
if (!routes->label) goto next;
|
||||
if (!uwsgi_strncmp(routes->label, routes->label_len, ub->buf, ub->pos)) {
|
||||
@@ -806,6 +835,31 @@ static int uwsgi_router_remheader(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clearheaders route
|
||||
static int uwsgi_router_clearheaders_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, ub->buf, ub->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_clearheaders(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_clearheaders_func;
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// signal route
|
||||
@@ -1630,6 +1684,8 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("addheader", uwsgi_router_addheader);
|
||||
uwsgi_register_router("delheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("remheader", uwsgi_router_remheader);
|
||||
uwsgi_register_router("clearheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("resetheaders", uwsgi_router_clearheaders);
|
||||
uwsgi_register_router("signal", uwsgi_router_signal);
|
||||
uwsgi_register_router("send", uwsgi_router_send);
|
||||
uwsgi_register_router("send-crnl", uwsgi_router_send_crnl);
|
||||
@@ -1750,6 +1806,7 @@ struct uwsgi_route_condition *uwsgi_register_route_condition(char *name, int (*f
|
||||
}
|
||||
|
||||
void uwsgi_routing_dump() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
if (!routes) goto next;
|
||||
uwsgi_log("*** dumping internal routing table ***\n");
|
||||
@@ -1784,8 +1841,25 @@ next:
|
||||
}
|
||||
uwsgi_log("*** end of the internal error routing table ***\n");
|
||||
next2:
|
||||
routes = uwsgi.response_routes;
|
||||
if (!routes) goto next3;
|
||||
uwsgi_log("*** dumping internal response routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
|
||||
}
|
||||
else if (!routes->subject_str && !routes->if_func) {
|
||||
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
|
||||
}
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal response routing table ***\n");
|
||||
next3:
|
||||
routes = uwsgi.final_routes;
|
||||
if (!routes) return;
|
||||
if (!routes) goto next4;
|
||||
uwsgi_log("*** dumping internal final routing table ***\n");
|
||||
while(routes) {
|
||||
if (routes->label) {
|
||||
@@ -1800,5 +1874,20 @@ next2:
|
||||
routes = routes->next;
|
||||
}
|
||||
uwsgi_log("*** end of the internal final routing table ***\n");
|
||||
|
||||
next4:
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid collect header syntax, must be <header> <var>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
usl->custom = strlen(usl->value);
|
||||
*space = ' ';
|
||||
usl->custom_ptr = space+1;
|
||||
usl->custom2 = strlen(space+1);
|
||||
uwsgi_log("collecting header %.*s to var %s\n", usl->custom, usl->value, usl->custom_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+9
-6
@@ -4,6 +4,11 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
// sendfile() abstraction
|
||||
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
|
||||
if (uwsgi.disable_sendfile) goto no_sendfile;
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
off_t sf_len = len;
|
||||
@@ -18,12 +23,11 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#else
|
||||
// for platform not supporting sendfile we need to rely on boring read/write
|
||||
// generally that platforms have very low memory, so use a 8k buffer
|
||||
char buf[8192];
|
||||
#endif
|
||||
|
||||
no_sendfile:
|
||||
if (pos > 0) {
|
||||
if (lseek(filefd, pos, SEEK_SET)) {
|
||||
if (lseek(filefd, pos, SEEK_SET) < 0) {
|
||||
uwsgi_error("uwsgi_sendfile_do()/seek()");
|
||||
return -1;
|
||||
}
|
||||
@@ -34,7 +38,6 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
return write(sockfd, buf, rlen);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
+33
-4
@@ -187,6 +187,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
@@ -1645,8 +1653,8 @@ void uwsgi_map_sockets() {
|
||||
}
|
||||
if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
|
||||
enabled = 0;
|
||||
char *p = strtok(colon + 1, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(colon + 1, ",", p, ctx) {
|
||||
int w = atoi(p);
|
||||
if (w < 1 || w > uwsgi.numproc) {
|
||||
uwsgi_log("invalid worker num: %d\n", w);
|
||||
@@ -1657,7 +1665,6 @@ void uwsgi_map_sockets() {
|
||||
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
|
||||
break;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1785,7 +1792,8 @@ void uwsgi_bind_sockets() {
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
uwsgi_log("WARNING: unable to remap stdin, /dev/null not available\n");
|
||||
goto stdin_done;
|
||||
}
|
||||
if (fd != 0) {
|
||||
if (dup2(fd, 0) < 0) {
|
||||
@@ -1803,6 +1811,8 @@ void uwsgi_bind_sockets() {
|
||||
|
||||
}
|
||||
|
||||
stdin_done:
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -1955,3 +1965,22 @@ void uwsgi_tcp_nodelay(int fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int uwsgi_accept(int server_fd) {
|
||||
struct sockaddr_un client_src;
|
||||
memset(&client_src, 0, sizeof(struct sockaddr_un));
|
||||
socklen_t client_src_len = 0;
|
||||
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
return accept4(server_fd, (struct sockaddr *) &client_src, &client_src_len, SOCK_NONBLOCK);
|
||||
#elif defined(__linux__)
|
||||
int client_fd = accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd >= 0) {
|
||||
uwsgi_socket_nb(client_fd);
|
||||
}
|
||||
return client_fd;
|
||||
#else
|
||||
return accept(server_fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,11 @@ SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen,
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
|
||||
#else
|
||||
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
|
||||
#endif
|
||||
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
|
||||
return sess;
|
||||
}
|
||||
|
||||
+328
-29
@@ -344,6 +344,8 @@ void uwsgi_as_root() {
|
||||
}
|
||||
#endif
|
||||
|
||||
int in_jail = 0;
|
||||
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
if (uwsgi.unshare && !uwsgi.reloads) {
|
||||
|
||||
@@ -354,9 +356,221 @@ void uwsgi_as_root() {
|
||||
else {
|
||||
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare);
|
||||
}
|
||||
in_jail = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
if (uwsgi.jail && !uwsgi.reloads) {
|
||||
|
||||
struct jail ujail;
|
||||
char *jarg = uwsgi_str(uwsgi.jail);
|
||||
char *j_hostname = NULL;
|
||||
char *j_name = NULL;
|
||||
|
||||
char *space = strchr(jarg, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
j_hostname = space + 1;
|
||||
space = strchr(j_hostname, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
j_name = space + 1;
|
||||
}
|
||||
}
|
||||
ujail.version = JAIL_API_VERSION;
|
||||
ujail.path = jarg;
|
||||
ujail.hostname = j_hostname ? j_hostname : "";
|
||||
ujail.jailname = j_name;
|
||||
ujail.ip4s = 0;
|
||||
ujail.ip6s = 0;
|
||||
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip4) {
|
||||
ujail.ip4s++;
|
||||
}
|
||||
struct in_addr *saddr = uwsgi_calloc(sizeof(struct in_addr) * ujail.ip4s);
|
||||
int i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip4) {
|
||||
if (!inet_pton(AF_INET, usl->value, &saddr[i].s_addr)) {
|
||||
uwsgi_error("jail()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ujail.ip4 = saddr;
|
||||
#ifdef AF_INET6
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip6) {
|
||||
ujail.ip6s++;
|
||||
}
|
||||
|
||||
struct in6_addr *saddr6 = uwsgi_calloc(sizeof(struct in6_addr) * ujail.ip6s);
|
||||
i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail_ip6) {
|
||||
if (!inet_pton(AF_INET6, usl->value, &saddr6[i].s6_addr)) {
|
||||
uwsgi_error("jail()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ujail.ip6 = saddr6;
|
||||
#endif
|
||||
|
||||
int jail_id = jail(&ujail);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jail()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.jidfile) {
|
||||
if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
|
||||
uwsgi_log("unable to write jidfile\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_HAS_FREEBSD_LIBJAIL
|
||||
if (uwsgi.jail_attach && !uwsgi.reloads) {
|
||||
struct jailparam jparam;
|
||||
uwsgi_log("attaching to FreeBSD jail %s ...\n", uwsgi.jail_attach);
|
||||
if (!is_a_number(uwsgi.jail_attach)) {
|
||||
if (jailparam_init(&jparam, "name")) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (jailparam_init(&jparam, "jid")) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
jailparam_import(&jparam, uwsgi.jail_attach);
|
||||
int jail_id = jailparam_set(&jparam, 1, JAIL_UPDATE|JAIL_ATTACH);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jailparam_set()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
jailparam_free(&jparam, 1);
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
|
||||
if (uwsgi.jail2 && !uwsgi.reloads) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
unsigned nparams = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail2) {
|
||||
nparams++;
|
||||
}
|
||||
struct jailparam *params = uwsgi_malloc(sizeof(struct jailparam) * nparams);
|
||||
int i = 0;
|
||||
uwsgi_foreach(usl, uwsgi.jail2) {
|
||||
uwsgi_log("FreeBSD libjail applying %s\n", usl->value);
|
||||
char *equal = strchr(usl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
}
|
||||
if (jailparam_init(¶ms[i], usl->value)) {
|
||||
uwsgi_error("jailparam_init()");
|
||||
exit(1);
|
||||
}
|
||||
if (equal) {
|
||||
jailparam_import(¶ms[i], equal+1);
|
||||
*equal = '=';
|
||||
}
|
||||
else {
|
||||
jailparam_import(¶ms[i], "1");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
int jail_id = jailparam_set(params, nparams, JAIL_CREATE|JAIL_ATTACH);
|
||||
if (jail_id < 0) {
|
||||
uwsgi_error("jailparam_set()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
jailparam_free(params, nparams);
|
||||
|
||||
if (uwsgi.jidfile) {
|
||||
if (uwsgi_write_intfile(uwsgi.jidfile, jail_id)) {
|
||||
uwsgi_log("unable to write jidfile\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("--- running in FreeBSD jail %d ---\n", jail_id);
|
||||
in_jail = 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (in_jail) {
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_post_jail) {
|
||||
uwsgi_log("mounting \"%s\" (post-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_post_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (post-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.exec_post_jail) {
|
||||
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.refork_post_jail) {
|
||||
uwsgi_log("re-fork()ing...\n");
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
}
|
||||
if (pid > 0) {
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
sigprocmask(SIG_BLOCK, &smask, NULL);
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->post_jail) {
|
||||
uwsgi.gp[i]->post_jail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.chroot && !uwsgi.reloads) {
|
||||
if (!uwsgi.master_as_root)
|
||||
@@ -372,6 +586,52 @@ void uwsgi_as_root() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (uwsgi.pivot_root && !uwsgi.reloads) {
|
||||
char *arg = uwsgi_str(uwsgi.pivot_root);
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid pivot_root syntax, new_root and put_old must be separated by a space\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
if (chdir(arg)) {
|
||||
uwsgi_error("pivot_root()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
space += 1+strlen(arg);
|
||||
if (space[0] == '/') space++;
|
||||
if (pivot_root(".", space)) {
|
||||
uwsgi_error("pivot_root()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG]) {
|
||||
uwsgi_log("*** Warning, on linux system you have to bind-mount the /proc fs in your chroot to get memory debug/report.\n");
|
||||
}
|
||||
free(arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.refork_as_root) {
|
||||
uwsgi_log("re-fork()ing...\n");
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
exit(1);
|
||||
}
|
||||
if (pid > 0) {
|
||||
// block all signals
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
sigprocmask(SIG_BLOCK, &smask, NULL);
|
||||
int status;
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.wait_for_interface) {
|
||||
@@ -396,7 +656,22 @@ void uwsgi_as_root() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_root, "as root", 1);
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_as_root) {
|
||||
uwsgi_log("mounting \"%s\" (as root)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_as_root) {
|
||||
uwsgi_log("un-mounting \"%s\" (as root)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// now run the scripts needed by root
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_root) {
|
||||
@@ -614,6 +889,8 @@ void uwsgi_as_root() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_user, "as user", 1);
|
||||
|
||||
// now run the scripts needed by the user
|
||||
uwsgi_foreach(usl, uwsgi.exec_as_user) {
|
||||
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
|
||||
@@ -627,6 +904,7 @@ void uwsgi_as_root() {
|
||||
uwsgi_foreach(usl, uwsgi.call_as_user) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,6 +1721,11 @@ int uwsgi_file_exists(char *filename) {
|
||||
return !access(filename, R_OK);
|
||||
}
|
||||
|
||||
int uwsgi_file_executable(char *filename) {
|
||||
// TODO check for http url or stdin
|
||||
return !access(filename, R_OK|X_OK);
|
||||
}
|
||||
|
||||
char *magic_sub(char *buffer, size_t len, size_t *size, char *magic_table[]) {
|
||||
|
||||
size_t i;
|
||||
@@ -1596,14 +1879,12 @@ char *uwsgi_get_optname_by_index(int index) {
|
||||
int uwsgi_list_has_num(char *list, int num) {
|
||||
|
||||
char *list2 = uwsgi_concat2(list, "");
|
||||
|
||||
char *p = strtok(list2, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, ",", p, ctx) {
|
||||
if (atoi(p) == num) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -1613,14 +1894,12 @@ int uwsgi_list_has_num(char *list, int num) {
|
||||
int uwsgi_list_has_str(char *list, char *str) {
|
||||
|
||||
char *list2 = uwsgi_str(list);
|
||||
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
if (!strcasecmp(p, str)) {
|
||||
free(list2);
|
||||
return 1;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -2003,9 +2282,19 @@ void uwsgi_sig_pause() {
|
||||
sigsuspend(&mask);
|
||||
}
|
||||
|
||||
char *uwsgi_binsh() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.binsh) {
|
||||
if (uwsgi_file_executable(usl->value)) {
|
||||
return usl->value;
|
||||
}
|
||||
}
|
||||
return "/bin/sh";
|
||||
}
|
||||
|
||||
void uwsgi_exec_command_with_args(char *cmdline) {
|
||||
char *argv[4];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = cmdline;
|
||||
argv[3] = NULL;
|
||||
@@ -2025,7 +2314,7 @@ static int uwsgi_run_command_do(char *command, char *arg) {
|
||||
#endif
|
||||
|
||||
if (command == NULL) {
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = arg;
|
||||
argv[3] = NULL;
|
||||
@@ -2178,12 +2467,12 @@ pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = command;
|
||||
argv[3] = NULL;
|
||||
|
||||
execvp("/bin/sh", argv);
|
||||
execvp(uwsgi_binsh(), argv);
|
||||
|
||||
uwsgi_error("execvp()");
|
||||
//never here
|
||||
@@ -2473,14 +2762,12 @@ static int uwsgi_get_unshare_id(char *name) {
|
||||
void uwsgi_build_unshare(char *what, int *mask) {
|
||||
|
||||
char *list = uwsgi_str(what);
|
||||
|
||||
char *p = strtok(list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list, ",", p, ctx) {
|
||||
int u_id = uwsgi_get_unshare_id(p);
|
||||
if (u_id != -1) {
|
||||
*mask |= u_id;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
@@ -2569,8 +2856,8 @@ void uwsgi_build_cap(char *what) {
|
||||
int pos = 0;
|
||||
uwsgi.cap_count = 0;
|
||||
|
||||
char *p = strtok(caps, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(caps, ",", p, ctx) {
|
||||
if (is_a_number(p)) {
|
||||
uwsgi.cap_count++;
|
||||
}
|
||||
@@ -2580,15 +2867,14 @@ void uwsgi_build_cap(char *what) {
|
||||
uwsgi.cap_count++;
|
||||
}
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(caps);
|
||||
|
||||
uwsgi.cap = uwsgi_malloc(sizeof(cap_value_t) * uwsgi.cap_count);
|
||||
|
||||
caps = uwsgi_str(what);
|
||||
p = strtok(caps, ",");
|
||||
while (p != NULL) {
|
||||
ctx = NULL;
|
||||
uwsgi_foreach_token(caps, ",", p, ctx) {
|
||||
if (is_a_number(p)) {
|
||||
cap_id = atoi(p);
|
||||
}
|
||||
@@ -2600,7 +2886,6 @@ void uwsgi_build_cap(char *what) {
|
||||
uwsgi_log("setting capability %s [%d]\n", p, cap_id);
|
||||
pos++;
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(caps);
|
||||
|
||||
@@ -2989,12 +3274,20 @@ char *uwsgi_chomp2(char *str) {
|
||||
|
||||
|
||||
int uwsgi_tmpfd() {
|
||||
int fd = -1;
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
#ifdef O_TMPFILE
|
||||
fd = open(tmpdir, O_TMPFILE | O_RDWR);
|
||||
if (fd >= 0) {
|
||||
return fd;
|
||||
}
|
||||
// fallback to old style
|
||||
#endif
|
||||
char *template = uwsgi_concat2(tmpdir, "/uwsgiXXXXXX");
|
||||
int fd = mkstemp(template);
|
||||
fd = mkstemp(template);
|
||||
unlink(template);
|
||||
free(template);
|
||||
return fd;
|
||||
@@ -3045,15 +3338,21 @@ void uwsgi_emulate_cow_for_apps(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_write_intfile(char *filename, int n) {
|
||||
FILE *pidfile = fopen(filename, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", n) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_write_pidfile(char *pidfile_name) {
|
||||
uwsgi_log("writing pidfile to %s\n", pidfile_name);
|
||||
FILE *pidfile = fopen(pidfile_name, "w");
|
||||
if (!pidfile) {
|
||||
uwsgi_error_open(pidfile_name);
|
||||
exit(1);
|
||||
}
|
||||
if (fprintf(pidfile, "%d\n", (int) getpid()) <= 0 || ferror(pidfile) || fclose(pidfile)) {
|
||||
if (uwsgi_write_intfile(pidfile_name, (int) getpid())) {
|
||||
uwsgi_log("could not write pidfile.\n");
|
||||
}
|
||||
}
|
||||
|
||||
+263
-38
@@ -199,7 +199,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
{"vassals-include", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
@@ -226,6 +227,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"locks", required_argument, 0, "create the specified number of shared locks", uwsgi_opt_set_int, &uwsgi.locks, 0},
|
||||
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"persistent-ipcsem", no_argument, 0, "do not remove ipcsem's on shutdown", uwsgi_opt_true, &uwsgi.persistent_ipcsem, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
|
||||
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
@@ -261,7 +263,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"spooler-external", required_argument, 0, "map spoolers requests to a spooler directory managed by an external instance", uwsgi_opt_add_spooler, (void *) UWSGI_SPOOLER_EXTERNAL, UWSGI_OPT_MASTER},
|
||||
{"spooler-ordered", no_argument, 0, "try to order the execution of spooler tasks", uwsgi_opt_true, &uwsgi.spooler_ordered, 0},
|
||||
{"spooler-chdir", required_argument, 0, "chdir() to specified directory before each spooler task", uwsgi_opt_set_str, &uwsgi.spooler_chdir, 0},
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, 0},
|
||||
{"spooler-processes", required_argument, 0, "set the number of processes for spoolers", uwsgi_opt_set_int, &uwsgi.spooler_numproc, UWSGI_OPT_IMMEDIATE},
|
||||
{"spooler-quiet", no_argument, 0, "do not be verbose with spooler tasks", uwsgi_opt_true, &uwsgi.spooler_quiet, 0},
|
||||
{"spooler-max-tasks", required_argument, 0, "set the maximum number of tasks to run before recycling a spooler", uwsgi_opt_set_int, &uwsgi.spooler_max_tasks, 0},
|
||||
{"spooler-harakiri", required_argument, 0, "set harakiri timeout for spooler tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_SPOOLER_HARAKIRI, 0},
|
||||
@@ -288,6 +290,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"pidfile", required_argument, 0, "create pidfile (before privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile, 0},
|
||||
{"pidfile2", required_argument, 0, "create pidfile (after privileges drop)", uwsgi_opt_set_str, &uwsgi.pidfile2, 0},
|
||||
{"chroot", required_argument, 0, "chroot() to the specified directory", uwsgi_opt_set_str, &uwsgi.chroot, 0},
|
||||
#ifdef __linux__
|
||||
{"pivot-root", required_argument, 0, "pivot_root() to the specified directories (new_root and put_old must be separated with a space)", uwsgi_opt_set_str, &uwsgi.pivot_root, 0},
|
||||
{"pivot_root", required_argument, 0, "pivot_root() to the specified directories (new_root and put_old must be separated with a space)", uwsgi_opt_set_str, &uwsgi.pivot_root, 0},
|
||||
#endif
|
||||
|
||||
{"uid", required_argument, 0, "setuid to the specified user/uid", uwsgi_opt_set_uid, NULL, 0},
|
||||
{"gid", required_argument, 0, "setgid to the specified group/gid", uwsgi_opt_set_gid, NULL, 0},
|
||||
{"add-gid", required_argument, 0, "add the specified group id to the process credentials", uwsgi_opt_add_string_list, &uwsgi.additional_gids, 0},
|
||||
@@ -299,10 +306,40 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
{"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0},
|
||||
{"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0},
|
||||
{"jail-ip6", required_argument, 0, "add an ipv6 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip6, 0},
|
||||
{"jidfile", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0},
|
||||
{"jid-file", required_argument, 0, "save the jid of a FreeBSD jail in the specified file", uwsgi_opt_set_str, &uwsgi.jidfile, 0},
|
||||
#ifdef UWSGI_HAS_FREEBSD_LIBJAIL
|
||||
{"jail2", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0},
|
||||
{"libjail", required_argument, 0, "add an option to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail2, 0},
|
||||
{"jail-attach", required_argument, 0, "attach to the FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail_attach, 0},
|
||||
#endif
|
||||
#endif
|
||||
{"refork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
|
||||
{"re-fork", no_argument, 0, "fork() again after privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork, 0},
|
||||
{"refork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0},
|
||||
{"re-fork-as-root", no_argument, 0, "fork() again before privileges drop. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_as_root, 0},
|
||||
{"refork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
|
||||
{"re-fork-post-jail", no_argument, 0, "fork() again after jailing. Useful for jailing systems", uwsgi_opt_true, &uwsgi.refork_post_jail, 0},
|
||||
|
||||
{"hook-asap", required_argument, 0, "run the specified hook as soon as possible", uwsgi_opt_add_string_list, &uwsgi.hook_asap, 0},
|
||||
{"hook-pre-jail", required_argument, 0, "run the specified hook before jailing", uwsgi_opt_add_string_list, &uwsgi.hook_pre_jail, 0},
|
||||
{"hook-post-jail", required_argument, 0, "run the specified hook after jailing", uwsgi_opt_add_string_list, &uwsgi.hook_post_jail, 0},
|
||||
{"hook-in-jail", required_argument, 0, "run the specified hook in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.hook_in_jail, 0},
|
||||
{"hook-as-root", required_argument, 0, "run the specified hook before privileges drop", uwsgi_opt_add_string_list, &uwsgi.hook_as_root, 0},
|
||||
{"hook-as-user", required_argument, 0, "run the specified hook after privileges drop", uwsgi_opt_add_string_list, &uwsgi.hook_as_user, 0},
|
||||
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
|
||||
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
|
||||
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
|
||||
|
||||
{"hook-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
|
||||
{"hook-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
|
||||
|
||||
{"exec-asap", required_argument, 0, "run the specified command as soon as possible", uwsgi_opt_add_string_list, &uwsgi.exec_asap, 0},
|
||||
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
|
||||
{"exec-post-jail", required_argument, 0, "run the specified command after jailing", uwsgi_opt_add_string_list, &uwsgi.exec_post_jail, 0},
|
||||
{"exec-in-jail", required_argument, 0, "run the specified command in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.exec_in_jail, 0},
|
||||
@@ -315,6 +352,24 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exec-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.exec_as_vassal, 0},
|
||||
{"exec-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.exec_as_emperor, 0},
|
||||
|
||||
{"mount-asap", required_argument, 0, "mount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.mount_asap, 0},
|
||||
{"mount-pre-jail", required_argument, 0, "mount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.mount_pre_jail, 0},
|
||||
{"mount-post-jail", required_argument, 0, "mount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.mount_post_jail, 0},
|
||||
{"mount-in-jail", required_argument, 0, "mount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.mount_in_jail, 0},
|
||||
{"mount-as-root", required_argument, 0, "mount filesystem before privileges drop", uwsgi_opt_add_string_list, &uwsgi.mount_as_root, 0},
|
||||
|
||||
{"mount-as-vassal", required_argument, 0, "mount filesystem before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.mount_as_vassal, 0},
|
||||
{"mount-as-emperor", required_argument, 0, "mount filesystem in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.mount_as_emperor, 0},
|
||||
|
||||
{"umount-asap", required_argument, 0, "unmount filesystem as soon as possible", uwsgi_opt_add_string_list, &uwsgi.umount_asap, 0},
|
||||
{"umount-pre-jail", required_argument, 0, "unmount filesystem before jailing", uwsgi_opt_add_string_list, &uwsgi.umount_pre_jail, 0},
|
||||
{"umount-post-jail", required_argument, 0, "unmount filesystem after jailing", uwsgi_opt_add_string_list, &uwsgi.umount_post_jail, 0},
|
||||
{"umount-in-jail", required_argument, 0, "unmount filesystem in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.umount_in_jail, 0},
|
||||
{"umount-as-root", required_argument, 0, "unmount filesystem before privileges drop", uwsgi_opt_add_string_list, &uwsgi.umount_as_root, 0},
|
||||
|
||||
{"umount-as-vassal", required_argument, 0, "unmount filesystem before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.umount_as_vassal, 0},
|
||||
{"umount-as-emperor", required_argument, 0, "unmount filesystem in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.umount_as_emperor, 0},
|
||||
|
||||
{"wait-for-interface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-for-interface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
@@ -327,6 +382,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"wait-iface", required_argument, 0, "wait for the specified network interface to come up before running root hooks", uwsgi_opt_add_string_list, &uwsgi.wait_for_interface, 0},
|
||||
{"wait-iface-timeout", required_argument, 0, "set the timeout for wait-for-interface", uwsgi_opt_set_int, &uwsgi.wait_for_interface_timeout, 0},
|
||||
|
||||
{"call-asap", required_argument, 0, "call the specified function as soon as possible", uwsgi_opt_add_string_list, &uwsgi.call_asap, 0},
|
||||
{"call-pre-jail", required_argument, 0, "call the specified function before jailing", uwsgi_opt_add_string_list, &uwsgi.call_pre_jail, 0},
|
||||
{"call-post-jail", required_argument, 0, "call the specified function after jailing", uwsgi_opt_add_string_list, &uwsgi.call_post_jail, 0},
|
||||
{"call-in-jail", required_argument, 0, "call the specified function in jail after initialization", uwsgi_opt_add_string_list, &uwsgi.call_in_jail, 0},
|
||||
@@ -406,7 +462,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
|
||||
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
|
||||
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal management", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
|
||||
@@ -439,6 +495,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
|
||||
{"multicast-loop", required_argument, 0, "set multicast loop (default 1)", uwsgi_opt_set_int, &uwsgi.multicast_loop, 0},
|
||||
|
||||
{"master-fifo", required_argument, 0, "enable the master fifo", uwsgi_opt_add_string_list, &uwsgi.master_fifo, UWSGI_OPT_MASTER},
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"legion", required_argument, 0, "became a member of a legion", uwsgi_opt_legion, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-mcast", required_argument, 0, "became a member of a legion (shortcut for multicast)", uwsgi_opt_legion_mcast, NULL, UWSGI_OPT_MASTER},
|
||||
@@ -510,6 +568,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"logger-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
|
||||
{"loggers-list", no_argument, 0, "list enabled loggers", uwsgi_opt_true, &uwsgi.loggers_list, 0},
|
||||
{"threaded-logger", no_argument, 0, "offload log writing to a thread", uwsgi_opt_true, &uwsgi.threaded_logger, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
|
||||
|
||||
{"log-encoder", required_argument, 0, "add an item in the log encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_encoders, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{"log-req-encoder", required_argument, 0, "add an item in the log req encoder chain", uwsgi_opt_add_string_list, &uwsgi.requested_log_req_encoders, 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},
|
||||
@@ -538,6 +602,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_int, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
@@ -556,7 +622,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
|
||||
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
|
||||
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
|
||||
|
||||
{"drop-after-init", no_argument, 0, "run privileges drop after plugin initialization", uwsgi_opt_true, &uwsgi.drop_after_init, 0},
|
||||
{"drop-after-apps", no_argument, 0, "run privileges drop after apps loading", uwsgi_opt_true, &uwsgi.drop_after_apps, 0},
|
||||
|
||||
{"force-cwd", required_argument, 0, "force the initial working directory to the specified value", uwsgi_opt_set_str, &uwsgi.force_cwd, 0},
|
||||
{"binsh", required_argument, 0, "override /bin/sh (used by exec hooks, it always fallback to /bin/sh)", uwsgi_opt_add_string_list, &uwsgi.binsh, 0},
|
||||
{"chdir", required_argument, 0, "chdir to specified directory before apps loading", uwsgi_opt_set_str, &uwsgi.chdir, 0},
|
||||
{"chdir2", required_argument, 0, "chdir to specified directory after apps loading", uwsgi_opt_set_str, &uwsgi.chdir2, 0},
|
||||
{"lazy", no_argument, 0, "set lazy mode (load apps in workers instead of master)", uwsgi_opt_true, &uwsgi.lazy, 0},
|
||||
@@ -570,6 +641,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"cheaper-algo-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-algos-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-list", no_argument, 0, "list enabled cheapers algorithms", uwsgi_opt_true, &uwsgi.cheaper_algo_list, 0},
|
||||
{"cheaper-rss-limit-soft", required_argument, 0, "don't spawn new workers if total resident memory usage of all workers is higher than this limit", uwsgi_opt_set_64bit, &uwsgi.cheaper_rss_limit_soft, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"cheaper-rss-limit-hard", required_argument, 0, "if total workers resident memory usage is higher try to stop workers", uwsgi_opt_set_64bit, &uwsgi.cheaper_rss_limit_hard, UWSGI_OPT_MASTER | UWSGI_OPT_CHEAPER},
|
||||
{"idle", required_argument, 0, "set idle mode (put uWSGI in cheap mode after inactivity)", uwsgi_opt_set_int, &uwsgi.idle, UWSGI_OPT_MASTER},
|
||||
{"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
|
||||
{"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
|
||||
@@ -627,6 +700,20 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"error-route-if-not", required_argument, 0, "add an error route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"error-route-run", required_argument, 0, "always run the specified error route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"response-route", required_argument, 0, "add a response route", uwsgi_opt_add_route, "path_info", 0},
|
||||
{"response-route-status", required_argument, 0, "add a response route for the specified status", uwsgi_opt_add_route, "status", 0},
|
||||
{"response-route-host", required_argument, 0, "add a response route based on Host header", uwsgi_opt_add_route, "http_host", 0},
|
||||
{"response-route-uri", required_argument, 0, "add a response route based on REQUEST_URI", uwsgi_opt_add_route, "request_uri", 0},
|
||||
{"response-route-qs", required_argument, 0, "add a response route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
{"response-route-remote-addr", required_argument, 0, "add a response route based on REMOTE_ADDR", uwsgi_opt_add_route, "remote_addr", 0},
|
||||
{"response-route-user-agent", required_argument, 0, "add a response route based on HTTP_USER_AGENT", uwsgi_opt_add_route, "user_agent", 0},
|
||||
{"response-route-remote-user", required_argument, 0, "add a response route based on REMOTE_USER", uwsgi_opt_add_route, "remote_user", 0},
|
||||
{"response-route-referer", required_argument, 0, "add a response route based on HTTP_REFERER", uwsgi_opt_add_route, "referer", 0},
|
||||
{"response-route-label", required_argument, 0, "add a response routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
|
||||
{"response-route-if", required_argument, 0, "add a response route based on condition", uwsgi_opt_add_route, "if", 0},
|
||||
{"response-route-if-not", required_argument, 0, "add a response route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
|
||||
{"response-route-run", required_argument, 0, "always run the specified response route action", uwsgi_opt_add_route, "run", 0},
|
||||
|
||||
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
@@ -651,6 +738,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
|
||||
{"rem-header", required_argument, 0, "automatically remove specified HTTP header from the response", uwsgi_opt_add_string_list, &uwsgi.remove_headers, 0},
|
||||
{"del-header", required_argument, 0, "automatically remove specified HTTP header from the response", uwsgi_opt_add_string_list, &uwsgi.remove_headers, 0},
|
||||
{"collect-header", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
{"response-header-collect", required_argument, 0, "store the specified response header in a request var (syntax: header var)", uwsgi_opt_add_string_list, &uwsgi.collect_headers, 0},
|
||||
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
@@ -662,8 +751,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"static-safe", required_argument, 0, "skip security checks if the file is under the specified path", uwsgi_opt_add_string_list, &uwsgi.static_safe, UWSGI_OPT_MIME},
|
||||
{"static-cache-paths", required_argument, 0, "put resolved paths in the uWSGI cache for the specified amount of seconds", uwsgi_opt_set_int, &uwsgi.use_static_cache_paths, UWSGI_OPT_MIME|UWSGI_OPT_MASTER},
|
||||
{"static-cache-paths-name", required_argument, 0, "use the specified cache for static paths", uwsgi_opt_set_str, &uwsgi.static_cache_paths_name, UWSGI_OPT_MIME|UWSGI_OPT_MASTER},
|
||||
#ifdef __APPLE__
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/apache2/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/apache2/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
#else
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
#endif
|
||||
|
||||
{"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
|
||||
{"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
|
||||
@@ -693,6 +787,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
|
||||
{"disable-sendfile", no_argument, 0, "disable sendfile() and rely on boring read()/write()", uwsgi_opt_true, &uwsgi.disable_sendfile, 0},
|
||||
|
||||
{"check-cache", optional_argument, 0, "check for response data in the specified cache (empty for default cache)", uwsgi_opt_set_str, &uwsgi.use_check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode, 0},
|
||||
@@ -783,6 +879,7 @@ void show_config(void) {
|
||||
}
|
||||
|
||||
int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char *value) {
|
||||
int configured;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
@@ -808,11 +905,10 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
p = strtok(tmp_val, " ");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -827,8 +923,8 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
p = strtok(tmp_opt, ";");
|
||||
while (p) {
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
@@ -859,9 +955,11 @@ int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
// we can ignore its return value
|
||||
(void) uwsgi_manage_opt(new_key, new_value);
|
||||
p = strtok(NULL, ";");
|
||||
retry:
|
||||
configured = uwsgi_manage_opt(new_key, new_value);
|
||||
if (!configured && uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(new_key)) goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
clear:
|
||||
@@ -972,11 +1070,15 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
|
||||
int base = '0';
|
||||
char *to_split = uwsgi_str(magic_table['d']);
|
||||
char *p = strtok(to_split, "/");
|
||||
while (p && base <= '9') {
|
||||
magic_table[base] = p;
|
||||
base++;
|
||||
p = strtok(NULL, "/");
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(to_split, "/", p, ctx) {
|
||||
if (base <= '9') {
|
||||
magic_table[base] = p;
|
||||
base++;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp)
|
||||
@@ -1129,6 +1231,28 @@ void kill_them_all(int signum) {
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
|
||||
// gracefully destroy
|
||||
void gracefully_kill_them_all(int signum) {
|
||||
|
||||
if (uwsgi_instance_is_dying) return;
|
||||
uwsgi.status.gracefully_destroying = 1;
|
||||
|
||||
// unsubscribe if needed
|
||||
uwsgi_unsubscribe_all();
|
||||
|
||||
uwsgi_log_verbose("graceful shutdown triggered...\n");
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
}
|
||||
|
||||
|
||||
// graceful reload
|
||||
void grace_them_all(int signum) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
|
||||
@@ -1366,6 +1490,8 @@ struct uwsgi_plugin unconfigured_plugin = {
|
||||
|
||||
void uwsgi_exec_atexit(void) {
|
||||
if (getpid() == masterpid) {
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_user_atexit, "atexit", 0);
|
||||
// now run exit scripts needed by the user
|
||||
struct uwsgi_string_list *usl;
|
||||
|
||||
@@ -1935,6 +2061,10 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_embedded_routers();
|
||||
#endif
|
||||
|
||||
// call here to allows plugin to override hooks
|
||||
uwsgi_register_base_hooks();
|
||||
uwsgi_log_encoders_register_embedded();
|
||||
|
||||
//initialize embedded plugins
|
||||
UWSGI_LOAD_EMBEDDED_PLUGINS
|
||||
// now a bit of magic, if the executable basename contains a 'uwsgi_' string,
|
||||
@@ -1952,6 +2082,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
uwsgi.magic_table['['] = "\033";
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -1982,6 +2113,32 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
// run "asap" hooks
|
||||
uwsgi_hooks_run(uwsgi.hook_asap, "asap", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_asap) {
|
||||
uwsgi_log("mounting \"%s\" (asap)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.umount_asap) {
|
||||
uwsgi_log("un-mounting \"%s\" (asap)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) exit(1);
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.exec_asap) {
|
||||
uwsgi_log("running \"%s\" (asap)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
uwsgi_foreach(usl, uwsgi.call_asap) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// manage envdirs ASAP
|
||||
uwsgi_envdirs(uwsgi.envdirs);
|
||||
|
||||
@@ -2032,6 +2189,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// setup cheaper algos
|
||||
uwsgi_register_cheaper_algo("spare", uwsgi_cheaper_algo_spare);
|
||||
uwsgi_register_cheaper_algo("backlog", uwsgi_cheaper_algo_backlog);
|
||||
uwsgi_register_cheaper_algo("manual", uwsgi_cheaper_algo_manual);
|
||||
|
||||
// setup imperial monitors
|
||||
uwsgi_register_imperial_monitor("dir", uwsgi_imperial_monitor_directory_init, uwsgi_imperial_monitor_directory);
|
||||
@@ -2159,6 +2317,8 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_routing_dump();
|
||||
#else
|
||||
uwsgi_log("!!! no internal routing support, rebuild with pcre support !!!\n");
|
||||
#endif
|
||||
|
||||
// initialize shared sockets
|
||||
@@ -2169,21 +2329,37 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_emperor_start();
|
||||
}
|
||||
|
||||
// run the pre-jail scripts
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_pre_jail;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (pre-jail)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (!uwsgi.reloads) {
|
||||
uwsgi_hooks_run(uwsgi.hook_pre_jail, "pre-jail", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.mount_pre_jail) {
|
||||
uwsgi_log("mounting \"%s\" (pre-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_foreach(usl, uwsgi.umount_pre_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (pre-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
// run the pre-jail scripts
|
||||
uwsgi_foreach(usl, uwsgi.exec_pre_jail) {
|
||||
uwsgi_log("running \"%s\" (pre-jail)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2239,7 +2415,24 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_in_jail, "in-jail", 1);
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.mount_in_jail) {
|
||||
uwsgi_log("mounting \"%s\" (in-jail)...\n", usl->value);
|
||||
if (uwsgi_mount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.umount_in_jail) {
|
||||
uwsgi_log("un-mounting \"%s\" (in-jail)...\n", usl->value);
|
||||
if (uwsgi_umount_hook(usl->value)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.exec_in_jail) {
|
||||
uwsgi_log("running \"%s\" (in-jail)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
@@ -2251,14 +2444,15 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_in_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uwsgi_file_write_do(uwsgi.file_write_list);
|
||||
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root && !uwsgi.chown_socket && !uwsgi.drop_after_init && !uwsgi.drop_after_apps) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
@@ -2363,7 +2557,11 @@ int uwsgi_start(void *v_argv) {
|
||||
// build mime.types dictionary
|
||||
if (uwsgi.build_mime_dict) {
|
||||
if (!uwsgi.mime_file)
|
||||
#ifdef __APPLE__
|
||||
uwsgi_string_new_list(&uwsgi.mime_file, "/etc/apache2/mime.types");
|
||||
#else
|
||||
uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
|
||||
#endif
|
||||
struct uwsgi_string_list *umd = uwsgi.mime_file;
|
||||
while (umd) {
|
||||
if (!access(umd->value, R_OK)) {
|
||||
@@ -2406,6 +2604,12 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
// setup locking
|
||||
uwsgi_setup_locking();
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
uwsgi_log("thunder lock: enabled\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("thunder lock: disabled (you can enable it with --thunder-lock)\n");
|
||||
}
|
||||
|
||||
// allocate rpc structures
|
||||
uwsgi_rpc_init();
|
||||
@@ -2498,6 +2702,11 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.drop_after_init) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
|
||||
/* gp/plugin initialization */
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->post_init) {
|
||||
@@ -2737,6 +2946,10 @@ next:
|
||||
uwsgi_init_all_apps();
|
||||
}
|
||||
|
||||
if (uwsgi.drop_after_apps) {
|
||||
uwsgi_as_root();
|
||||
}
|
||||
|
||||
// postinit apps (setup specific features after app initialization)
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->postinit_apps) {
|
||||
@@ -3067,8 +3280,8 @@ void uwsgi_worker_run() {
|
||||
|
||||
// eventually remap plugins
|
||||
if (uwsgi.remap_modifier) {
|
||||
char *map = strtok(uwsgi.remap_modifier, ",");
|
||||
while (map != NULL) {
|
||||
char *map, *ctx = NULL;
|
||||
uwsgi_foreach_token(uwsgi.remap_modifier, ",", map, ctx) {
|
||||
char *colon = strchr(map, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
@@ -3077,7 +3290,6 @@ void uwsgi_worker_run() {
|
||||
uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
|
||||
uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
|
||||
}
|
||||
map = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3330,6 +3542,8 @@ void uwsgi_init_all_apps() {
|
||||
|
||||
int i, j;
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_pre_app, "pre app", 1);
|
||||
|
||||
// now run the pre-app scripts
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_pre_app;
|
||||
while (usl) {
|
||||
@@ -3345,6 +3559,7 @@ void uwsgi_init_all_apps() {
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_app) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3396,6 +3611,8 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_post_app, "post app", 1);
|
||||
|
||||
usl = uwsgi.exec_post_app;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
|
||||
@@ -3846,8 +4063,8 @@ void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
|
||||
char *plugins_list = uwsgi_concat2(value, "");
|
||||
char *p = strtok(plugins_list, ",");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(plugins_list, ",", p, ctx) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("loading plugin %s\n", p);
|
||||
#endif
|
||||
@@ -3858,7 +4075,6 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
uwsgi_log("unable to load plugin \"%s\"\n", p);
|
||||
exit(1);
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(p);
|
||||
free(plugins_list);
|
||||
@@ -4347,3 +4563,12 @@ void uwsgi_print_sym(char *opt, char *symbol, void *foobar) {
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_update_pidfiles() {
|
||||
if (uwsgi.pidfile) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile);
|
||||
}
|
||||
if (uwsgi.pidfile2) {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,19 @@ error:
|
||||
|
||||
//each protocol has its header generator
|
||||
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
|
||||
|
||||
|
||||
// collect the header ?
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.collect_headers) {
|
||||
if (!uwsgi_strnicmp(key, key_len, usl->value, usl->custom)) {
|
||||
if (!uwsgi_req_append(wsgi_req, usl->custom_ptr, usl->custom2, value, value_len)) {
|
||||
wsgi_req->write_errors++ ; return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wsgi_req->headers) {
|
||||
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
|
||||
wsgi_req->headers->limit = UMAX16;
|
||||
@@ -171,6 +184,16 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *ah = uwsgi.additional_headers;
|
||||
while(ah) {
|
||||
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
|
||||
@@ -221,6 +244,19 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
*** WORK IN PROGRESS ***
|
||||
|
||||
Zeus mode
|
||||
|
||||
A Zeus instance can load all of the available imperial monitor plugins, but instead of spawning
|
||||
vassals it delegates actions to Emperors connected to it.
|
||||
|
||||
The Zeus instance try to distribute vassals evenly between Emperors.
|
||||
|
||||
Emperors register to one (ore more, maybe...) Zeus instance, passing various informations (like the maximum number
|
||||
of vassals it can manage)
|
||||
|
||||
to spawn a Zeus:
|
||||
|
||||
|
||||
# unencrypted mode
|
||||
uwsgi --zeus "192.168.173.17:4040 /etc/uwsgi/vassals"
|
||||
# crypted mode
|
||||
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key /etc/uwsgi/vassals"
|
||||
# crypted + authentication mode
|
||||
uwsgi --zeus "192.168.173.17:4040,foobar.crt,foobar.key,clients.pem /etc/uwsgi/vassals"
|
||||
|
||||
|
||||
to connect an Emperor to Zeus
|
||||
|
||||
# unencrypted mode
|
||||
uwsgi --emperor zeus:192.168.173.17:4040
|
||||
# crypted mode
|
||||
uwsgi --emperor zeus-ssl:192.168.173.17:4040
|
||||
# crypted + authentication mode
|
||||
uwsgi --emperor zeus-ssl:192.168.173.17:4040,myself.key
|
||||
|
||||
|
||||
Protocol
|
||||
|
||||
(each message is a basic uwsgi packet: modifier1 pktsize modifier2 payload)
|
||||
|
||||
modifier2 identifies the type of the message
|
||||
|
||||
0 -> I_AM_ALIVE {node: 'node001', max_vassals: '100', running_vassals: '17'} [ emperor -> zeus ]
|
||||
|
||||
1 -> NEW_VASSAL {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
2 -> ACCEPTED_VASSAL {name: 'foobar.ini'} [ emperor -> zeus ]
|
||||
|
||||
3 -> CONFIG_CHUNK {name: 'foobar.ini', body: '[uwsgi].....'} [ zeus -> the choosen emperor ]
|
||||
|
||||
4 -> CONFIG_END {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
5 -> VASSAL_SPAWNED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
6 -> VASSAL_REJECTED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
7 -> VASSAL_RELOAD {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
8 -> VASSAL_UPDATE {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
9 -> VASSAL_DESTROY {name: 'foobar.ini'} [ zeus -> the choosen emperor ]
|
||||
|
||||
10 -> VASSAL_RELOADED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
11 -> VASSAL_DESTROYED {name: 'foobar.ini'} [the choosen emperor -> zeus]
|
||||
|
||||
*/
|
||||
+10
-2
@@ -66,11 +66,17 @@ void linux_namespace_start(void *argv) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if defined(MS_REC) && defined(MS_PRIVATE)
|
||||
if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
// run the post-jail scripts
|
||||
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
uwsgi_hooks_run(uwsgi.hook_post_jail, "post-jail", 1);
|
||||
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
|
||||
while(usl) {
|
||||
uwsgi_log("running \"%s\" (post-jail)...\n", usl->value);
|
||||
@@ -84,7 +90,8 @@ void linux_namespace_start(void *argv) {
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_jail) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +180,7 @@ void linux_namespace_jail() {
|
||||
uwsgi_log("remounting /proc\n");
|
||||
if (mount("proc", "/proc", "proc", 0, NULL)) {
|
||||
uwsgi_error("mount()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uwsgi.ns_keep_mount;
|
||||
|
||||
@@ -71,8 +71,8 @@ static void carbon_post_init() {
|
||||
u_server->healthy = 1;
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p = strtok(usl->value, ":");
|
||||
while (p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(usl->value, ":", p, ctx) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
@@ -81,7 +81,6 @@ static void carbon_post_init() {
|
||||
}
|
||||
else
|
||||
break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
|
||||
@@ -828,8 +828,8 @@ clear2:
|
||||
// set the start position of args in argv
|
||||
i = 1;
|
||||
if (helper) i = 2;
|
||||
char *p = strtok(qs, "+");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(qs, "+", p, ctx) {
|
||||
// create a copy for the url_decoded string
|
||||
char *arg_copy = uwsgi_str(p);
|
||||
uint16_t arg_copy_len = strlen(p);
|
||||
@@ -838,7 +838,6 @@ clear2:
|
||||
argv[i] = uwsgi_malloc( (arg_copy_len * 2) +1);
|
||||
escape_shell_arg(arg_copy, arg_copy_len, argv[i]);
|
||||
i++;
|
||||
p = strtok(NULL, "+");
|
||||
}
|
||||
free(qs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
|
||||
uWSGI forkpty-router
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
#include "../corerouter/cr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef __linux__
|
||||
#include <pty.h>
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#include <util.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <libutil.h>
|
||||
#endif
|
||||
#ifndef __FreeBSD__
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
|
||||
|
||||
static struct uwsgi_forkptyrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
char *cmd;
|
||||
} ufpty;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct forkptyrouter_session {
|
||||
struct corerouter_session session;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static struct uwsgi_option forkptyrouter_options[] = {
|
||||
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
|
||||
|
||||
{"forkptyrouter-fallback", required_argument, 0, "fallback to the specified node in case of error", uwsgi_opt_add_string_list, &ufpty.cr.fallback, 0},
|
||||
|
||||
{"forkptyrouter-events", required_argument, 0, "set the maximum number of concufptyent events", uwsgi_opt_set_int, &ufpty.cr.nevents, 0},
|
||||
{"forkptyrouter-cheap", no_argument, 0, "run the forkptyrouter in cheap mode", uwsgi_opt_true, &ufpty.cr.cheap, 0},
|
||||
|
||||
{"forkptyrouter-timeout", required_argument, 0, "set forkptyrouter timeout", uwsgi_opt_set_int, &ufpty.cr.socket_timeout, 0},
|
||||
|
||||
{"forkptyrouter-stats", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-stats-server", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-ss", required_argument, 0, "run the forkptyrouter stats server", uwsgi_opt_set_str, &ufpty.cr.stats_server, 0},
|
||||
{"forkptyrouter-harakiri", required_argument, 0, "enable forkptyrouter harakiri", uwsgi_opt_set_int, &ufpty.cr.harakiri, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
// write to backend
|
||||
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_write(peer, "fpty_instance_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
|
||||
// the chunk has been sent, start (again) reading from client and instances
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the buffer
|
||||
peer->out->pos = 0;
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// write to client
|
||||
static ssize_t fpty_write(struct corerouter_peer *main_peer) {
|
||||
ssize_t len = cr_write(main_peer, "fpty_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
|
||||
// ok this response chunk is sent, let's start reading again
|
||||
if (cr_write_complete(main_peer)) {
|
||||
// reset the buffer
|
||||
main_peer->out->pos = 0;
|
||||
cr_reset_hooks(main_peer);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// read from backend
|
||||
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_read(peer, "fpty_instance_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
// set the input buffer as the main output one
|
||||
peer->session->main_peer->out = peer->in;
|
||||
peer->session->main_peer->out_pos = 0;
|
||||
|
||||
cr_write_to_main(peer, fpty_write);
|
||||
return len;
|
||||
}
|
||||
|
||||
// read from client
|
||||
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
|
||||
ssize_t len = cr_read(main_peer, "fpty_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
main_peer->session->peers->out_pos = 0;
|
||||
|
||||
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void fpty_session_close(struct corerouter_session *cs) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
if (fpty_session->pid > 0) {
|
||||
int waitpid_status = 0;
|
||||
if (waitpid(fpty_session->pid, &waitpid_status, WNOHANG) < 0) {
|
||||
uwsgi_error("fpty_session_close()/waitpid()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// allocate a new session
|
||||
static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, struct corerouter_session *cs, struct sockaddr *sa, socklen_t s_len) {
|
||||
|
||||
// set default read hook
|
||||
cs->main_peer->last_hook_read = fpty_read;
|
||||
|
||||
// wait4() on close
|
||||
cs->close = fpty_session_close;
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
|
||||
// add a new peer
|
||||
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
|
||||
|
||||
// on new connection generate a new pty
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, NULL);
|
||||
if (fpty_session->pid < 0) {
|
||||
uwsgi_error("forkpty()");
|
||||
return -1;
|
||||
}
|
||||
else if (fpty_session->pid == 0) {
|
||||
if (ufpty.cmd) {
|
||||
char *space = strchr(ufpty.cmd, ' ');
|
||||
if (space) {
|
||||
char *argv[4];
|
||||
argv[0] = uwsgi_binsh();
|
||||
argv[1] = "-c";
|
||||
argv[2] = ufpty.cmd;
|
||||
argv[3] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = ufpty.cmd;
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
}
|
||||
// never here;
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execve()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ucr->cr_table[peer->fd] = peer;
|
||||
cr_reset_hooks_and_read(peer, fpty_instance_read);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int forkptyrouter_init() {
|
||||
|
||||
ufpty.cr.session_size = sizeof(struct forkptyrouter_session);
|
||||
ufpty.cr.alloc_session = forkptyrouter_alloc_session;
|
||||
uwsgi_corerouter_init((struct uwsgi_corerouter *) &ufpty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void forkptyrouter_setup() {
|
||||
ufpty.cr.name = uwsgi_str("uWSGI forkptyrouter");
|
||||
ufpty.cr.short_name = uwsgi_str("forkptyrouter");
|
||||
}
|
||||
|
||||
struct uwsgi_plugin forkptyrouter_plugin = {
|
||||
|
||||
.name = "forkptyrouter",
|
||||
.options = forkptyrouter_options,
|
||||
.init = forkptyrouter_init,
|
||||
.on_load = forkptyrouter_setup
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='forkptyrouter'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
REQUIRES = ['corerouter']
|
||||
|
||||
GCC_LIST = ['forkptyrouter']
|
||||
@@ -123,10 +123,9 @@ static void uwsgi_gccgo_initialize() {
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
argc++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
free(argv_list);
|
||||
}
|
||||
@@ -134,12 +133,11 @@ static void uwsgi_gccgo_initialize() {
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p = strtok(argv_list, " ");
|
||||
char *p, *ctx = NULL;
|
||||
int n = 0;
|
||||
while(p) {
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
argv[n] = p;
|
||||
n++;
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
runtime_args(argc, argv);
|
||||
}
|
||||
|
||||
+69
-15
@@ -19,14 +19,40 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
static struct uwsgi_option gevent_options[] = {
|
||||
{"gevent", required_argument, 0, "a shortcut enabling gevent loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_gevent, NULL, UWSGI_OPT_THREADS},
|
||||
{"gevent-monkey-patch", no_argument, 0, "call gevent.monkey.patch_all() automatically on startup", uwsgi_opt_true, &ugevent.monkey, 0},
|
||||
{"gevent-wait-for-hub", no_argument, 0, "wait for gevent hub's death instead of the control greenlet", uwsgi_opt_true, &ugevent.wait_for_hub, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Dumb greenlet used for controlling the shutdown (originally uWSGI only wait for the hub)
|
||||
*/
|
||||
PyObject *py_uwsgi_gevent_ctrl_gl(PyObject *self, PyObject *args) {
|
||||
for(;;) {
|
||||
PyObject *gevent_sleep_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(gevent_sleep_args, 0, PyInt_FromLong(60));
|
||||
PyObject *gswitch = PyEval_CallObject(ugevent.greenlet_switch, gevent_sleep_args);
|
||||
// could be NULL on exception
|
||||
if (!gswitch) {
|
||||
// just for being paranid
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(gswitch);
|
||||
Py_DECREF(gevent_sleep_args);
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) {
|
||||
|
||||
int running_cores = 0;
|
||||
int rounds = 0;
|
||||
|
||||
uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
|
||||
@@ -41,29 +67,34 @@ PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) {
|
||||
}
|
||||
uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
|
||||
int running_cores = 0;
|
||||
retry:
|
||||
running_cores = 0;
|
||||
for(i=0;i<uwsgi.async;i++) {
|
||||
if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) {
|
||||
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i,
|
||||
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
if (!rounds) {
|
||||
uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i,
|
||||
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
}
|
||||
running_cores++;
|
||||
}
|
||||
}
|
||||
|
||||
if (running_cores > 0) {
|
||||
uwsgi_log_verbose("waiting for %d running requests on worker %d (pid: %d)...\n", running_cores, uwsgi.mywid, uwsgi.mypid);
|
||||
} else {
|
||||
// no need to worry about freeing memory
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
|
||||
if (ae) {
|
||||
python_call(ae, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
PyObject *gevent_sleep_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(gevent_sleep_args, 0, PyInt_FromLong(1));
|
||||
PyObject *gswitch = python_call(ugevent.greenlet_switch, gevent_sleep_args, 0, NULL);
|
||||
Py_DECREF(gswitch);
|
||||
Py_DECREF(gevent_sleep_args);
|
||||
rounds++;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -300,6 +331,7 @@ PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_geven
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_unix_signal_handler_def[] = { {"uwsgi_gevent_unix_signal_handler", py_uwsgi_gevent_graceful, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_ctrl_gl_def[] = { {"uwsgi_gevent_ctrl_gl_handler", py_uwsgi_gevent_ctrl_gl, METH_VARARGS, ""} };
|
||||
|
||||
static void gil_gevent_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
@@ -450,8 +482,21 @@ static void gevent_loop() {
|
||||
|
||||
python_call(ugevent.signal, ge_signal_tuple, 0, NULL);
|
||||
|
||||
PyObject *wait_for_me = ugevent.hub;
|
||||
|
||||
if (!ugevent.wait_for_hub) {
|
||||
// spawn the control greenlet
|
||||
PyObject *uwsgi_greenlet_ctrl_gl_handler = PyCFunction_New(uwsgi_gevent_ctrl_gl_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_ctrl_gl_handler);
|
||||
PyObject *ctrl_gl_args = PyTuple_New(1);
|
||||
PyTuple_SetItem(ctrl_gl_args, 0, uwsgi_greenlet_ctrl_gl_handler);
|
||||
ugevent.ctrl_gl = python_call(ugevent.spawn, ctrl_gl_args, 0, NULL);
|
||||
Py_INCREF(ugevent.ctrl_gl);
|
||||
wait_for_me = ugevent.ctrl_gl;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
|
||||
if (!PyObject_CallMethod(wait_for_me, "join", NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
@@ -459,6 +504,15 @@ static void gevent_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// no need to worry about freeing memory
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
if (uwsgi_dict) {
|
||||
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
|
||||
if (ae) {
|
||||
python_call(ae, PyTuple_New(0), 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
|
||||
uwsgi_log("goodbye to the gevent Hub on worker %d (pid: %d)\n", uwsgi.mywid, uwsgi.mypid);
|
||||
if (ugevent.destroy) {
|
||||
|
||||
@@ -51,7 +51,9 @@ struct uwsgi_gevent {
|
||||
PyObject *my_signal_watcher;
|
||||
PyObject *signal_watcher;
|
||||
PyObject **watchers;
|
||||
PyObject *ctrl_gl;
|
||||
int destroy;
|
||||
int monkey;
|
||||
int wait_for_hub;
|
||||
};
|
||||
|
||||
|
||||
@@ -117,13 +117,12 @@ connect:
|
||||
|
||||
static void uwsgi_glusterfs_connect_do(struct uwsgi_app *ua) {
|
||||
char *servers = uwsgi_str(ua->callable);
|
||||
char *p = strtok(servers, ";");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(servers, ";", p, ctx) {
|
||||
uwsgi_log("[glusterfs] try connect to %s for mountpoint %.*s on worker %d ...\n", p, ua->mountpoint_len, ua->mountpoint, uwsgi.mywid);
|
||||
if (uwsgi_glusterfs_try(ua, p)) {
|
||||
goto end;
|
||||
}
|
||||
p = strtok(NULL, ";");
|
||||
}
|
||||
end:
|
||||
free(servers);
|
||||
|
||||
+4
-6
@@ -181,10 +181,9 @@ static void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
@@ -228,10 +227,9 @@ static void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
|
||||
entry = &ule[i];
|
||||
|
||||
char *list2 = uwsgi_concat2(entry->names + 1, "");
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(list2, " ", p, ctx) {
|
||||
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
free(list2);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#include <uwsgi.h>
|
||||
#include <libtcc.h>
|
||||
|
||||
uint64_t uwsgi_libtcc_counter = 0;
|
||||
|
||||
static int uwsgi_libtcc_hook(char *arg) {
|
||||
char *func_base = "uwsgi_libtcc_func";
|
||||
size_t func_len = strlen(func_base) + sizeof(UMAX64_STR);
|
||||
char *func_name = uwsgi_malloc(func_len);
|
||||
if (snprintf(func_name, func_len, "%s%llu", func_base, uwsgi_libtcc_counter) < (int) strlen(func_base)) {
|
||||
free(func_name);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_libtcc_counter++;
|
||||
size_t source_len = 64 + func_len + strlen(arg);
|
||||
char *source = uwsgi_malloc(source_len);
|
||||
if (snprintf(source, source_len, "void %s() { %s ;}", func_name, arg) < (int) ( strlen(func_base) + strlen(arg))) {
|
||||
free(func_name);
|
||||
free(source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
TCCState *s = tcc_new();
|
||||
|
||||
if (tcc_compile_string(s, source)) goto error;
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO)) goto error;
|
||||
|
||||
void (*func)() = tcc_get_symbol(s, func_name);
|
||||
if (!func) goto error;
|
||||
free(func_name);
|
||||
free(source);
|
||||
|
||||
// call the function
|
||||
func();
|
||||
|
||||
tcc_delete(s);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(func_name);
|
||||
free(source);
|
||||
tcc_delete(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_libtcc_setup() {
|
||||
uwsgi_register_hook("tcc", uwsgi_libtcc_hook);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin libtcc_plugin = {
|
||||
.name = "libtcc",
|
||||
.on_load = uwsgi_libtcc_setup,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='libtcc'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=['-ltcc']
|
||||
GCC_LIST=['libtcc']
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
static ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
@@ -18,8 +18,24 @@ ssize_t uwsgi_file_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_fd_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
ul->fd = -1;
|
||||
if (ul->arg) ul->fd = atoi(ul->arg);
|
||||
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);
|
||||
uwsgi_register_logger("fd", uwsgi_fd_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logfile_plugin = {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
The pipe logger
|
||||
|
||||
Author: INADA Naoki
|
||||
|
||||
every log line is sent to the stdin of an external process
|
||||
|
||||
Example:
|
||||
|
||||
req-logger = pipe:/usr/local/bin/mylogger
|
||||
|
||||
*/
|
||||
|
||||
static ssize_t uwsgi_pipe_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
if (!ul->configured) {
|
||||
if (ul->arg) {
|
||||
int pipefd[2];
|
||||
// retry later...
|
||||
if (pipe(pipefd) < 0) return -1;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) return -1;
|
||||
if (pid > 0) {
|
||||
close(pipefd[0]);
|
||||
ul->fd = pipefd[1];
|
||||
}
|
||||
else {
|
||||
// child
|
||||
setsid();
|
||||
close(pipefd[1]);
|
||||
dup2(pipefd[0], STDIN_FILENO);
|
||||
close(pipefd[0]);
|
||||
uwsgi_exec_command_with_args(ul->arg);
|
||||
exit(1); // if here something seriously failed
|
||||
}
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
int err = write(ul->fd, message, len);
|
||||
// on failed writes, re-configure the logger
|
||||
if (err <= 0) {
|
||||
close(ul->fd);
|
||||
ul->configured = 0;
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_pipe_logger_register() {
|
||||
uwsgi_register_logger("pipe", uwsgi_pipe_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logpipe_plugin = {
|
||||
.name = "logpipe",
|
||||
.on_load = uwsgi_pipe_logger_register,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logpipe'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logpipe']
|
||||
@@ -0,0 +1,360 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
msgpack utilities
|
||||
|
||||
*/
|
||||
|
||||
enum {
|
||||
MSGPACK_NIL = 0,
|
||||
MSGPACK_TRUE,
|
||||
MSGPACK_FALSE,
|
||||
MSGPACK_INT,
|
||||
MSGPACK_FLOAT,
|
||||
MSGPACK_STR,
|
||||
MSGPACK_BIN,
|
||||
MSGPACK_ARRAY,
|
||||
MSGPACK_MAP,
|
||||
MSGPACK_EXT,
|
||||
MSGPACK_MAGIC,
|
||||
};
|
||||
|
||||
struct uwsgi_msgpack_item {
|
||||
uint8_t type;
|
||||
char *str;
|
||||
uint32_t str_len;
|
||||
int64_t num;
|
||||
double fnum;
|
||||
int (*func)(char *);
|
||||
struct uwsgi_msgpack_item *next;
|
||||
};
|
||||
|
||||
struct uwsgi_msgpack_item *uwsgi_msgpack_item_add(struct uwsgi_msgpack_item **list, uint8_t type) {
|
||||
struct uwsgi_msgpack_item *old_umi = NULL, *umi = *list;
|
||||
while(umi) {
|
||||
old_umi = umi;
|
||||
umi = umi->next;
|
||||
}
|
||||
|
||||
umi = uwsgi_calloc(sizeof(struct uwsgi_msgpack_item));
|
||||
umi->type = type;
|
||||
if (old_umi) {
|
||||
old_umi->next = umi;
|
||||
}
|
||||
else {
|
||||
*list = umi;
|
||||
}
|
||||
return umi;
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_map(struct uwsgi_buffer *ub, uint32_t len) {
|
||||
if (len <= 15) {
|
||||
return uwsgi_buffer_byte(ub, 0x80 + len);
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDE)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) len);
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_byte(ub, 0xDF)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_array(struct uwsgi_buffer *ub, uint32_t len) {
|
||||
if (len <= 15) {
|
||||
return uwsgi_buffer_byte(ub, 0x90 + len);
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDC)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) len);
|
||||
}
|
||||
|
||||
if (uwsgi_buffer_byte(ub, 0xDD)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_str(struct uwsgi_buffer *ub, char *str, uint32_t len) {
|
||||
if (len <= 31) {
|
||||
if (uwsgi_buffer_byte(ub, 0xA0 + len)) return -1;
|
||||
}
|
||||
// this is annoying, D9 does not work for older SPEC :(
|
||||
/*
|
||||
else if (len <= 0xff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD9)) return -1;
|
||||
if (uwsgi_buffer_byte(ub, (uint8_t) len)) return -1;
|
||||
}
|
||||
*/
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xDA)) return -1;
|
||||
if (uwsgi_buffer_u16be(ub, (uint16_t) len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_byte(ub, 0xDB)) return -1;
|
||||
if (uwsgi_buffer_u32be(ub, len)) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_buffer_append(ub, str, len);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_bin(struct uwsgi_buffer *ub, char *str, uint32_t len) {
|
||||
if (len <= 0xff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xC4)) return -1;
|
||||
if (uwsgi_buffer_byte(ub, (uint8_t) len)) return -1;
|
||||
}
|
||||
else if (len <= 0xffff) {
|
||||
if (uwsgi_buffer_byte(ub, 0xC5)) return -1;
|
||||
if (uwsgi_buffer_u16be(ub, (uint16_t) len)) return -1;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_byte(ub, 0xC6)) return -1;
|
||||
if (uwsgi_buffer_u32be(ub, len)) return -1;
|
||||
}
|
||||
|
||||
return uwsgi_buffer_append(ub, str, len);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_msgpack_int(struct uwsgi_buffer *ub, int64_t num) {
|
||||
if (num > 0 && num <= 127) {
|
||||
return uwsgi_buffer_byte(ub, (uint8_t) num);
|
||||
}
|
||||
else if (num < 0 && num >= 31) {
|
||||
return uwsgi_buffer_byte(ub, 224 | (int8_t) num);
|
||||
}
|
||||
else if (num <= 127 && num >= -127) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD0)) return -1;
|
||||
return uwsgi_buffer_byte(ub, (int8_t) num);
|
||||
}
|
||||
else if (num <= 32767 && num >= -32767) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD1)) return -1;
|
||||
return uwsgi_buffer_u16be(ub, (uint16_t) num);
|
||||
}
|
||||
else if (num <= 2147483647LL && num >= -2147483648LL) {
|
||||
if (uwsgi_buffer_byte(ub, 0xD2)) return -1;
|
||||
return uwsgi_buffer_u32be(ub, (uint32_t) num);
|
||||
}
|
||||
if (uwsgi_buffer_byte(ub, 0xD3)) return -1;
|
||||
return uwsgi_buffer_u64be(ub, (uint64_t)num);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_float(struct uwsgi_buffer *ub, double num) {
|
||||
if (num >= -126.0 && num <= 127.0) {
|
||||
if (uwsgi_buffer_byte(ub, 0xCA)) return -1;
|
||||
return uwsgi_buffer_f32be(ub, (float) num);
|
||||
}
|
||||
if (uwsgi_buffer_byte(ub, 0xCB)) return -1;
|
||||
return uwsgi_buffer_f64be(ub, num);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_nil(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC0);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_true(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC3);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_msgpack_false(struct uwsgi_buffer *ub) {
|
||||
return uwsgi_buffer_byte(ub, 0xC2);
|
||||
}
|
||||
|
||||
static char *uwsgi_msgpack_log_encoder(struct uwsgi_log_encoder *ule, char *msg, size_t len, size_t *rlen) {
|
||||
char *buf = NULL;
|
||||
if (!ule->configured) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(ule->args, "|", p, ctx) {
|
||||
char *colon = strchr(p, ':');
|
||||
if (colon) *colon = 0;
|
||||
// find the type of item
|
||||
if (!strcmp(p, "map")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAP);
|
||||
if (colon) {
|
||||
new_umi->num = strtoull(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "array")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_ARRAY);
|
||||
if (colon) {
|
||||
new_umi->num = strtoull(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "nil")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_NIL);
|
||||
}
|
||||
else if (!strcmp(p, "true")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_TRUE);
|
||||
}
|
||||
else if (!strcmp(p, "false")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_FALSE);
|
||||
}
|
||||
else if (!strcmp(p, "int")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_INT);
|
||||
if (colon) {
|
||||
new_umi->num = strtoll(colon+1, NULL, 10);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "float")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_FLOAT);
|
||||
if (colon) {
|
||||
new_umi->fnum = strtod(colon+1, NULL);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "str")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_STR);
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "bin")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_BIN);
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
else if (!strcmp(p, "msg")) {
|
||||
uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
}
|
||||
else if (!strcmp(p, "msgbin")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 1;
|
||||
}
|
||||
|
||||
else if (!strcmp(p, "msgnl")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 2;
|
||||
}
|
||||
else if (!strcmp(p, "msgbinnl")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 3;
|
||||
}
|
||||
else if (!strcmp(p, "unix")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 4;
|
||||
}
|
||||
else if (!strcmp(p, "micros")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 5;
|
||||
}
|
||||
else if (!strcmp(p, "strftime")) {
|
||||
struct uwsgi_msgpack_item *new_umi = uwsgi_msgpack_item_add((struct uwsgi_msgpack_item**)&ule->data, MSGPACK_MAGIC);
|
||||
new_umi->num = 6;
|
||||
if (colon) {
|
||||
new_umi->str = colon+1;
|
||||
new_umi->str_len = strlen(colon+1);
|
||||
}
|
||||
else {
|
||||
new_umi->str = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (colon) *colon = ':';
|
||||
}
|
||||
ule->configured = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(len + strlen(ule->args));
|
||||
struct uwsgi_msgpack_item *umi = (struct uwsgi_msgpack_item*) ule->data;
|
||||
uint32_t tmp_len = 0;
|
||||
while(umi) {
|
||||
switch(umi->type) {
|
||||
case(MSGPACK_NIL):
|
||||
if (uwsgi_buffer_msgpack_nil(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_TRUE):
|
||||
if (uwsgi_buffer_msgpack_true(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_FALSE):
|
||||
if (uwsgi_buffer_msgpack_false(ub)) goto end;
|
||||
break;
|
||||
case(MSGPACK_STR):
|
||||
if (uwsgi_buffer_msgpack_str(ub, umi->str, umi->str_len)) goto end;
|
||||
break;
|
||||
case(MSGPACK_BIN):
|
||||
if (uwsgi_buffer_msgpack_bin(ub, umi->str, umi->str_len)) goto end;
|
||||
break;
|
||||
case(MSGPACK_MAP):
|
||||
if (uwsgi_buffer_msgpack_map(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_ARRAY):
|
||||
if (uwsgi_buffer_msgpack_array(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_INT):
|
||||
if (uwsgi_buffer_msgpack_int(ub, umi->num)) goto end;
|
||||
break;
|
||||
case(MSGPACK_FLOAT):
|
||||
if (uwsgi_buffer_msgpack_float(ub, umi->fnum)) goto end;
|
||||
break;
|
||||
case(MSGPACK_MAGIC):
|
||||
// msg
|
||||
tmp_len = len;
|
||||
if (umi->num == 0) {
|
||||
if (msg[len-1] == '\n') tmp_len--;
|
||||
if (uwsgi_buffer_msgpack_str(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgbin
|
||||
else if (umi->num == 1) {
|
||||
if (msg[len-1] == '\n') tmp_len--;
|
||||
if (uwsgi_buffer_msgpack_bin(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgnl
|
||||
if (umi->num == 2) {
|
||||
if (uwsgi_buffer_msgpack_str(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// msgbinnl
|
||||
else if (umi->num == 3) {
|
||||
if (uwsgi_buffer_msgpack_bin(ub, msg, tmp_len)) goto end;
|
||||
}
|
||||
// unix
|
||||
else if (umi->num == 4) {
|
||||
if (uwsgi_buffer_msgpack_int(ub, (int64_t)uwsgi_now())) goto end;
|
||||
}
|
||||
// micros
|
||||
else if (umi->num == 5) {
|
||||
if (uwsgi_buffer_msgpack_int(ub, (int64_t)uwsgi_micros())) goto end;
|
||||
}
|
||||
// strftime
|
||||
else if (umi->num == 6) {
|
||||
char sftime[64];
|
||||
time_t now = uwsgi_now();
|
||||
int rlen = strftime(sftime, 64, umi->str, localtime(&now));
|
||||
if (rlen > 0) {
|
||||
if (uwsgi_buffer_msgpack_str(ub, sftime, rlen)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_buffer_msgpack_str(ub, "", 0)) goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
umi = umi->next;
|
||||
}
|
||||
|
||||
buf = ub->buf;
|
||||
*rlen = ub->pos;
|
||||
ub->buf = NULL;
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void uwsgi_msgpack_register() {
|
||||
uwsgi_register_log_encoder("msgpack", uwsgi_msgpack_log_encoder);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin msgpack_plugin = {
|
||||
.name = "msgpack",
|
||||
.on_load = uwsgi_msgpack_register,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='msgpack'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=[]
|
||||
GCC_LIST = ['msgpack']
|
||||
@@ -5,25 +5,24 @@ NAME='php'
|
||||
ld_run_path = None
|
||||
PHPPATH = 'php-config'
|
||||
|
||||
try:
|
||||
phpdir = os.environ['UWSGICONFIG_PHPDIR']
|
||||
phpdir = os.environ.get('UWSGICONFIG_PHPDIR')
|
||||
if phpdir:
|
||||
ld_run_path = "%s/lib" % phpdir
|
||||
PHPPATH = "%s/bin/php-config" % phpdir
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
|
||||
except:
|
||||
pass
|
||||
PHPPATH = os.environ.get('UWSGICONFIG_PHPPATH', PHPPATH)
|
||||
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip(), '-Wno-sign-compare']
|
||||
|
||||
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
|
||||
|
||||
if ld_run_path:
|
||||
LDFLAGS.append('-L%s' % ld_run_path)
|
||||
os.environ['LD_RUN_PATH'] = ld_run_path
|
||||
|
||||
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
|
||||
|
||||
phplibdir = os.environ.get('UWSGICONFIG_PHPLIBDIR')
|
||||
if phplibdir:
|
||||
LIBS.append('-Wl,-rpath=%s' % phplibdir)
|
||||
|
||||
GCC_LIST = ['php_plugin']
|
||||
|
||||
@@ -383,10 +383,9 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
AV *uperl_argv = GvAV(PL_argvgv);
|
||||
if (uperl.argv_items) {
|
||||
char *argv_list = uwsgi_str(uperl.argv_items);
|
||||
char *p = strtok(argv_list, " ");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(argv_list, " ", p, ctx) {
|
||||
av_push(uperl_argv, newSVpv(p, 0));
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
struct uwsgi_string_list *usl = uperl.argv_item;
|
||||
|
||||
+11
-3
@@ -78,7 +78,7 @@ static struct uwsgi_option uwsgi_pty_options[] = {
|
||||
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
|
||||
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
|
||||
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
|
||||
{"pty-exec", no_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{"pty-exec", required_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -118,6 +118,14 @@ static void *uwsgi_pty_loop(void *arg) {
|
||||
if client is ready we have something to write to the master pty
|
||||
*/
|
||||
|
||||
// block signals on this thread
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
#ifndef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
for(;;) {
|
||||
char buf[8192];
|
||||
int interesting_fd = -1;
|
||||
@@ -264,8 +272,8 @@ static int uwsgi_pty_client() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(upty.server_fd);
|
||||
uwsgi_socket_nb(0);
|
||||
//uwsgi_socket_nb(upty.server_fd);
|
||||
//uwsgi_socket_nb(0);
|
||||
|
||||
uwsgi_log("[pty] connected.\n");
|
||||
|
||||
|
||||
@@ -320,8 +320,9 @@ void init_pyargv() {
|
||||
char *tmp_ptr = uwsgi_str(up.argv);
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(tmp_ptr, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
char *ctx = NULL;
|
||||
ap = strtok_r(tmp_ptr, " ", &ctx);
|
||||
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
|
||||
#endif
|
||||
@@ -352,8 +353,9 @@ void init_pyargv() {
|
||||
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(py_argv_copy, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
char *ctx = NULL;
|
||||
ap = strtok_r(py_argv_copy, " ", &ctx);
|
||||
while ((ap = strtok_r(NULL, " ", &ctx)) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
|
||||
#endif
|
||||
|
||||
@@ -394,6 +394,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(func);
|
||||
|
||||
if (uwsgi_register_rpc(name, &python_plugin, argc, func)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
|
||||
@@ -498,6 +499,8 @@ PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(handler);
|
||||
|
||||
if (uwsgi_register_signal(uwsgi_signal, signal_kind, handler, 0)) {
|
||||
return PyErr_Format(PyExc_ValueError, "unable to register signal");
|
||||
}
|
||||
|
||||
@@ -818,6 +818,18 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi_apps[wsgi_req->app_id].requests++;
|
||||
|
||||
env = rb_hash_new();
|
||||
// the following vars have to always been defined (we skip REQUEST_METHOD and PATH_INFO as they should always be available)
|
||||
rb_hash_aset(env, rb_str_new2("SCRIPT_NAME"), rb_str_new2(""));
|
||||
rb_hash_aset(env, rb_str_new2("QUERY_STRING"), rb_str_new2(""));
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_NAME"), rb_str_new2(uwsgi.hostname));
|
||||
// SERVER_PORT
|
||||
char *server_port = strchr(wsgi_req->socket->name, ':');
|
||||
if (server_port) {
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_PORT"), rb_str_new(server_port+1, strlen(server_port+1)));
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("SERVER_PORT"), rb_str_new2("80"));
|
||||
}
|
||||
|
||||
// fill ruby hash
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
#include <uwsgi.h>
|
||||
#include <rados/librados.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
Author: Javier Guerra
|
||||
|
||||
based on the uWSGI GlusterFS plugin by Roberto De Ioris
|
||||
|
||||
--rados-mount mountpoint=/foo,pool=unbit001,config=/etc/ceph.conf
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_plugin rados_plugin;
|
||||
|
||||
struct uwsgi_rados {
|
||||
int timeout;
|
||||
struct uwsgi_string_list *mountpoints;
|
||||
} urados;
|
||||
|
||||
static struct uwsgi_option uwsgi_rados_options[] = {
|
||||
{"rados-mount", required_argument, 0, "virtual mount the specified rados volume in a uri", uwsgi_opt_add_string_list, &urados.mountpoints, UWSGI_OPT_MIME},
|
||||
{"rados-timeout", required_argument, 0, "timeout for async operations", uwsgi_opt_set_int, &urados.timeout, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static int uwsgi_rados_read_sync(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
while(remains > 0) {
|
||||
char buf[8192];
|
||||
int rlen = rados_read(ctx, key, buf, UMIN(remains, 8192), off);
|
||||
if (rlen <= 0) return -1;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) return -1;
|
||||
remains -= rlen;
|
||||
off += rlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
async read of a resource
|
||||
the uwsgi_rados_async_io structure is passed between threads
|
||||
the callback simply signal the main core about the availability of data
|
||||
*/
|
||||
struct uwsgi_rados_async_io {
|
||||
int fd[2];
|
||||
ssize_t rlen;
|
||||
};
|
||||
|
||||
static void uwsgi_rados_read_async_cb(rados_completion_t comp, void *data) {
|
||||
struct uwsgi_rados_async_io *aio = (struct uwsgi_rados_async_io *) data;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[rados-cb] rlen = %d\n", rlen);
|
||||
#endif
|
||||
aio->rlen = rados_aio_get_return_value(comp);
|
||||
// signal the core
|
||||
if (write(aio->fd[1], "\1", 1) <= 0) {
|
||||
uwsgi_error("uwsgi_rados_read_async_cb()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_rados_read_async(struct wsgi_request *wsgi_req, rados_ioctx_t *ctx, const char *key, size_t remains) {
|
||||
uint64_t off = 0;
|
||||
char buf[8192];
|
||||
struct uwsgi_rados_async_io aio;
|
||||
int ret = -1;
|
||||
if (pipe(aio.fd)) {
|
||||
uwsgi_error("uwsgi_rados_read_async()/pipe()");
|
||||
return -1;
|
||||
}
|
||||
aio.rlen = -1;
|
||||
rados_completion_t comp;
|
||||
if (rados_aio_create_completion(&aio, uwsgi_rados_read_async_cb, NULL, &comp) < 0) goto end;
|
||||
|
||||
while(remains > 0) {
|
||||
// trigger an async read
|
||||
if (rados_aio_read(ctx, key, comp, buf, 8192, off) < 0) goto end;
|
||||
// wait for the callback to be executed
|
||||
if (uwsgi.wait_read_hook(aio.fd[0], urados.timeout) <= 0) goto end;
|
||||
if (aio.rlen <= 0) goto end;
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, aio.rlen)) goto end;
|
||||
remains -= aio.rlen;
|
||||
}
|
||||
ret = 0;
|
||||
end:
|
||||
rados_aio_release(&comp);
|
||||
close(aio.fd[0]);
|
||||
close(aio.fd[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
|
||||
char *rad_mountpoint = NULL;
|
||||
char *rad_config = NULL;
|
||||
char *rad_poolname = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
|
||||
"mountpoint", &rad_mountpoint,
|
||||
"config", &rad_config,
|
||||
"pool", &rad_poolname,
|
||||
NULL)) {
|
||||
uwsgi_log("unable to parse rados mountpoint definition\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!rad_mountpoint|| !rad_poolname) {
|
||||
uwsgi_log("[rados] mount requires a mountpoint, and a pool name.\n");
|
||||
exit(1);
|
||||
}
|
||||
time_t now = uwsgi_now();
|
||||
uwsgi_log("[rados] mounting %s ...\n", rad_mountpoint);
|
||||
|
||||
rados_t cluster;
|
||||
if (rados_create(&cluster, NULL) < 0) {
|
||||
uwsgi_error("Can't create Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
if (rad_config)
|
||||
uwsgi_log("Using Ceph conf:%s\n", rad_config);
|
||||
else
|
||||
uwsgi_log("Using default Ceph conf.\n");
|
||||
if (rados_conf_read_file(cluster, rad_config) < 0) {
|
||||
uwsgi_error("Can't configure Ceph cluster handle");
|
||||
exit(1);
|
||||
}
|
||||
if (rados_connect(cluster) < 0) {
|
||||
uwsgi_error("Can't connect with Ceph cluster");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rados_ioctx_t ctx;
|
||||
uwsgi_log("Ceph pool: %s\n", rad_poolname);
|
||||
if (rados_ioctx_create(cluster, rad_poolname, &ctx) < 0) {
|
||||
uwsgi_error("Can't open rados pool")
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, rados_plugin.modifier1, rad_mountpoint, strlen(rad_mountpoint), NULL, NULL);
|
||||
if (!ua) {
|
||||
uwsgi_log("[rados] unable to mount %s\n", rad_mountpoint);
|
||||
rados_shutdown(cluster);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ua->responder0 = cluster;
|
||||
ua->responder1 = ctx;
|
||||
ua->started_at = now;
|
||||
ua->startup_time = uwsgi_now() - now;
|
||||
uwsgi_log("Rados app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, rad_mountpoint, (int) ua->startup_time, ctx);
|
||||
}
|
||||
|
||||
// we translate the string list to an app representation
|
||||
// this happens before fork() if not in lazy/lazy-apps mode
|
||||
static void uwsgi_rados_setup() {
|
||||
if (!urados.timeout) {
|
||||
urados.timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = urados.mountpoints;
|
||||
while(usl) {
|
||||
uwsgi_rados_add_mountpoint(usl->value, usl->len);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_rados_request(struct wsgi_request *wsgi_req) {
|
||||
char filename[PATH_MAX+1];
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log( "Empty request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// blocks empty paths
|
||||
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) {
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, rados_plugin.modifier1);
|
||||
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
||||
if (uwsgi_apps[uwsgi.default_app].modifier1 == rados_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
}
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
if (wsgi_req->path_info_len > ua->mountpoint_len &&
|
||||
memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0)
|
||||
{
|
||||
memcpy(filename, wsgi_req->path_info+ua->mountpoint_len, wsgi_req->path_info_len-ua->mountpoint_len);
|
||||
} else {
|
||||
memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
filename[wsgi_req->path_info_len] = 0;
|
||||
|
||||
struct {
|
||||
uint64_t size;
|
||||
time_t mtime;
|
||||
} st;
|
||||
rados_ioctx_t ctx = ua->responder1;
|
||||
|
||||
int r = rados_stat(ctx, filename, &st.size, &st.mtime);
|
||||
if (r < 0) {
|
||||
if (r == -ENOENT)
|
||||
uwsgi_404(wsgi_req);
|
||||
else
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
size_t mime_type_len = 0;
|
||||
char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len);
|
||||
if (mime_type) {
|
||||
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.mtime)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.size)) goto end;
|
||||
|
||||
// skip body on HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
size_t remains = st.size;
|
||||
if (uwsgi.async > 1) {
|
||||
if (uwsgi_rados_read_async(wsgi_req, ctx, filename, remains)) goto end;
|
||||
}
|
||||
else {
|
||||
if (uwsgi_rados_read_sync(wsgi_req, ctx, filename, remains)) goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin rados_plugin = {
|
||||
.name = "rados",
|
||||
.modifier1 = 28,
|
||||
.options = uwsgi_rados_options,
|
||||
.post_fork = uwsgi_rados_setup,
|
||||
.request = uwsgi_rados_request,
|
||||
.after_request = log_request,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import os
|
||||
NAME='rados'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lrados']
|
||||
GCC_LIST = ['rados']
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
@@ -158,18 +158,19 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
argc = 0;
|
||||
argv[0] = strtok(args, "/");
|
||||
char *ctx = NULL;
|
||||
argv[0] = strtok_r(args, "/", &ctx);
|
||||
if (!argv[0]) {
|
||||
free(args);
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
char *p = strtok(NULL, "/");
|
||||
char *p = strtok_r(NULL, "/", &ctx);
|
||||
while(p) {
|
||||
argc++;
|
||||
argv[argc] = p;
|
||||
argvs[argc] = strlen(p);
|
||||
p = strtok(NULL, "/");
|
||||
p = strtok_r(NULL, "/", &ctx);
|
||||
}
|
||||
|
||||
wsgi_req->uh->pktsize = uwsgi_rpc(argv[0], argc, argv+1, argvs+1, response_buf);
|
||||
@@ -558,8 +559,8 @@ static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
|
||||
ur->custom = 0;
|
||||
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
|
||||
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
|
||||
char *p = strtok(args, " ");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(args, " ", p, ctx) {
|
||||
if (!ur->data) {
|
||||
ur->data = p;
|
||||
}
|
||||
@@ -576,7 +577,6 @@ static int uwsgi_router_rpc_base(struct uwsgi_route *ur, char *args) {
|
||||
argvs[ur->custom] = strlen(p);
|
||||
ur->custom++;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
if (!ur->data) {
|
||||
|
||||
@@ -39,10 +39,17 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
|
||||
uwsgi_socket_nb(ul->fd);
|
||||
|
||||
ul->count = 29;
|
||||
|
||||
char *comma = strchr(ul->arg, ',');
|
||||
if (comma) {
|
||||
ul->data = comma+1;
|
||||
*comma = 0;
|
||||
char *prisev = strchr(ul->data, ',');
|
||||
if (prisev) {
|
||||
*prisev = 0;
|
||||
ul->count = atoi(prisev+1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ul->data = uwsgi_concat2(uwsgi.hostname," uwsgi");
|
||||
@@ -83,7 +90,7 @@ ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len)
|
||||
for (pos=0 ; pos < (int) len ;) {
|
||||
if (pos > 0 && !u_rsyslog.split_msg) return pos;
|
||||
msg_len = ( ((int)len)-pos > u_rsyslog.msg_size ? u_rsyslog.msg_size : ((int)len)-pos);
|
||||
rlen = snprintf(ul->buf, u_rsyslog.packet_size, "<29>%.*s %s: %.*s", 15, ctime_storage+4, (char *) ul->data, msg_len, &message[pos]);
|
||||
rlen = snprintf(ul->buf, u_rsyslog.packet_size, "<%d>%.*s %s: %.*s", ul->count, 15, ctime_storage+4, (char *) ul->data, msg_len, &message[pos]);
|
||||
if (rlen > 0 && rlen <= u_rsyslog.packet_size) {
|
||||
ret = sendto(ul->fd, ul->buf, rlen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
if (ret <= 0) return ret;
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
#include "common.h"
|
||||
|
||||
extern struct uwsgi_tuntap utt;
|
||||
|
||||
// create a new peer
|
||||
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *uttr, int fd) {
|
||||
|
||||
struct uwsgi_tuntap_peer *uttp = uwsgi_calloc(sizeof(struct uwsgi_tuntap_peer));
|
||||
uttp->fd = fd;
|
||||
// leave space fot he uwsgi header
|
||||
uttp->buf = uwsgi_malloc(utt.buffer_size + 4);
|
||||
uttp->write_buf = uwsgi_malloc(utt.buffer_size);
|
||||
|
||||
if (uttr->peers_tail) {
|
||||
uttr->peers_tail->next = uttp;
|
||||
uttp->prev = uttr->peers_tail;
|
||||
uttr->peers_tail = uttp;
|
||||
}
|
||||
else {
|
||||
uttr->peers_head = uttp;
|
||||
uttr->peers_tail = uttp;
|
||||
}
|
||||
|
||||
return uttp;
|
||||
}
|
||||
|
||||
// destroy a peer
|
||||
void uwsgi_tuntap_peer_destroy(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
|
||||
struct uwsgi_tuntap_peer *prev = uttp->prev;
|
||||
struct uwsgi_tuntap_peer *next = uttp->next;
|
||||
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
if (uttp == uttr->peers_head) {
|
||||
uttr->peers_head = next;
|
||||
}
|
||||
|
||||
if (uttp == uttr->peers_tail) {
|
||||
uttr->peers_tail = prev;
|
||||
}
|
||||
|
||||
free(uttp->buf);
|
||||
free(uttp->write_buf);
|
||||
close(uttp->fd);
|
||||
free(uttp);
|
||||
}
|
||||
|
||||
|
||||
// get a peer by addr
|
||||
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_get_by_addr(struct uwsgi_tuntap_router *uttr, uint32_t addr) {
|
||||
struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
|
||||
while (uttp) {
|
||||
if (uttp->addr == addr)
|
||||
return uttp;
|
||||
uttp = uttp->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// block all reading peers
|
||||
void uwsgi_tuntap_block_reads(struct uwsgi_tuntap_router *uttr) {
|
||||
struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
|
||||
while (uttp) {
|
||||
if (!uttp->blocked_read) {
|
||||
if (!uttp->wait_for_write) {
|
||||
if (event_queue_del_fd(uttr->queue, uttp->fd, event_queue_read())) {
|
||||
struct uwsgi_tuntap_peer *tmp_uttp = uttp;
|
||||
uttp = uttp->next;
|
||||
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event_queue_fd_readwrite_to_write(uttr->queue, uttp->fd)) {
|
||||
struct uwsgi_tuntap_peer *tmp_uttp = uttp;
|
||||
uttp = uttp->next;
|
||||
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uttp->blocked_read = 1;
|
||||
}
|
||||
uttp = uttp->next;
|
||||
}
|
||||
}
|
||||
|
||||
//unblock all reading peers
|
||||
void uwsgi_tuntap_unblock_reads(struct uwsgi_tuntap_router *uttr) {
|
||||
struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
|
||||
while (uttp) {
|
||||
if (uttp->blocked_read) {
|
||||
if (!uttp->wait_for_write) {
|
||||
if (event_queue_add_fd_read(uttr->queue, uttp->fd)) {
|
||||
struct uwsgi_tuntap_peer *tmp_uttp = uttp;
|
||||
uttp = uttp->next;
|
||||
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event_queue_fd_write_to_readwrite(uttr->queue, uttp->fd)) {
|
||||
struct uwsgi_tuntap_peer *tmp_uttp = uttp;
|
||||
uttp = uttp->next;
|
||||
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uttp->blocked_read = 0;
|
||||
}
|
||||
uttp = uttp->next;
|
||||
}
|
||||
}
|
||||
|
||||
// enqueue a packet in the tuntap device
|
||||
void uwsgi_tuntap_enqueue(struct uwsgi_tuntap_router *uttr) {
|
||||
ssize_t rlen = write(uttr->fd, uttr->write_buf + uttr->write_pos, uttr->write_pktsize - uttr->write_pos);
|
||||
// error on the tuntap device, destroy !!!
|
||||
if (rlen == 0) {
|
||||
uwsgi_error("uwsgi_tuntap_enqueue()/write()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again())
|
||||
goto retry;
|
||||
uwsgi_error("uwsgi_tuntap_enqueue()/write()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uttr->write_pos += rlen;
|
||||
if (uttr->write_pos >= uttr->write_pktsize) {
|
||||
uttr->write_pos = 0;
|
||||
if (uttr->wait_for_write) {
|
||||
if (event_queue_fd_write_to_read(uttr->queue, uttr->fd)) {
|
||||
uwsgi_error("uwsgi_tuntap_enqueue()/event_queue_fd_read_to_write()");
|
||||
exit(1);
|
||||
}
|
||||
uttr->wait_for_write = 0;
|
||||
}
|
||||
uwsgi_tuntap_unblock_reads(uttr);
|
||||
return;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (!uttr->wait_for_write) {
|
||||
uwsgi_tuntap_block_reads(uttr);
|
||||
if (event_queue_fd_read_to_write(uttr->queue, uttr->fd)) {
|
||||
uwsgi_error("uwsgi_tuntap_enqueue()/event_queue_fd_read_to_write()");
|
||||
exit(1);
|
||||
}
|
||||
uttr->wait_for_write = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// receive a packet from the client
|
||||
int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
|
||||
// get body
|
||||
if (uttp->header_pos >= 4) {
|
||||
ssize_t rlen = read(uttp->fd, uttp->buf + uttp->buf_pos, uttp->buf_pktsize - uttp->buf_pos);
|
||||
if (rlen == 0)
|
||||
return -1;
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again())
|
||||
return 0;
|
||||
uwsgi_error("uwsgi_tuntap_peer_dequeue()/read()");
|
||||
return -1;
|
||||
}
|
||||
uttp->buf_pos += rlen;
|
||||
uttp->rx += rlen;
|
||||
// a whole pkt has been received
|
||||
if (uttp->buf_pos >= uttp->buf_pktsize) {
|
||||
|
||||
uttp->header_pos = 0;
|
||||
uttp->buf_pos = 0;
|
||||
|
||||
if (uwsgi_tuntap_firewall_check(utt.fw_out, uttp->buf, uttp->buf_pktsize)) return 0;
|
||||
|
||||
// if there is no associated address store the source
|
||||
if (!uttp->addr) {
|
||||
uint32_t *src_ip = (uint32_t *) & uttp->buf[12];
|
||||
uttp->addr = *src_ip;
|
||||
// drop invalid ip addresses
|
||||
if (!uttp->addr)
|
||||
return -1;
|
||||
|
||||
struct uwsgi_tuntap_peer *tmp_uttp = uwsgi_tuntap_peer_get_by_addr(uttr, uttp->addr);
|
||||
char ip[INET_ADDRSTRLEN + 1];
|
||||
memset(ip, 0, INET_ADDRSTRLEN + 1);
|
||||
if (!inet_ntop(AF_INET, &uttp->addr, ip, INET_ADDRSTRLEN)) {
|
||||
uwsgi_error("inet_ntop()");
|
||||
return -1;
|
||||
}
|
||||
if (uttp != tmp_uttp) {
|
||||
uwsgi_log("[tuntap-router] detected ip collision for %s\n", ip);
|
||||
uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
|
||||
}
|
||||
uwsgi_log("[tuntap-router] registered new peer %s (fd: %d)\n", ip, uttp->fd);
|
||||
}
|
||||
|
||||
memcpy(uttr->write_buf, uttp->buf, uttp->buf_pktsize);
|
||||
uttr->write_pktsize = uttp->buf_pktsize;
|
||||
uwsgi_tuntap_enqueue(uttr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ssize_t rlen = read(uttp->fd, uttp->header + uttp->header_pos, 4 - uttp->header_pos);
|
||||
if (rlen == 0)
|
||||
return -1;
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again())
|
||||
return 0;
|
||||
uwsgi_error("uwsgi_tuntap_peer_dequeue()/read()");
|
||||
return -1;
|
||||
}
|
||||
uttp->header_pos += rlen;
|
||||
if (uttp->header_pos >= 4) {
|
||||
uint16_t *pktsize = (uint16_t *) &uttp->header[1];
|
||||
uttp->buf_pktsize = *pktsize;
|
||||
uttp->rx += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enqueue a packet to the client
|
||||
int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
|
||||
|
||||
ssize_t rlen = write(uttp->fd, uttp->write_buf + uttp->written, uttp->write_buf_pktsize - uttp->written);
|
||||
if (rlen == 0) {
|
||||
uwsgi_error("uwsgi_tuntap_peer_enqueue()/write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again())
|
||||
goto retry;
|
||||
uwsgi_error("uwsgi_tuntap_peer_enqueue()/write()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uttp->written += rlen;
|
||||
uttp->tx += rlen;
|
||||
if (uttp->written >= uttp->write_buf_pktsize) {
|
||||
uttp->written = 0;
|
||||
uttp->write_buf_pktsize = 0;
|
||||
if (uttp->wait_for_write) {
|
||||
// if the write ends while we are writing to the tuntap, block the reads
|
||||
if (uttr->wait_for_write) {
|
||||
uttp->blocked_read = 1;
|
||||
if (event_queue_del_fd(uttr->queue, uttp->fd, event_queue_write())) {
|
||||
uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_del_fd()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event_queue_fd_readwrite_to_read(uttr->queue, uttp->fd)) {
|
||||
uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_write_to_read()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
uttp->wait_for_write = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
memmove(uttp->write_buf, uttp->write_buf + rlen, uttp->write_buf_pktsize - rlen);
|
||||
uttp->write_buf_pktsize -= rlen;
|
||||
|
||||
retry:
|
||||
if (!uttp->wait_for_write) {
|
||||
if (event_queue_fd_read_to_readwrite(uttr->queue, uttp->fd)) {
|
||||
uwsgi_error("uwsgi_tuntap_peer_enqueue()/event_queue_fd_read_to_write()");
|
||||
return -1;
|
||||
}
|
||||
uttp->wait_for_write = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_tuntap_device(char *name) {
|
||||
struct ifreq ifr;
|
||||
int fd = open(UWSGI_TUNTAP_DEVICE, O_RDWR);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(UWSGI_TUNTAP_DEVICE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
||||
strncpy(ifr.ifr_name, name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
|
||||
uwsgi_error("uwsgi_tuntap_device()/ioctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("initialized tuntap device %s (fd: %d)\n", ifr.ifr_name, fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/if_tun.h>
|
||||
#define UWSGI_TUNTAP_DEVICE "/dev/net/tun"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
a peer is a client connected to the router. It has 2 queue, one for read
|
||||
and one for write. The write queue can be filled up. If the write queue is full, packets are dropped.
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_tuntap_peer {
|
||||
int fd;
|
||||
uint32_t addr;
|
||||
int wait_for_write;
|
||||
int blocked_read;
|
||||
size_t written;
|
||||
char header[4];
|
||||
uint8_t header_pos;
|
||||
char *buf;
|
||||
uint16_t buf_pktsize;
|
||||
uint16_t buf_pos;
|
||||
char *write_buf;
|
||||
uint16_t write_buf_pktsize;
|
||||
uint16_t write_buf_pos;
|
||||
struct uwsgi_tuntap_peer *prev;
|
||||
struct uwsgi_tuntap_peer *next;
|
||||
// counters
|
||||
uint64_t tx;
|
||||
uint64_t rx;
|
||||
uint64_t dropped;
|
||||
};
|
||||
|
||||
struct uwsgi_tuntap_firewall_rule {
|
||||
uint8_t action;
|
||||
uint32_t src;
|
||||
uint32_t src_mask;
|
||||
uint32_t dst;
|
||||
uint32_t dst_mask;
|
||||
struct uwsgi_tuntap_firewall_rule *next;
|
||||
};
|
||||
|
||||
struct uwsgi_tuntap_router {
|
||||
int fd;
|
||||
int server_fd;
|
||||
int queue;
|
||||
char *buf;
|
||||
char *write_buf;
|
||||
struct uwsgi_tuntap_peer *peers_head;
|
||||
struct uwsgi_tuntap_peer *peers_tail;
|
||||
uint16_t write_pktsize;
|
||||
uint16_t write_pos;
|
||||
int wait_for_write;
|
||||
};
|
||||
|
||||
struct uwsgi_tuntap {
|
||||
struct uwsgi_string_list *routers;
|
||||
struct uwsgi_string_list *devices;
|
||||
uint16_t buffer_size;
|
||||
struct uwsgi_tuntap_firewall_rule *fw_in;
|
||||
struct uwsgi_tuntap_firewall_rule *fw_out;
|
||||
};
|
||||
|
||||
int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *);
|
||||
int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *);
|
||||
void uwsgi_tuntap_enqueue(struct uwsgi_tuntap_router *);
|
||||
|
||||
int uwsgi_tuntap_firewall_check(struct uwsgi_tuntap_firewall_rule *, char *, uint16_t);
|
||||
|
||||
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *, int);
|
||||
struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_get_by_addr(struct uwsgi_tuntap_router *,uint32_t);
|
||||
void uwsgi_tuntap_peer_destroy(struct uwsgi_tuntap_router *, struct uwsgi_tuntap_peer *);
|
||||
|
||||
int uwsgi_tuntap_device(char *);
|
||||
|
||||
void uwsgi_tuntap_opt_firewall(char *, char *, void *);
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "common.h"
|
||||
|
||||
extern struct uwsgi_tuntap utt;
|
||||
|
||||
int uwsgi_tuntap_firewall_check(struct uwsgi_tuntap_firewall_rule *direction, char *pkt, uint16_t len) {
|
||||
// sanity check
|
||||
if (len < 20) return -1;
|
||||
uint32_t *src_ip = (uint32_t *) &pkt[12];
|
||||
uint32_t *dst_ip = (uint32_t *) &pkt[16];
|
||||
|
||||
uint32_t src = ntohl(*src_ip);
|
||||
uint32_t dst = ntohl(*dst_ip);
|
||||
|
||||
struct uwsgi_tuntap_firewall_rule *utfr = direction;
|
||||
while(utfr) {
|
||||
if (utfr->src) {
|
||||
uint32_t src_masked = src & utfr->src_mask;
|
||||
if (src_masked != utfr->src) goto next;
|
||||
}
|
||||
|
||||
if (utfr->dst) {
|
||||
uint32_t dst_masked = dst & utfr->dst_mask;
|
||||
if (dst_masked != utfr->dst) goto next;
|
||||
}
|
||||
|
||||
return utfr->action;
|
||||
next:
|
||||
utfr = utfr->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_tuntap_firewall_add_rule(struct uwsgi_tuntap_firewall_rule **direction, uint8_t action, uint32_t src, uint32_t src_mask, uint32_t dst, uint32_t dst_mask) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[tuntap-router] firewall action %d %x %x %x %x\n",action, src,src_mask,dst,dst_mask);
|
||||
#endif
|
||||
|
||||
struct uwsgi_tuntap_firewall_rule *old_uttr = NULL, *uttr = *direction;
|
||||
while(uttr) {
|
||||
old_uttr = uttr;
|
||||
uttr = uttr->next;
|
||||
}
|
||||
|
||||
uttr = uwsgi_calloc(sizeof(struct uwsgi_tuntap_firewall_rule));
|
||||
uttr->action = action;
|
||||
uttr->src = src & src_mask;
|
||||
uttr->src_mask = src_mask;
|
||||
uttr->dst = dst & dst_mask;
|
||||
uttr->dst_mask = dst_mask;
|
||||
|
||||
if (old_uttr) {
|
||||
old_uttr->next = uttr;
|
||||
}
|
||||
else {
|
||||
*direction = uttr;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_tuntap_opt_firewall(char *opt, char *value, void *direction) {
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
if (!strcmp("deny", value)) {
|
||||
uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, 1, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
*space = 0;
|
||||
|
||||
uint8_t action = 0;
|
||||
if (!strcmp(value, "deny")) action = 1;
|
||||
|
||||
char *space2 = strchr(space + 1, ' ');
|
||||
if (!space2) {
|
||||
uwsgi_log("invalid tuntap firewall rule syntax. must be <action> <src/mask> <dst/mask>");
|
||||
}
|
||||
|
||||
*space2 = 0;
|
||||
|
||||
uint32_t src = 0;
|
||||
uint32_t src_mask = 32;
|
||||
uint32_t dst = 0;
|
||||
uint32_t dst_mask = 32;
|
||||
|
||||
char *slash = strchr(space + 1 , '/');
|
||||
if (slash) {
|
||||
src_mask = atoi(slash+1);
|
||||
*slash = 0;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, space + 1, &src) != 1) {
|
||||
uwsgi_error("uwsgi_tuntap_opt_firewall()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (slash) *slash = '/';
|
||||
*space = ' ';
|
||||
|
||||
slash = strchr(space2 + 1 , '/');
|
||||
if (slash) {
|
||||
dst_mask = atoi(slash+1);
|
||||
*slash = 0;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, space2 + 1, &dst) != 1) {
|
||||
uwsgi_error("uwsgi_tuntap_opt_firewall()/inet_pton()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (slash) *slash = '/';
|
||||
*space2 = ' ';
|
||||
|
||||
uwsgi_tuntap_firewall_add_rule((struct uwsgi_tuntap_firewall_rule **) direction, action, ntohl(src), (0xffffffff << (32-src_mask)), ntohl(dst), (0xffffffff << (32-dst_mask)));
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
#include "common.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_tuntap utt;
|
||||
|
||||
/*
|
||||
|
||||
The tuntap router is a non-blocking highly optimized ip router
|
||||
translating from tuntap device to socket streams.
|
||||
|
||||
It is meant as a replacement for the currently available networking namespaces
|
||||
approaches. Compared to veth or macvlan it is really simple and allows total control
|
||||
over the routing subsystem (in addition to a simple customizable firewalling engine)
|
||||
|
||||
Generally you spawn the tuntap router in the Emperor instance
|
||||
|
||||
[uwsgi]
|
||||
master = true
|
||||
emperor = /etc/uwsgi
|
||||
emperor-use-clone = fs,uts,ipc,pid,net
|
||||
tuntap-router = emperor0 /tmp/tuntap.socket
|
||||
exec-as-root = ifconfig emperor0 192.168.0.1 netmask 255.255.255.0 up
|
||||
exec-as-root = iptables -t nat -F
|
||||
exec-as-root = iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
|
||||
exec-as-root = echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
|
||||
vassals will run in new namespaces in which they create a tuntap device attached to
|
||||
the tuntap router. UNIX sockets are the only way to connect to the tuntap router
|
||||
after jailing.
|
||||
|
||||
Firewalling is based on 2 chains (in and out), and each rule is formed by 3 parameters: <action> <src> <dst>
|
||||
The firewall is applied to traffic from the clients to the tuntap device (out) and the opposite (in)
|
||||
|
||||
|
||||
The first matching rule stop the chain, if no rule applies, the policy is "allow"
|
||||
|
||||
the following rules allows access from vassals to the internet, but block
|
||||
vassals intercommunication
|
||||
|
||||
--tuntap-router-firewall-out = allow 192.168.0.0/24 192.168.0.1
|
||||
--tuntap-router-firewall-out = deny 192.168.0.0/24 192.168.0.0/24
|
||||
--tuntap-router-firewall-out = allow 192.168.0.0/24 0.0.0.0
|
||||
--tuntap-router-firewall-out = deny
|
||||
--tuntap-router-firewall-in = allow 192.168.0.1 192.168.0.0/24
|
||||
--tuntap-router-firewall-in = deny 192.168.0.0/24 192.168.0.0/24
|
||||
--tuntap-router-firewall-in = allow 0.0.0.0 192.168.0.0/24
|
||||
--tuntap-router-firewall-in = deny
|
||||
|
||||
Author: Roberto De Ioris
|
||||
|
||||
TODO:
|
||||
|
||||
- some form of security to disallow raw access to the tuntap router unix socket
|
||||
- stats server
|
||||
- port to other platforms ?
|
||||
|
||||
*/
|
||||
|
||||
static struct uwsgi_option uwsgi_tuntap_options[] = {
|
||||
{"tuntap-router", required_argument, 0, "run the tuntap router (syntax: <device> <socket> [stats])", uwsgi_opt_add_string_list, &utt.routers, 0},
|
||||
{"tuntap-device", required_argument, 0, "add a tuntap device to the instance (syntax: <device>[ <socket>])", uwsgi_opt_add_string_list, &utt.devices, 0},
|
||||
{"tuntap-router-firewall-in", required_argument, 0, "add a firewall rule to the tuntap router (syntax: <action> <src/mask> <dst/mask>)", uwsgi_tuntap_opt_firewall, &utt.fw_in, 0},
|
||||
{"tuntap-router-firewall-out", required_argument, 0, "add a firewall rule to the tuntap router (syntax: <action> <src/mask> <dst/mask>)", uwsgi_tuntap_opt_firewall, &utt.fw_out, 0},
|
||||
{NULL, 0, 0, NULL, NULL, NULL, 0},
|
||||
};
|
||||
|
||||
static void *uwsgi_tuntap_loop(void *arg) {
|
||||
|
||||
// block signals on this thread
|
||||
sigset_t smask;
|
||||
sigfillset(&smask);
|
||||
#ifndef UWSGI_DEBUG
|
||||
sigdelset(&smask, SIGSEGV);
|
||||
#endif
|
||||
pthread_sigmask(SIG_BLOCK, &smask, NULL);
|
||||
|
||||
struct uwsgi_tuntap_router *uttr = (struct uwsgi_tuntap_router *) arg;
|
||||
|
||||
uwsgi_socket_nb(uttr->fd);
|
||||
|
||||
if (!utt.buffer_size)
|
||||
utt.buffer_size = 8192;
|
||||
uttr->buf = uwsgi_malloc(utt.buffer_size);
|
||||
uttr->write_buf = uwsgi_malloc(utt.buffer_size);
|
||||
|
||||
uttr->queue = event_queue_init();
|
||||
|
||||
if (event_queue_add_fd_read(uttr->queue, uttr->fd)) {
|
||||
exit(1);
|
||||
}
|
||||
if (event_queue_add_fd_read(uttr->queue, uttr->server_fd)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(uttr->server_fd);
|
||||
|
||||
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, uttr->server_fd);
|
||||
|
||||
for (;;) {
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(uttr->queue, -1, &interesting_fd);
|
||||
|
||||
if (ret <= 0)
|
||||
continue;
|
||||
|
||||
if (interesting_fd == uttr->fd) {
|
||||
if (uttr->wait_for_write) {
|
||||
uwsgi_tuntap_enqueue(uttr);
|
||||
continue;
|
||||
}
|
||||
ssize_t rlen = read(uttr->fd, uttr->buf, utt.buffer_size);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("uwsgi_tuntap_loop()/read()");
|
||||
exit(1);
|
||||
}
|
||||
uint16_t pktsize = rlen;
|
||||
char *ptr = uttp->write_buf + uttp->write_buf_pktsize;
|
||||
memcpy(ptr + 4, uttr->buf, rlen);
|
||||
ptr[0] = 0;
|
||||
ptr[1] = (uint8_t) (pktsize & 0xff);
|
||||
ptr[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
ptr[3] = 0;
|
||||
uttp->write_buf_pktsize+= pktsize+4;
|
||||
if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) {
|
||||
uwsgi_log("server disconnected...\n");
|
||||
exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (interesting_fd == uttr->server_fd) {
|
||||
// read from the client
|
||||
if (!uttp->wait_for_write) {
|
||||
if (uwsgi_tuntap_peer_dequeue(uttr, uttp)) {
|
||||
uwsgi_log("server disconnected...\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// something is wrong (the tuntap device is blocked)
|
||||
if (uttr->wait_for_write) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// write to the client
|
||||
if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) {
|
||||
uwsgi_log("server disconnected...\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uwsgi_tuntap_client() {
|
||||
|
||||
if (!utt.devices) return;
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, utt.devices) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
struct uwsgi_tuntap_router *uttr = uwsgi_calloc(sizeof(struct uwsgi_tuntap_router));
|
||||
uttr->fd = uwsgi_tuntap_device(usl->value);
|
||||
|
||||
uttr->server_fd = uwsgi_connect(space+1, 30, 0);
|
||||
if (uttr->server_fd < 0) {
|
||||
uwsgi_error("uwsgi_tuntap_client()/uwsgi_connect()");
|
||||
exit(1);
|
||||
}
|
||||
*space = ' ';
|
||||
|
||||
pthread_t t;
|
||||
pthread_create(&t, NULL, uwsgi_tuntap_loop, uttr);
|
||||
}
|
||||
else {
|
||||
if (uwsgi_tuntap_device(usl->value) < 0) {
|
||||
// foo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_tuntap_router_loop(int id, void *arg) {
|
||||
int i;
|
||||
|
||||
struct uwsgi_tuntap_router *uttr = (struct uwsgi_tuntap_router *) arg;
|
||||
uttr->buf = uwsgi_malloc(utt.buffer_size);
|
||||
uttr->write_buf = uwsgi_malloc(utt.buffer_size);
|
||||
uttr->queue = event_queue_init();
|
||||
|
||||
void *events = event_queue_alloc(64);
|
||||
if (event_queue_add_fd_read(uttr->queue, uttr->server_fd))
|
||||
exit(1);
|
||||
if (event_queue_add_fd_read(uttr->queue, uttr->fd))
|
||||
exit(1);
|
||||
|
||||
for (;;) {
|
||||
int nevents = event_queue_wait_multi(uttr->queue, -1, events, 64);
|
||||
for (i = 0; i < nevents; i++) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, i);
|
||||
if (interesting_fd == uttr->fd) {
|
||||
// if writing, continue enqueuing
|
||||
if (uttr->wait_for_write) {
|
||||
uwsgi_tuntap_enqueue(uttr);
|
||||
continue;
|
||||
}
|
||||
ssize_t rlen = read(uttr->fd, uttr->buf, utt.buffer_size);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("uwsgi_tuntap_router_loop()/read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi_tuntap_firewall_check(utt.fw_in, uttr->buf, rlen)) continue;
|
||||
|
||||
uint32_t *dst_ip = (uint32_t *) & uttr->buf[16];
|
||||
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_get_by_addr(uttr, *dst_ip);
|
||||
if (!uttp)
|
||||
continue;
|
||||
|
||||
// check for full write buffer
|
||||
if (uttp->write_buf_pktsize + 4 + rlen > utt.buffer_size) {
|
||||
uttp->dropped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t pktsize = rlen;
|
||||
char *ptr = uttp->write_buf + uttp->write_buf_pktsize;
|
||||
memcpy(ptr + 4, uttr->buf, rlen);
|
||||
ptr[0] = 0;
|
||||
ptr[1] = (uint8_t) (pktsize & 0xff);
|
||||
ptr[2] = (uint8_t) ((pktsize >> 8) & 0xff);
|
||||
ptr[3] = 0;
|
||||
uttp->write_buf_pktsize+= pktsize+4;
|
||||
if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) {
|
||||
uwsgi_tuntap_peer_destroy(uttr, uttp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (interesting_fd == uttr->server_fd) {
|
||||
int client_fd = uwsgi_accept(uttr->server_fd);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("uwsgi_tuntap_server_loop()/accept()");
|
||||
continue;
|
||||
}
|
||||
struct uwsgi_tuntap_peer *uttp = uwsgi_tuntap_peer_create(uttr, client_fd);
|
||||
if (event_queue_add_fd_read(uttr->queue, uttp->fd)) {
|
||||
uwsgi_tuntap_peer_destroy(uttr, uttp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
|
||||
while (uttp) {
|
||||
if (interesting_fd == uttp->fd) {
|
||||
// read from the client
|
||||
if (event_queue_interesting_fd_is_read(events, i)) {
|
||||
if (uwsgi_tuntap_peer_dequeue(uttr, uttp)) {
|
||||
uwsgi_tuntap_peer_destroy(uttr, uttp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (event_queue_interesting_fd_is_write(events, i)) {
|
||||
// something is wrong (the tuntap device is blocked)
|
||||
if (uttr->wait_for_write)
|
||||
break;
|
||||
|
||||
// write to the client
|
||||
if (uwsgi_tuntap_peer_enqueue(uttr, uttp)) {
|
||||
uwsgi_tuntap_peer_destroy(uttr, uttp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
uttp = uttp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_tuntap_router() {
|
||||
|
||||
if (!utt.routers) return;
|
||||
|
||||
if (!utt.buffer_size)
|
||||
utt.buffer_size = 8192;
|
||||
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, utt.routers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid tuntap router syntax, must be <device> <socket> [stats]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_tuntap_router *uttr = uwsgi_calloc(sizeof(struct uwsgi_tuntap_router));
|
||||
|
||||
uttr->server_fd = bind_to_unix(space+1, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
|
||||
*space = 0 ;
|
||||
uttr->fd = uwsgi_tuntap_device(usl->value);
|
||||
*space = ' ';
|
||||
|
||||
if (register_gateway("uWSGI tuntap router", uwsgi_tuntap_router_loop, uttr) == NULL) {
|
||||
uwsgi_log("unable to register the tuntap server gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_plugin tuntap_plugin = {
|
||||
.name = "tuntap",
|
||||
.options = uwsgi_tuntap_options,
|
||||
.post_jail = uwsgi_tuntap_client,
|
||||
.jail = uwsgi_tuntap_router,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='tuntap'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=[]
|
||||
GCC_LIST=['common','firewall','tuntap']
|
||||
@@ -158,11 +158,10 @@ static void uwsgi_webdav_add_a_prop(xmlNode *node, char *opt, xmlNode *req_prop,
|
||||
else if (type == 2) {
|
||||
new_node = xmlNewChild(node, NULL, BAD_CAST first_space + 1, NULL);
|
||||
char *comps = uwsgi_str(second_space + 1);
|
||||
char *p = strtok(comps, ",");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(comps, ",", p, ctx) {
|
||||
xmlNode *comp = xmlNewChild(new_node, NULL, BAD_CAST "comp", NULL);
|
||||
xmlNewProp(comp, BAD_CAST "name", BAD_CAST p);
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(comps);
|
||||
}
|
||||
|
||||
+2
-3
@@ -72,16 +72,15 @@ static char *uwsgi_xslt_apply(xmlDoc *doc, char *xsltfile, char *params, int *rl
|
||||
}
|
||||
vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
|
||||
tmp_params = uwsgi_str(params);
|
||||
char *p = strtok(tmp_params, "&");
|
||||
int pos = 0;
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_params, "&", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
vparams[pos] = p; pos++;
|
||||
vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;
|
||||
}
|
||||
p = strtok(NULL, "&");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,18 +91,17 @@ struct zergpool_socket *add_zergpool_socket(char *name, char *sockets) {
|
||||
}
|
||||
|
||||
char *sock_list = uwsgi_str(sockets);
|
||||
char *p = strtok(sock_list, ",");
|
||||
while(p) {
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(sock_list, ",", p, ctx) {
|
||||
z_sock->num_sockets++;
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(sock_list);
|
||||
z_sock->sockets = uwsgi_calloc(sizeof(int) * (z_sock->num_sockets + 1));
|
||||
|
||||
sock_list = uwsgi_str(sockets);
|
||||
int pos = 0;
|
||||
p = strtok(sock_list, ",");
|
||||
while(p) {
|
||||
ctx = NULL;
|
||||
uwsgi_foreach_token(sock_list, ",", p, ctx) {
|
||||
char *port = strchr(p, ':');
|
||||
char *sockname;
|
||||
if (!port) {
|
||||
@@ -117,7 +116,6 @@ struct zergpool_socket *add_zergpool_socket(char *name, char *sockets) {
|
||||
uwsgi_log("zergpool %s bound to TCP socket %s (fd: %d)\n", name, sockname, z_sock->sockets[pos]);
|
||||
}
|
||||
pos++;
|
||||
p = strtok(NULL, ",");
|
||||
free(sockname);
|
||||
}
|
||||
free(sock_list);
|
||||
|
||||
+19
-6
@@ -103,6 +103,9 @@ parse:
|
||||
uint16_t fcgi_len = uwsgi_be16((char *)&fr->cl1);
|
||||
uint32_t fcgi_all_len = sizeof(struct fcgi_record) + fcgi_len + fr->pad;
|
||||
uint8_t fcgi_type = fr->type;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
sid[0] = fr->req0;
|
||||
sid[1] = fr->req1;
|
||||
// if STDIN, end of the loop
|
||||
if (fcgi_type == 5) {
|
||||
wsgi_req->uh->modifier1 = uwsgi.fastcgi_modifier1;
|
||||
@@ -235,8 +238,9 @@ int uwsgi_proto_fastcgi_write(struct wsgi_request *wsgi_req, char *buf, size_t l
|
||||
struct fcgi_record fr;
|
||||
fr.version = 1;
|
||||
fr.type = 6;
|
||||
fr.req1 = 0;
|
||||
fr.req0 = 1;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
fr.req1 = sid[1];
|
||||
fr.req0 = sid[0];
|
||||
fr.pad = 0;
|
||||
fr.reserved = 0;
|
||||
fr.cl0 = (uint8_t) (fcgi_len & 0xff);
|
||||
@@ -265,8 +269,16 @@ int uwsgi_proto_fastcgi_write(struct wsgi_request *wsgi_req, char *buf, size_t l
|
||||
}
|
||||
|
||||
void uwsgi_proto_fastcgi_close(struct wsgi_request *wsgi_req) {
|
||||
// special case here, we run i nvoid context, so we need to wait directly here
|
||||
(void) uwsgi_write_true_nb(wsgi_req->fd, (char *) FCGI_END_REQUEST, sizeof(FCGI_END_REQUEST), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
// special case here, we run in void context, so we need to wait directly here
|
||||
char end_request[24];
|
||||
memcpy(end_request, FCGI_END_REQUEST, 24);
|
||||
char *sid = (char *) &wsgi_req->stream_id;
|
||||
// update with request id
|
||||
end_request[2] = sid[1];
|
||||
end_request[3] = sid[0];
|
||||
end_request[10] = sid[1];
|
||||
end_request[11] = sid[0];
|
||||
(void) uwsgi_write_true_nb(wsgi_req->fd, end_request, 24, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
uwsgi_proto_base_close(wsgi_req);
|
||||
}
|
||||
|
||||
@@ -279,8 +291,9 @@ int uwsgi_proto_fastcgi_sendfile(struct wsgi_request *wsgi_req, int fd, size_t p
|
||||
struct fcgi_record fr;
|
||||
fr.version = 1;
|
||||
fr.type = 6;
|
||||
fr.req1 = 0;
|
||||
fr.req0 = 1;
|
||||
uint8_t *sid = (uint8_t *) &wsgi_req->stream_id;
|
||||
fr.req1 = sid[1];
|
||||
fr.req0 = sid[0];
|
||||
fr.pad = 0;
|
||||
fr.reserved = 0;
|
||||
fr.cl0 = (uint8_t) (fcgi_len & 0xff);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
import pyuwsgi
|
||||
|
||||
orig_args = sys.argv
|
||||
orig_executable = sys.executable
|
||||
orig_args.insert(0, orig_executable)
|
||||
|
||||
uwsgi_args = []
|
||||
|
||||
uwsgi_args.append('--socket')
|
||||
uwsgi_args.append(':3031')
|
||||
#uwsgi_args.append('--master')
|
||||
uwsgi_args.append('--module')
|
||||
#uwsgi_args.append('welcome')
|
||||
uwsgi_args.append('hello')
|
||||
|
||||
#pyuwsgi.run('welcome.ini')
|
||||
pyuwsgi.run(uwsgi_args)
|
||||
|
||||
# if you are here uWSGI has been reloaded
|
||||
os.execv(orig_executable, orig_args)
|
||||
+1
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2013-08-29'
|
||||
s.date = '2013-09-22'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
|
||||
@@ -10,7 +10,7 @@ extern "C" {
|
||||
#define UMAX8 256
|
||||
|
||||
#define UMAX64_STR "18446744073709551615"
|
||||
#define MAX64_STR "−9223372036854775808"
|
||||
#define MAX64_STR "-9223372036854775808"
|
||||
|
||||
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_error_realpath(x) uwsgi_log("realpath() of %s failed: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
@@ -132,6 +132,8 @@ extern "C" {
|
||||
|
||||
#define uwsgi_foreach(x, y) for(x=y;x;x = x->next)
|
||||
|
||||
#define uwsgi_foreach_token(x, y, z, w) for(z=strtok_r(x, y, &w);z;z = strtok_r(NULL, y, &w))
|
||||
|
||||
|
||||
#ifndef __need_IOV_MAX
|
||||
#define __need_IOV_MAX
|
||||
@@ -199,6 +201,10 @@ extern "C" {
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/jail.h>
|
||||
#ifdef UWSGI_HAS_FREEBSD_LIBJAIL
|
||||
#include <jail.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
@@ -229,7 +235,13 @@ extern "C" {
|
||||
#include <sched.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux) || defined(__FreeBSD__)
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
extern int pivot_root(const char *new_root, const char *put_old);
|
||||
#endif
|
||||
|
||||
@@ -443,6 +455,12 @@ struct uwsgi_dyn_dict {
|
||||
struct uwsgi_dyn_dict *next;
|
||||
};
|
||||
|
||||
struct uwsgi_hook {
|
||||
char *name;
|
||||
int (*func)(char *);
|
||||
struct uwsgi_hook *next;
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
struct uwsgi_regexp_list {
|
||||
|
||||
@@ -553,6 +571,7 @@ struct uwsgi_daemon {
|
||||
int status;
|
||||
int registered;
|
||||
|
||||
int has_daemonized;
|
||||
|
||||
char *pidfile;
|
||||
int daemonize;
|
||||
@@ -853,6 +872,7 @@ struct uwsgi_opt {
|
||||
#define UWSGI_DE_HIJACKED_CODE 173
|
||||
#define UWSGI_EXCEPTION_CODE 5
|
||||
#define UWSGI_QUIET_CODE 29
|
||||
#define UWSGI_BRUTAL_RELOAD_CODE 31
|
||||
|
||||
#define MAX_VARS 64
|
||||
|
||||
@@ -985,6 +1005,7 @@ struct uwsgi_plugin {
|
||||
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
|
||||
|
||||
void (*jail) (int (*)(void *), char **);
|
||||
void (*post_jail) (void);
|
||||
void (*before_privileges_drop) (void);
|
||||
|
||||
int (*mule) (char *);
|
||||
@@ -1233,6 +1254,16 @@ struct uwsgi_logvar {
|
||||
struct uwsgi_logvar *next;
|
||||
};
|
||||
|
||||
struct uwsgi_log_encoder {
|
||||
char *name;
|
||||
char *(*func)(struct uwsgi_log_encoder *, char *, size_t, size_t *);
|
||||
int configured;
|
||||
char *use_for;
|
||||
char *args;
|
||||
void *data;
|
||||
struct uwsgi_log_encoder *next;
|
||||
};
|
||||
|
||||
struct uwsgi_transformation {
|
||||
int (*func)(struct wsgi_request *, struct uwsgi_transformation *);
|
||||
struct uwsgi_buffer *chunk;
|
||||
@@ -1465,14 +1496,18 @@ struct wsgi_request {
|
||||
int is_routing;
|
||||
int is_final_routing;
|
||||
int is_error_routing;
|
||||
int is_response_routing;
|
||||
int routes_applied;
|
||||
int response_routes_applied;
|
||||
// internal routing vm program counter
|
||||
uint32_t route_pc;
|
||||
uint32_t error_route_pc;
|
||||
uint32_t response_route_pc;
|
||||
uint32_t final_route_pc;
|
||||
// internal routing goto instruction
|
||||
uint32_t route_goto;
|
||||
uint32_t error_route_goto;
|
||||
uint32_t response_route_goto;
|
||||
uint32_t final_route_goto;
|
||||
|
||||
int ignore_body;
|
||||
@@ -1648,6 +1683,17 @@ struct uwsgi_server {
|
||||
|
||||
// leave master running as root
|
||||
int master_as_root;
|
||||
// postpone privileges drop
|
||||
int drop_after_init;
|
||||
int drop_after_apps;
|
||||
|
||||
int master_is_reforked;
|
||||
|
||||
struct uwsgi_string_list *master_fifo;
|
||||
int master_fifo_fd;
|
||||
int master_fifo_slot;
|
||||
|
||||
|
||||
// kill the stack on SIGTERM (instead of brutal reloading)
|
||||
int die_on_term;
|
||||
|
||||
@@ -1690,6 +1736,12 @@ struct uwsgi_server {
|
||||
// enable idle mode
|
||||
int idle;
|
||||
|
||||
// cheaper mode memory usage limits
|
||||
uint64_t cheaper_rss_limit_soft;
|
||||
uint64_t cheaper_rss_limit_hard;
|
||||
|
||||
int cheaper_fifo_delta;
|
||||
|
||||
// destroy the stack when idle
|
||||
int die_on_idle;
|
||||
|
||||
@@ -1734,6 +1786,7 @@ struct uwsgi_server {
|
||||
char *emperor_stats;
|
||||
int emperor_stats_fd;
|
||||
struct uwsgi_string_list *vassals_templates;
|
||||
struct uwsgi_string_list *vassals_includes;
|
||||
// true if loyal to the emperor
|
||||
int loyal;
|
||||
|
||||
@@ -1743,6 +1796,7 @@ struct uwsgi_server {
|
||||
|
||||
struct uwsgi_string_list *additional_headers;
|
||||
struct uwsgi_string_list *remove_headers;
|
||||
struct uwsgi_string_list *collect_headers;
|
||||
|
||||
// set cpu affinity
|
||||
int cpu_affinity;
|
||||
@@ -1814,8 +1868,22 @@ struct uwsgi_server {
|
||||
#ifdef __linux__
|
||||
int unshare;
|
||||
int emperor_clone;
|
||||
char *pivot_root;
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
char *jail;
|
||||
struct uwsgi_string_list *jail_ip4;
|
||||
#ifdef AF_INET6
|
||||
struct uwsgi_string_list *jail_ip6;
|
||||
#endif
|
||||
struct uwsgi_string_list *jail2;
|
||||
char *jidfile;
|
||||
char *jail_attach;
|
||||
#endif
|
||||
int refork;
|
||||
int refork_as_root;
|
||||
int refork_post_jail;
|
||||
|
||||
int ignore_sigpipe;
|
||||
int ignore_write_errors;
|
||||
@@ -1878,6 +1946,8 @@ struct uwsgi_server {
|
||||
int log_master;
|
||||
char *log_master_buf;
|
||||
size_t log_master_bufsize;
|
||||
int log_master_stream;
|
||||
int log_master_req_stream;
|
||||
|
||||
int log_reopen;
|
||||
int log_truncate;
|
||||
@@ -1893,6 +1963,23 @@ struct uwsgi_server {
|
||||
|
||||
struct uwsgi_string_list *mime_file;
|
||||
|
||||
struct uwsgi_hook *hooks;
|
||||
|
||||
struct uwsgi_string_list *hook_asap;
|
||||
struct uwsgi_string_list *hook_pre_jail;
|
||||
struct uwsgi_string_list *hook_post_jail;
|
||||
struct uwsgi_string_list *hook_in_jail;
|
||||
struct uwsgi_string_list *hook_as_root;
|
||||
struct uwsgi_string_list *hook_as_user;
|
||||
struct uwsgi_string_list *hook_as_user_atexit;
|
||||
struct uwsgi_string_list *hook_pre_app;
|
||||
struct uwsgi_string_list *hook_post_app;
|
||||
|
||||
struct uwsgi_string_list *hook_as_vassal;
|
||||
struct uwsgi_string_list *hook_as_emperor;
|
||||
|
||||
|
||||
struct uwsgi_string_list *exec_asap;
|
||||
struct uwsgi_string_list *exec_pre_jail;
|
||||
struct uwsgi_string_list *exec_post_jail;
|
||||
struct uwsgi_string_list *exec_in_jail;
|
||||
@@ -1905,6 +1992,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *exec_as_vassal;
|
||||
struct uwsgi_string_list *exec_as_emperor;
|
||||
|
||||
struct uwsgi_string_list *call_asap;
|
||||
struct uwsgi_string_list *call_pre_jail;
|
||||
struct uwsgi_string_list *call_post_jail;
|
||||
struct uwsgi_string_list *call_in_jail;
|
||||
@@ -1923,6 +2011,24 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *call_as_emperor2;
|
||||
struct uwsgi_string_list *call_as_emperor4;
|
||||
|
||||
struct uwsgi_string_list *mount_asap;
|
||||
struct uwsgi_string_list *mount_pre_jail;
|
||||
struct uwsgi_string_list *mount_post_jail;
|
||||
struct uwsgi_string_list *mount_in_jail;
|
||||
struct uwsgi_string_list *mount_as_root;
|
||||
|
||||
struct uwsgi_string_list *mount_as_vassal;
|
||||
struct uwsgi_string_list *mount_as_emperor;
|
||||
|
||||
struct uwsgi_string_list *umount_asap;
|
||||
struct uwsgi_string_list *umount_pre_jail;
|
||||
struct uwsgi_string_list *umount_post_jail;
|
||||
struct uwsgi_string_list *umount_in_jail;
|
||||
struct uwsgi_string_list *umount_as_root;
|
||||
|
||||
struct uwsgi_string_list *umount_as_vassal;
|
||||
struct uwsgi_string_list *umount_as_emperor;
|
||||
|
||||
struct uwsgi_string_list *wait_for_interface;
|
||||
int wait_for_interface_timeout;
|
||||
|
||||
@@ -1937,6 +2043,10 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *requested_logger;
|
||||
struct uwsgi_string_list *requested_req_logger;
|
||||
|
||||
struct uwsgi_log_encoder *log_encoders;
|
||||
struct uwsgi_string_list *requested_log_encoders;
|
||||
struct uwsgi_string_list *requested_log_req_encoders;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
int pcre_jit;
|
||||
struct uwsgi_regexp_list *log_drain_rules;
|
||||
@@ -2028,6 +2138,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_thread **offload_thread;
|
||||
|
||||
int check_static_docroot;
|
||||
int disable_sendfile;
|
||||
|
||||
char *daemonize;
|
||||
char *daemonize2;
|
||||
@@ -2216,6 +2327,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_route *routes;
|
||||
struct uwsgi_route *final_routes;
|
||||
struct uwsgi_route *error_routes;
|
||||
struct uwsgi_route *response_routes;
|
||||
struct uwsgi_route_condition *route_conditions;
|
||||
struct uwsgi_route_var *route_vars;
|
||||
#endif
|
||||
@@ -2232,6 +2344,7 @@ struct uwsgi_server {
|
||||
char *force_cwd;
|
||||
char *chdir;
|
||||
char *chdir2;
|
||||
struct uwsgi_string_list *binsh;
|
||||
|
||||
int vacuum;
|
||||
int no_server;
|
||||
@@ -2358,6 +2471,7 @@ struct uwsgi_server {
|
||||
|
||||
|
||||
int locks;
|
||||
int persistent_ipcsem;
|
||||
|
||||
struct uwsgi_lock_item *queue_lock;
|
||||
struct uwsgi_lock_item **user_lock;
|
||||
@@ -3462,6 +3576,7 @@ void uwsgi_opt_add_route(char *, char *, void *);
|
||||
int uwsgi_apply_routes(struct wsgi_request *);
|
||||
void uwsgi_apply_final_routes(struct wsgi_request *);
|
||||
int uwsgi_apply_error_routes(struct wsgi_request *);
|
||||
int uwsgi_apply_response_routes(struct wsgi_request *);
|
||||
int uwsgi_apply_routes_do(struct uwsgi_route *, struct wsgi_request *, char *, uint16_t);
|
||||
void uwsgi_register_embedded_routers(void);
|
||||
void uwsgi_routing_dump();
|
||||
@@ -3488,6 +3603,7 @@ int uwsgi_calc_cheaper(void);
|
||||
int uwsgi_cheaper_algo_spare(void);
|
||||
int uwsgi_cheaper_algo_backlog(void);
|
||||
int uwsgi_cheaper_algo_backlog2(void);
|
||||
int uwsgi_cheaper_algo_manual(void);
|
||||
|
||||
int uwsgi_master_log(void);
|
||||
int uwsgi_master_req_log(void);
|
||||
@@ -3508,6 +3624,7 @@ void uwsgi_setup_post_buffering(void);
|
||||
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *);
|
||||
|
||||
void uwsgi_write_pidfile(char *);
|
||||
int uwsgi_write_intfile(char *, int);
|
||||
|
||||
void uwsgi_protected_close(int);
|
||||
ssize_t uwsgi_protected_read(int, void *, size_t);
|
||||
@@ -3752,8 +3869,10 @@ int uwsgi_buffer_u16le(struct uwsgi_buffer *, uint16_t);
|
||||
int uwsgi_buffer_u16be(struct uwsgi_buffer *, uint16_t);
|
||||
int uwsgi_buffer_u32be(struct uwsgi_buffer *, uint32_t);
|
||||
int uwsgi_buffer_u32le(struct uwsgi_buffer *, uint32_t);
|
||||
int uwsgi_buffer_f32be(struct uwsgi_buffer *, float);
|
||||
int uwsgi_buffer_u24be(struct uwsgi_buffer *, uint32_t);
|
||||
int uwsgi_buffer_u64be(struct uwsgi_buffer *, uint64_t);
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *, double);
|
||||
int uwsgi_buffer_num64(struct uwsgi_buffer *, int64_t);
|
||||
int uwsgi_buffer_append_keyval(struct uwsgi_buffer *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *, char *, uint32_t, char *, uint32_t);
|
||||
@@ -4162,7 +4281,6 @@ void uwsgi_envdir(char *);
|
||||
void uwsgi_envdirs(struct uwsgi_string_list *);
|
||||
void uwsgi_opt_envdir(char *, char *, void *);
|
||||
|
||||
void uwsgi_add_reload_fds();
|
||||
void uwsgi_add_reload_fds();
|
||||
|
||||
void uwsgi_check_emperor(void);
|
||||
@@ -4183,6 +4301,44 @@ void uwsgi_cache_rlock(struct uwsgi_cache *);
|
||||
void uwsgi_cache_rwunlock(struct uwsgi_cache *);
|
||||
char *uwsgi_cache_item_key(struct uwsgi_cache_item *);
|
||||
|
||||
char *uwsgi_binsh(void);
|
||||
int uwsgi_file_executable(char *);
|
||||
|
||||
int uwsgi_mount(char *, char *, char *, char *);
|
||||
int uwsgi_umount(char *, char *);
|
||||
int uwsgi_mount_hook(char *);
|
||||
int uwsgi_umount_hook(char *);
|
||||
|
||||
void uwsgi_hooks_run(struct uwsgi_string_list *, char *, int);
|
||||
void uwsgi_register_hook(char *, int (*)(char *));
|
||||
struct uwsgi_hook *uwsgi_hook_by_name(char *);
|
||||
void uwsgi_register_base_hooks(void);
|
||||
|
||||
void uwsgi_setup_log_encoders(void);
|
||||
void uwsgi_log_encoders_register_embedded(void);
|
||||
|
||||
void uwsgi_register_log_encoder(char *, char *(*)(struct uwsgi_log_encoder *, char *, size_t, size_t *));
|
||||
|
||||
int uwsgi_accept(int);
|
||||
void suspend_resume_them_all(int);
|
||||
|
||||
void uwsgi_master_fifo_prepare();
|
||||
int uwsgi_master_fifo();
|
||||
int uwsgi_master_fifo_manage(int);
|
||||
|
||||
void uwsgi_log_rotate();
|
||||
void uwsgi_log_reopen();
|
||||
void uwsgi_reload_workers();
|
||||
void uwsgi_chain_reload();
|
||||
void uwsgi_refork_master();
|
||||
void uwsgi_update_pidfiles();
|
||||
void gracefully_kill_them_all(int);
|
||||
void uwsgi_brutally_reload_workers();
|
||||
|
||||
void uwsgi_cheaper_increase();
|
||||
void uwsgi_cheaper_decrease();
|
||||
void uwsgi_go_cheap();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+8
-4
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.15'
|
||||
uwsgi_version = '1.9.17'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -507,11 +507,11 @@ class uConf(object):
|
||||
|
||||
self.config.readfp(open_profile(filename))
|
||||
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
|
||||
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
|
||||
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks', 'core/fifo',
|
||||
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions', 'core/config',
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron',
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon', 'core/mount',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
@@ -692,6 +692,7 @@ class uConf(object):
|
||||
|
||||
if uwsgi_os == 'SunOS':
|
||||
self.libs.append('-lsendfile')
|
||||
self.libs.append('-lrt')
|
||||
self.gcc_list.append('lib/sun_fixes')
|
||||
self.ldflags.append('-L/lib')
|
||||
if not uwsgi_os_v.startswith('Nexenta'):
|
||||
@@ -951,6 +952,9 @@ class uConf(object):
|
||||
uwsgi_version += self.get('append_version')
|
||||
|
||||
|
||||
if uwsgi_os == 'FreeBSD' and self.has_include('jail.h'):
|
||||
self.cflags.append('-DUWSGI_HAS_FREEBSD_LIBJAIL')
|
||||
self.libs.append('-ljail')
|
||||
|
||||
if uwsgi_os == 'Linux':
|
||||
if self.get('embed_config'):
|
||||
|
||||
+2
-2
@@ -378,9 +378,9 @@ class harakiri(object):
|
||||
def __init__(self, seconds):
|
||||
self.s = seconds
|
||||
|
||||
def real_call(self, *args):
|
||||
def real_call(self, *args, **kwargs):
|
||||
uwsgi.set_user_harakiri(self.s)
|
||||
r = self.f(*args)
|
||||
r = self.f(*args, **kwargs)
|
||||
uwsgi.set_user_harakiri(0)
|
||||
return r
|
||||
|
||||
|
||||
Reference in New Issue
Block a user