Compare commits

..
44 Commits
Author SHA1 Message Date
roberto@quantal64 5ae1c6fbd1 uWSGI 1.3 2012-09-30 09:23:53 +02:00
roberto@quantal64 51b9b5d070 added cppcheck option, improved multicast 2012-09-29 09:16:09 +02:00
roberto@quantal64 dafe3bb12c fixed rack.input with buffered arg 2012-09-28 16:21:37 +02:00
roberto@mercury 973e508af7 reports details on memory allocation error, and bypass broken rack middlewares 2012-09-28 12:37:11 +02:00
roberto@mercury 8e31bb612e allows building the rack plugin without async support 2012-09-28 06:16:55 +02:00
roberto@longshot f920ac0fb0 use SSL_CTX_use_certificate_chain_file instead of SSL_CTX_use_certificate_file 2012-09-27 19:39:14 +02:00
roberto@longshot ae1b5afd7d reoved last libstrophe reference 2012-09-27 18:21:14 +02:00
roberto@quantal64 1f2bae130e added alarm_xmpp plugin 2012-09-27 17:45:42 +02:00
roberto@quantal64 4417e55862 completed http support for alarm_curl 2012-09-27 08:01:06 +02:00
roberto@quantal64 74a84bdd3a added support for mail subject in alarm_curl plugin 2012-09-26 19:55:58 +02:00
roberto@quantal64 b764252e7f applied verbose bind errors 2012-09-26 18:42:48 +02:00
roberto@quantal64 2fd71be9d9 allows building without alarms 2012-09-26 07:19:01 +02:00
roberto@quantal64 d65f873e77 sadly Rack::BodyProxy is still badly broken on 1.9 2012-09-26 07:10:13 +02:00
roberto@quantal64 1427c9ce1c added alarm_curl plugin 2012-09-24 08:36:04 +02:00
roberto@quantal64 c3de9320d7 pass alarm to stdin in cmd mode 2012-09-23 17:19:56 +02:00
roberto@quantal64 674151e485 added alarm subsystem 2012-09-23 16:25:40 +02:00
roberto@quantal64 9c042ffc1c Added tag 1.3-rc4 for changeset aeea5a5d2e8b 2012-09-22 09:48:11 +02:00
roberto@quantal64 c5dc74b021 uWSGI 1.3-rc4 2012-09-22 09:45:08 +02:00
roberto@quantal64 97137488f9 improved emperor mongodb tyrant mode 2012-09-22 09:38:15 +02:00
roberto@quantal64 8cff01a1c7 report imperial monitor in emperor statistics 2012-09-22 09:21:37 +02:00
roberto@quantal64 3c8452313e added emperor_mongodb plugin 2012-09-22 09:04:47 +02:00
roberto@quantal64 322b130fc9 refactored imperial monitors api 2012-09-22 08:58:17 +02:00
roberto@quantal64 6c001c2fda fixed usage of inlining 2012-09-22 07:57:42 +02:00
roberto@quantal64 5d4050817d added --dlopen 2012-09-22 05:52:28 +02:00
roberto@quantal64 0a1147a4f6 added --rb-patch-rack-bodyproxy for older ruby/rack versions 2012-09-21 11:02:29 +02:00
roberto@quantal64 f92cb0e6a2 fixed rack compilation 2012-09-21 09:51:36 +02:00
roberto@quantal64 8b79c76261 refactored daemonize2 2012-09-20 18:08:49 +02:00
roberto@quantal64 0015b51262 fixed POST-handling reports 2012-09-20 17:49:30 +02:00
roberto@quantal64 b1dc8cd9c6 improved async cores detection 2012-09-20 17:41:13 +02:00
roberto@quantal64 3269e2d288 added support for dependancies in plugins 2012-09-20 17:16:30 +02:00
roberto@quantal64 71a9747d96 applied latest carbon patches from Łukasz Mierzwa 2012-09-20 16:43:20 +02:00
roberto@quantal64 455d041ce4 fixed http router parser 2012-09-20 16:36:08 +02:00
roberto@arch 88205f8dd1 added mongodblog plugin 2012-09-19 15:15:03 +02:00
roberto@centos6 7d9dadddf6 support for loading file for elf sections 2012-09-18 00:42:53 +02:00
roberto@centos6 57e78dd76f implemented rack.input each 2012-09-17 16:26:44 +02:00
roberto@centos6 7d0d2b33f4 improved rack.input disk buffering (second part) 2012-09-17 15:51:31 +02:00
roberto@quantal64 03c739102d reimplementing rack.input without IO wrapper 2012-09-17 13:43:43 +02:00
roberto@quantal64 392bb8d7b1 allows building with python3 and without embedded module 2012-09-17 07:41:11 +02:00
roberto@quantal64 505b35be29 do not try to remove sockets in abstract namespace 2012-09-17 06:47:07 +02:00
roberto@quantal64 fdb002ad9b added %0 - %9 magic vars for splitting paths 2012-09-17 06:33:52 +02:00
roberto@quantal64 557c46373f improved %c 2012-09-15 16:15:47 +02:00
roberto@quantal64 3cde8be505 allows building without embedded and multiple interpreters 2012-09-15 12:14:12 +02:00
roberto@quantal64 c2cf1f3a62 fixed threading + lazy 2012-09-14 15:52:23 +02:00
roberto@quantal64 956cb1f13c Added tag 1.3-rc3 for changeset 883b946db903 2012-09-13 18:47:08 +02:00
53 changed files with 2150 additions and 726 deletions
+2
View File
@@ -53,3 +53,5 @@ e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
+16 -1
View File
@@ -10,12 +10,27 @@
- merged routers codebase (fastrouter, http, rawrouter)
- https support in the http router
- config report at the end of uWSGI build process
- support for keepalive in the http router
- improved subscription system (multicast and unix socket)
- custom options
- graceful reloads on shared sockets
- configurable log-master buffer size
- extreme-optimizations for the stats subsystem
- redislog and mongodblog plugins
- added python logger
- mongodb and postgres imperial monitors
- implemented psgix.logger and psgix.cleanup
- full rack spec compliance
- preliminary ipv6 support
- gevent graceful reloads
- support for multiple loggers and logformat
- lazy-apps to load apps after fork() but without changing reloading subsystem
- emperor heartbeat subsystem
- cheaper busyness plugin
- pluggable clock sources
- added router_rewrite and router_http plugins
- external spoolers
- support for section:// and fd:// loaders
- alarm subsystem (with curl and xmpp plugins)
*** april 2012 ***
+3
View File
@@ -3,3 +3,6 @@ all:
clean:
python uwsgiconfig.py --clean
check:
python uwsgiconfig.py --check
+2 -1
View File
@@ -18,6 +18,7 @@ async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
@@ -29,7 +30,7 @@ plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, router_rewrite, router_http
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http
as_shared_library = false
locking = auto
-30
View File
@@ -1,30 +0,0 @@
[uwsgi]
xml = true
ini = true
snmp = true
erlang = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
proxy = true
minterpreters = true
async = true
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rack
[python]
paste = true
web3 = true
-29
View File
@@ -1,29 +0,0 @@
[uwsgi]
xml = true
ini = true
yaml = true
snmp = true
erlang = false
spooler = false
embedded = false
udp = true
multicast = false
threading = true
sendfile = true
nagios = true
proxy = true
minterpreters = true
async = true
ugreen = false
http = true
evdis = false
ldap = false
routing = false
stackless = false
debug = false
unbit = false
xml_implementation = libxml2
plugins = rack
bin_name = uwsgi
plugin_dir = .
embedded_plugins =
+1
View File
@@ -17,6 +17,7 @@ async = true
ldap = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
-44
View File
@@ -1,44 +0,0 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+266
View File
@@ -0,0 +1,266 @@
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
// generate a uwsgi signal on alarm
void uwsgi_alarm_init_signal(struct uwsgi_alarm_instance *uai) {
uai->data8 = atoi(uai->arg);
}
void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
uwsgi_route_signal(uai->data8);
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
}
void uwsgi_alarm_func_cmd(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
int pipe[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe)) {
return;
}
uwsgi_socket_nb(pipe[0]);
uwsgi_socket_nb(pipe[1]);
if (write(pipe[1], msg, len) != (ssize_t) len) {
close(pipe[0]);
close(pipe[1]);
return;
}
uwsgi_run_command(uai->data_ptr, pipe, -1);
close(pipe[0]);
close(pipe[1]);
}
// pass the log line to a mule
void uwsgi_alarm_init_mule(struct uwsgi_alarm_instance *uai) {
uai->data32 = atoi(uai->arg);
if (uai->data32 > (uint32_t) uwsgi.mules_cnt) {
uwsgi_log_alarm("] invalid mule_id (%d mules available), fallback to 0\n", uwsgi.mules_cnt);
uai->data32 = 0;
}
}
void uwsgi_alarm_func_mule(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
// skip if mules are not available
if (uwsgi.mules_cnt == 0) return;
int fd = uwsgi.shared->mule_queue_pipe[0];
if (uai->data32 > 0) {
int mule_id = uai->data32-1;
fd = uwsgi.mules[mule_id].queue_pipe[0];
}
mule_send_msg(fd, msg, len);
}
// register a new alarm
void uwsgi_register_alarm(char *name, void (*init)(struct uwsgi_alarm_instance *), void (*func)(struct uwsgi_alarm_instance *, char *, size_t)) {
struct uwsgi_alarm *old_ua=NULL,*ua = uwsgi.alarms;
while(ua) {
// skip already initialized alarms
if (!strcmp(ua->name, name)) {
return;
}
old_ua = ua;
ua = ua->next;
}
ua = uwsgi_calloc(sizeof(struct uwsgi_alarm));
ua->name = name;
ua->init = init;
ua->func = func;
if (old_ua) {
old_ua->next = ua;
}
else {
uwsgi.alarms = ua;
}
}
// register embedded alarms
void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
struct uwsgi_alarm *ua = uwsgi.alarms;
while(ua) {
if (!strcmp(ua->name, plugin)) {
break;
}
ua = ua->next;
}
if (!ua) return -1;
struct uwsgi_alarm_instance *old_uai = NULL, *uai = uwsgi.alarm_instances;
while(uai) {
old_uai = uai;
uai = uai->next;
}
uai = uwsgi_calloc(sizeof(struct uwsgi_alarm_instance));
uai->name = name;
uai->alarm = ua;
uai->arg = arg;
uai->last_msg = uwsgi_malloc(uwsgi.log_master_bufsize);
if (old_uai) {
old_uai->next = uai;
}
else {
uwsgi.alarm_instances = uai;
}
ua->init(uai);
return 0;
}
// get an alarm instance by its name
static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
struct uwsgi_alarm_instance *uai = uwsgi.alarm_instances;
while(uai) {
if (!strcmp(name, uai->name)) {
return uai;
}
uai = uai->next;
}
return NULL;
}
static int uwsgi_alarm_log_add(char *alarms, char *regexp) {
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
while(ual) {
old_ual = ual;
ual = ual->next;
}
ual = uwsgi_calloc(sizeof(struct uwsgi_alarm_log));
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
return -1;
}
if (old_ual) {
old_ual->next = ual;
}
else {
uwsgi.alarm_logs = ual;
}
// map instances to the log
char *list = uwsgi_str(alarms);
char *p = strtok(list, ",");
while(p) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) return -1;
struct uwsgi_alarm_ll *old_uall=NULL,*uall = ual->alarms;
while(uall) {
old_uall = uall;
uall = uall->next;
}
uall = uwsgi_calloc(sizeof(struct uwsgi_alarm_ll));
uall->alarm = uai;
if (old_uall) {
old_uall->next = uall;
}
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
return 0;
}
// initialize alarms, instances and log regexps
void uwsgi_alarms_init() {
// first of all, create instance of alarms
struct uwsgi_string_list *usl = uwsgi.alarm_list;
while(usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *plugin = space+1;
char *colon = strchr(plugin, ':');
if (!colon) {
uwsgi_log("invalid alarm syntax: %s\n", usl->value);
exit(1);
}
*colon = 0;
char *arg = colon+1;
// here the alarm is mapped to a name and initialized
if (uwsgi_alarm_add(line, plugin, arg)) {
uwsgi_log("invalid alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
// then map log-alarm
usl = uwsgi.alarm_logs_list;
while(usl) {
char *line = uwsgi_str(usl->value);
char *space = strchr(line, ' ');
if (!space) {
uwsgi_log("invalid log-alarm syntax: %s\n", usl->value);
exit(1);
}
*space = 0;
char *regexp = space+1;
// here the log-alarm is created
if (uwsgi_alarm_log_add(line, regexp)) {
uwsgi_log("invalid log-alarm: %s\n", usl->value);
exit(1);
}
usl = usl->next;
}
}
// check if a log should raise an alarm
void uwsgi_alarm_log_check(char *msg, size_t len) {
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12)) return;
struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
while(ual) {
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
uwsgi_alarm_log_run(ual, msg, len);
}
ual = ual->next;
}
}
// call the alarm func
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
time_t now = uwsgi_now();
// avoid alarm storming/loop if last message is the same
if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) {
if (now - uai->last_run < uwsgi.alarm_freq) return;
}
uai->alarm->func(uai, msg, len);
uai->last_run = uwsgi_now();
memcpy(uai->last_msg, msg, len);
uai->last_msg_size = len;
}
// call the alarms mapped to a log line
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
struct uwsgi_alarm_ll *uall = ual->alarms;
while(uall) {
uwsgi_alarm_run(uall->alarm, msg, len);
uall = uall->next;
}
}
+3 -4
View File
@@ -3,7 +3,6 @@
extern struct uwsgi_server uwsgi;
void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
@@ -64,6 +63,7 @@ void uwsgi_init_cache() {
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
int i;
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
@@ -102,7 +102,7 @@ uint32_t djb33x_hash(char *key, int keylen) {
}
inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
@@ -243,7 +243,6 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
struct uwsgi_cache_item *uci, *ucii;
int ret = -1;
int slot;
if (!keylen || !vallen) return -1;
@@ -283,7 +282,7 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
uci->keysize = keylen;
ret = 0;
// now put the value in the 16bit hashtable
slot = uci->djbhash % 0xffff;
int slot = uci->djbhash % 0xffff;
// reset values
uci->prev = 0;
uci->next = 0;
+37 -1
View File
@@ -498,7 +498,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
if (uwsgi.emperor_tyrant) {
if (uid == 0 || gid == 0) {
uwsgi_log("[emperor-tyrant] invalid permissions for file %s\n", name);
uwsgi_log("[emperor-tyrant] invalid permissions for vassal %s\n", name);
return;
}
}
@@ -1208,6 +1208,9 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
goto end0;
if (uwsgi_stats_keyval_comma(us, "monitor", c_ui->scanner->arg))
goto end0;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) c_ui->respawns))
goto end0;
@@ -1338,3 +1341,36 @@ void uwsgi_check_emperor() {
}
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
struct uwsgi_instance *ui_current = emperor_get(name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (uid != ui_current->uid || gid != ui_current->gid) {
uwsgi_log("[emperor-tyrant] !!! permissions of vassal %s changed. stopping the instance... !!!\n", name);
emperor_stop(ui_current);
return;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one)
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = strlen(config);
// always respawn (no need for amqp-style rules)
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
emperor_add(ues, name, ts, uwsgi_str(config), strlen((const char *)config), uid, gid);
}
}
+2 -5
View File
@@ -104,7 +104,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
port_event_t *pe;
if (timeout >= 0) {
ts.tv_sec = timeout;
@@ -123,8 +122,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
return 0;
}
pe = (port_event_t *) events;
return nget;
}
@@ -926,10 +923,10 @@ struct uwsgi_timer *event_queue_ack_timer(int id) {
}
#endif
inline int event_queue_read() {
int event_queue_read() {
return UWSGI_EVENT_IN;
}
inline int event_queue_write() {
int event_queue_write() {
return UWSGI_EVENT_OUT;
}
+37
View File
@@ -74,6 +74,15 @@ void uwsgi_init_default() {
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
#endif
#ifdef UWSGI_ALARM
uwsgi.alarm_freq = 3;
#endif
#ifdef UWSGI_MULTICAST
uwsgi.multicast_ttl = 1;
#endif
}
void uwsgi_setup_reload() {
@@ -252,3 +261,31 @@ void uwsgi_setup_workers() {
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", total_memory, total_memory / 1024, uwsgi.cores*uwsgi.numproc);
}
pid_t uwsgi_daemonize2() {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize2);
}
else {
if (!uwsgi.is_a_reload) {
uwsgi_log("*** daemonizing uWSGI ***\n");
daemonize(uwsgi.daemonize2);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize2);
}
}
uwsgi.mypid = getpid();
uwsgi.workers[0].pid = uwsgi.mypid;
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
return uwsgi.mypid;
}
+8
View File
@@ -265,6 +265,9 @@ int uwsgi_master_log(void) {
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
if (rlen > 0) {
#ifdef UWSGI_ALARM
uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
#endif
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
while(url) {
@@ -644,6 +647,11 @@ int master_loop(char **argv, char **environ) {
uwsgi.threaded_logger = 0;
}
}
#ifdef UWSGI_ALARM
// initialize the alarm subsystem
uwsgi_alarms_init();
#endif
}
if (uwsgi.cache_max_items > 0 && !uwsgi.cache_no_expire) {
+31 -1
View File
@@ -2,6 +2,27 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_ELF
static void uwsgi_plugin_parse_section(char *filename) {
size_t s_len = 0;
char *buf = uwsgi_elf_section(filename, "uwsgi", &s_len);
if (buf) {
char *p = strtok(buf, "\n");
while(p) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
uwsgi_load_plugin(-1, equal+1, NULL);
}
}
p = strtok(NULL, "\n");
}
free(buf);
}
}
#endif
static int plugin_already_loaded(const char *plugin) {
int i;
@@ -79,6 +100,9 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// step 1: check for absolute plugin (stop if it fails)
if (strchr(plugin_name, '/')) {
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_name);
#endif
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
if (!has_option)
@@ -95,6 +119,9 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
if (plugin_handle) {
plugin_abs_path = plugin_filename;
@@ -109,6 +136,9 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
// last step: search in compile-time plugin_dir
if (!plugin_handle) {
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
#ifdef UWSGI_ELF
uwsgi_plugin_parse_section(plugin_filename);
#endif
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
plugin_abs_path = plugin_filename;
//free(plugin_filename);
@@ -117,7 +147,7 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
success:
if (!plugin_handle) {
if (!has_option)
uwsgi_log( "%s\n", dlerror());
uwsgi_log( "!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
+225 -216
View File
@@ -4,13 +4,13 @@ extern struct uwsgi_server uwsgi;
int uwsgi_signal_handler(uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
struct uwsgi_signal_entry *use = NULL;
use = &uwsgi.shared->signal_table[sig];
if (!uwsgi.p[use->modifier1]->signal_handler) {
return -1;
}
}
// check for COW
if (uwsgi.master_process) {
@@ -34,52 +34,52 @@ int uwsgi_signal_handler(uint8_t sig) {
}
}
// set harakiri here (if required and if i am a worker)
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].sig = 1;
uwsgi.workers[uwsgi.mywid].signum = sig;
uwsgi.workers[uwsgi.mywid].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
}
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 1;
uwsgi.mules[uwsgi.muleid-1].signum = sig;
uwsgi.mules[uwsgi.muleid-1].signals++;
if(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
uwsgi.mules[uwsgi.muleid - 1].sig = 1;
uwsgi.mules[uwsgi.muleid - 1].signum = sig;
uwsgi.mules[uwsgi.muleid - 1].signals++;
if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
#endif
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
if (uwsgi.mywid > 0) {
uwsgi.workers[uwsgi.mywid].sig = 0;
if(uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
uwsgi.workers[uwsgi.mywid].sig = 0;
if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
set_harakiri(0);
}
}
}
else if (uwsgi.muleid > 0) {
uwsgi.mules[uwsgi.muleid-1].sig = 0;
if(uwsgi.mules[uwsgi.muleid-1].harakiri > 0) {
set_mule_harakiri(0);
uwsgi.mules[uwsgi.muleid - 1].sig = 0;
if (uwsgi.mules[uwsgi.muleid - 1].harakiri > 0) {
set_mule_harakiri(0);
}
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
return ret;
@@ -97,7 +97,8 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (strlen(receiver) > 63) return -1;
if (strlen(receiver) > 63)
return -1;
uwsgi_lock(uwsgi.signal_table_lock);
@@ -109,7 +110,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
return -1;
}
strncpy(use->receiver, receiver, strlen(receiver)+1);
strncpy(use->receiver, receiver, strlen(receiver) + 1);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
@@ -129,7 +130,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
if (strlen(filename) > (0xff-1)) {
if (strlen(filename) > (0xff - 1)) {
uwsgi_log("uwsgi_add_file_monitor: invalid filename length\n");
return -1;
}
@@ -140,9 +141,9 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
// fill the fmon table, the master will use it to add items to the event queue
memcpy(ushared->files_monitored[ushared->files_monitored_cnt].filename, filename, strlen(filename));
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].registered = 0;
ushared->files_monitored[ushared->files_monitored_cnt].sig = sig;
ushared->files_monitored_cnt++;
}
else {
@@ -157,31 +158,31 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func)(int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
struct uwsgi_probe *uwsgi_up = *up, *old_up;
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while(uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
return uwsgi_up;
}
@@ -189,10 +190,10 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while(up) {
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
@@ -201,15 +202,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024-1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
@@ -225,15 +226,15 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
@@ -267,107 +268,109 @@ void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while(uc->next) {
uc = uc->next;
old_uc = uc;
}
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value+i;
if (sscanf(value, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = value + i;
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
return 0;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process) return -1;
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.rb_timer_table_lock);
uwsgi_lock(uwsgi.rb_timer_table_lock);
if (ushared->rb_timers_cnt < 64) {
if (ushared->rb_timers_cnt < 64) {
// fill the timer table, the master will use it to add items to the event queue
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
ushared->rb_timers_cnt++;
}
else {
uwsgi_log("you can register max 64 rb_timers !!!\n");
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return -1;
}
// fill the timer table, the master will use it to add items to the event queue
ushared->rb_timers[ushared->rb_timers_cnt].value = secs;
ushared->rb_timers[ushared->rb_timers_cnt].registered = 0;
ushared->rb_timers[ushared->rb_timers_cnt].iterations = iterations;
ushared->rb_timers[ushared->rb_timers_cnt].iterations_done = 0;
ushared->rb_timers[ushared->rb_timers_cnt].sig = sig;
ushared->rb_timers_cnt++;
}
else {
uwsgi_log("you can register max 64 rb_timers !!!\n");
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.rb_timer_table_lock);
uwsgi_unlock(uwsgi.rb_timer_table_lock);
return 0;
return 0;
}
void create_signal_pipe(int *sigpipe) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sigpipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(sigpipe[0]);
uwsgi_socket_nb(sigpipe[1]);
if (uwsgi.signal_bufsize) {
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[0], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_SNDBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
if (setsockopt(sigpipe[1], SOL_SOCKET, SO_RCVBUF, &uwsgi.signal_bufsize, sizeof(int))) {
uwsgi_error("setsockopt()");
}
}
}
@@ -379,9 +382,10 @@ int uwsgi_remote_signal_send(char *addr, uint8_t sig) {
uh.modifier1 = 110;
uh.pktsize = 0;
uh.modifier2 = sig;
int fd = uwsgi_connect(addr, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return -1;
if (fd < 0)
return -1;
if (write(fd, (char *) &uh, 4) != 4) {
uwsgi_error("uwsgi_remote_signal_send()");
@@ -403,16 +407,16 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
if (write(fd, &sig, 1) != 1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
}
uwsgi_log("*** SIGNAL QUEUE IS FULL: buffer size %d bytes (you can tune it with --signal-bufsize) ***\n", so_bufsize);
}
else {
uwsgi_error("uwsgi_signal_send()");
}
return -1;
}
}
return 0;
}
@@ -430,7 +434,7 @@ void uwsgi_route_signal(uint8_t sig) {
}
// send to all workers
else if (!strcmp(use->receiver, "workers")) {
for(i=1;i<=uwsgi.numproc;i++) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
@@ -438,13 +442,13 @@ void uwsgi_route_signal(uint8_t sig) {
}
// route to specific worker
else if (!strncmp(use->receiver, "worker", 6)) {
i = atoi(use->receiver+6);
i = atoi(use->receiver + 6);
if (i > uwsgi.numproc) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
if (uwsgi_signal_send(uwsgi.workers[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
uwsgi_log("could not deliver signal %d to worker %d\n", sig, i);
}
}
// route to subscribed
else if (!strcmp(use->receiver, "subscribed")) {
@@ -454,54 +458,54 @@ void uwsgi_route_signal(uint8_t sig) {
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
uwsgi_log("could not deliver signal %d to the spooler\n", sig);
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for(i=0;i<uwsgi.mules_cnt;i++) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i+1);
}
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i + 1);
}
}
}
else if (!strncmp(use->receiver, "mule", 4)) {
i = atoi(use->receiver+4);
i = atoi(use->receiver + 4);
if (i > uwsgi.mules_cnt) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else if (i == 0) {
if (uwsgi_signal_send(ushared->mule_signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
uwsgi_log("could not deliver signal %d to a mule\n", sig);
}
}
else {
if (uwsgi_signal_send(uwsgi.mules[i-1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
if (uwsgi_signal_send(uwsgi.mules[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to mule %d\n", sig, i);
}
}
}
else if (!strncmp(use->receiver, "farm_", 5)) {
char *name = use->receiver+5;
char *name = use->receiver + 5;
struct uwsgi_farm *uf = get_farm_by_name(name);
if (!uf) {
uwsgi_log("unknown farm: %s\n", name);
return;
}
if (uwsgi_signal_send(uf->signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, uf->id, uf->name);
}
}
else if (!strncmp(use->receiver, "farm", 4)) {
i = atoi(use->receiver+4);
i = atoi(use->receiver + 4);
if (i > uwsgi.farms_cnt || i <= 0) {
uwsgi_log("invalid signal target: %s\n", use->receiver);
}
else {
if (uwsgi_signal_send(uwsgi.farms[i-1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i-1].name);
}
if (uwsgi_signal_send(uwsgi.farms[i - 1].signal_pipe[0], sig)) {
uwsgi_log("could not deliver signal %d to farm %d (%s)\n", sig, i, uwsgi.farms[i - 1].name);
}
}
}
@@ -512,51 +516,56 @@ void uwsgi_route_signal(uint8_t sig) {
}
uint8_t uwsgi_signal_wait(int signum) {
int uwsgi_signal_wait(int signum) {
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int ret;
struct pollfd pfd[2];
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
int received_signal = -1;
int ret;
struct pollfd pfd[2];
if (signum > -1) {
wait_for_specific_signal = 1;
}
wait_for_specific_signal = 1;
}
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
pfd[0].fd = uwsgi.signal_socket;
pfd[0].events = POLLIN;
pfd[1].fd = uwsgi.my_signal_socket;
pfd[1].events = POLLIN;
cycle:
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
ret = poll(pfd, 2, -1);
if (ret > 0) {
if (pfd[0].revents == POLLIN) {
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
received_signal = uwsgi_signal;
}
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void) uwsgi_signal_handler(uwsgi_signal);
if (wait_for_specific_signal) {
if (signum != uwsgi_signal)
goto cycle;
}
}
received_signal = uwsgi_signal;
}
if (pfd[1].revents == POLLIN) {
if (read(uwsgi.my_signal_socket, &received_signal, 1) != 1) {
uwsgi_error("read()");
}
else {
(void)uwsgi_signal_handler(received_signal);
if (wait_for_specific_signal) {
if (received_signal != uwsgi_signal) goto cycle;
}
}
}
}
}
return received_signal;
return received_signal;
}
void uwsgi_receive_signal(int fd, char *name, int id) {
@@ -565,27 +574,27 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
ssize_t ret = read(fd, &uwsgi_signal, 1);
if (ret == 0) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
else if (ret > 0) {
}
else if (ret > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
}
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
}
}
return;
destroy:
// better to kill the whole worker...
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
end_me(0);
}
+10 -1
View File
@@ -174,6 +174,7 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
struct sockaddr_in uws_addr;
char *udp_port;
int bcast = 1;
int reuse = 1;
#ifdef UWSGI_MULTICAST
struct ip_mreq mc;
@@ -231,6 +232,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
return -1;
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
}
#ifdef UWSGI_MULTICAST
if (multicast) {
// if multicast is enabled remember to bind to INADDR_ANY
@@ -265,6 +270,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
uwsgi_error("setsockopt()");
}
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_TTL, &uwsgi.multicast_ttl, sizeof(uwsgi.multicast_ttl))) {
uwsgi_error("setsockopt()");
}
}
#endif
@@ -595,7 +604,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
if (errno == EADDRINUSE) {
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
uwsgi_log("probably another instance of uWSGI is running on the same address (%s).\n", socket_name);
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
+162 -6
View File
@@ -1193,7 +1193,7 @@ char *uwsgi_str_contains(char *str, int slen, char what) {
}
// fast compare 2 sized strings
inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
if (slen != dlen)
return 1;
@@ -1203,7 +1203,7 @@ inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
}
// fast sized check of initial part of a string
inline int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
if (slen < dlen)
return -1;
@@ -1212,7 +1212,7 @@ inline int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
}
// unsized check
inline int uwsgi_startswith(char *src, char *what, int wlen) {
int uwsgi_startswith(char *src, char *what, int wlen) {
int i;
@@ -2149,18 +2149,20 @@ int uwsgi_waitfd_event(int fd, int timeout, int event) {
return ret;
}
inline void *uwsgi_malloc(size_t size) {
void *uwsgi_malloc(size_t size) {
char *ptr = malloc(size);
if (ptr == NULL) {
uwsgi_error("malloc()");
uwsgi_log("!!! tried memory allocation of %llu bytes !!!\n", (unsigned long long) size);
uwsgi_backtrace(uwsgi.backtrace_depth);
exit(1);
}
return ptr;
}
inline void *uwsgi_calloc(size_t size) {
void *uwsgi_calloc(size_t size) {
char *ptr = uwsgi_malloc(size);
memset(ptr, 0, size);
@@ -2531,6 +2533,18 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
}
#ifdef UWSGI_ELF
else if (!strncmp("section://", url, 10)) {
size_t s_len = 0;
buffer = uwsgi_elf_section(uwsgi.binary_path, url+10, &s_len);
if (!buffer) {
uwsgi_log("unable to find section %s in %s\n", url+10, uwsgi.binary_path);
exit(1);
}
*size = s_len;
if (add_zero) *size += 1;
}
#endif
// fallback to file
else {
fd = open(url, O_RDONLY);
@@ -4373,7 +4387,7 @@ SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ci
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0) {
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
uwsgi_log("unable to assign ssl certificate %s\n", crt);
exit(1);
}
@@ -4738,3 +4752,145 @@ void uwsgi_set_cpu_affinity() {
}
}
#ifdef UWSGI_ELF
#if defined(__linux__)
#include <elf.h>
#endif
char *uwsgi_elf_section(char *filename, char *s, size_t *len) {
struct stat st;
char *output = NULL;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
return NULL;
}
if (fstat(fd, &st)) {
uwsgi_error("stat()");
close(fd);
return NULL;
}
if (st.st_size < EI_NIDENT) {
uwsgi_log("invalid elf file: %s\n", filename);
close(fd);
return NULL;
}
char *addr = mmap(NULL, st.st_size , PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
uwsgi_error("mmap()");
close(fd);
return NULL;
}
if (addr[0] != ELFMAG0) goto clear;
if (addr[1] != ELFMAG1) goto clear;
if (addr[2] != ELFMAG2) goto clear;
if (addr[3] != ELFMAG3) goto clear;
if (addr[4] == ELFCLASS32) {
// elf header
Elf32_Ehdr *elfh = (Elf32_Ehdr *) addr;
// first section
Elf32_Shdr *sections = ((Elf32_Shdr *) (addr + elfh->e_shoff));
// number of sections
int ns = elfh->e_shnum;
// the names table
Elf32_Shdr *table = &sections[elfh->e_shstrndx];
// string table session pointer
char *names = addr + table->sh_offset;
Elf32_Shdr *ss = NULL; int i;
for(i=0;i<ns;i++) {
char *name = names + sections[i].sh_name;
if (!strcmp(name, s)) {
ss = &sections[i];
break;
}
}
if (ss) {
*len = ss->sh_size;
output = uwsgi_concat2n(addr + ss->sh_offset, ss->sh_size, "", 0);
}
}
else if (addr[4] == ELFCLASS64) {
// elf header
Elf64_Ehdr *elfh = (Elf64_Ehdr *) addr;
// first section
Elf64_Shdr *sections = ((Elf64_Shdr *) (addr + elfh->e_shoff));
// number of sections
int ns = elfh->e_shnum;
// the names table
Elf64_Shdr *table = &sections[elfh->e_shstrndx];
// string table session pointer
char *names = addr + table->sh_offset;
Elf64_Shdr *ss = NULL; int i;
for(i=0;i<ns;i++) {
char *name = names + sections[i].sh_name;
if (!strcmp(name, s)) {
ss = &sections[i];
break;
}
}
if (ss) {
*len = ss->sh_size;
output = uwsgi_concat2n(addr + ss->sh_offset, ss->sh_size, "", 0);
}
}
clear:
close(fd);
munmap(addr, st.st_size);
return output;
}
#endif
static void *uwsgi_thread_run(void *arg) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) arg;
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
ut->queue = event_queue_init();
event_queue_add_fd_read(ut->queue, ut->pipe[1]);
ut->func(ut);
return NULL;
}
struct uwsgi_thread *uwsgi_thread_new(void (*func)(struct uwsgi_thread *)) {
struct uwsgi_thread *ut = uwsgi_malloc(sizeof(struct uwsgi_thread));
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ut->pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ut->pipe)) {
#endif
free(ut);
return NULL;
}
uwsgi_socket_nb(ut->pipe[0]);
uwsgi_socket_nb(ut->pipe[1]);
ut->func = func;
if (pthread_create(&ut->tid, NULL, uwsgi_thread_run, ut)) {
uwsgi_error("pthread_create()");
goto error;
}
return ut;
error:
close(ut->pipe[0]);
close(ut->pipe[1]);
free(ut);
return NULL;
}
+76 -59
View File
@@ -302,6 +302,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"stats-server", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
#ifdef UWSGI_MULTICAST
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
{"multicast-ttl", required_argument, 0, "set multicast ttl", uwsgi_opt_set_int, &uwsgi.multicast_ttl, 0},
{"cluster", required_argument, 0, "join specified uWSGI cluster", uwsgi_opt_set_str, &uwsgi.cluster, UWSGI_OPT_MASTER},
{"cluster-nodes", required_argument, 0, "get nodes list from the specified cluster", uwsgi_opt_true, &uwsgi.cluster_nodes, UWSGI_OPT_MASTER | UWSGI_OPT_CLUSTER},
{"cluster-reload", required_argument, 0, "send a reload message to the cluster", uwsgi_opt_cluster_reload, NULL, UWSGI_OPT_IMMEDIATE},
@@ -352,6 +353,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
#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},
#endif
#ifdef UWSGI_ALARM
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
#endif
#ifdef UWSGI_ZEROMQ
{"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
#endif
@@ -480,6 +488,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"plugins-list", no_argument, 0, "list enabled plugins", uwsgi_opt_true, &uwsgi.plugins_list, 0},
{"plugin-list", no_argument, 0, "list enabled plugins", uwsgi_opt_true, &uwsgi.plugins_list, 0},
{"autoload", no_argument, 0, "try to automatically load plugins when unknown options are found", uwsgi_opt_true, &uwsgi.autoload, UWSGI_OPT_IMMEDIATE},
{"dlopen", required_argument, 0, "blindly load a shared library", uwsgi_opt_load_dl, NULL, UWSGI_OPT_IMMEDIATE},
{"allowed-modifiers", required_argument, 0, "comma separated list of allowed modifiers", uwsgi_opt_set_str, &uwsgi.allowed_modifiers, 0},
{"remap-modifier", required_argument, 0, "remap request modifier from one id to another", uwsgi_opt_set_str, &uwsgi.remap_modifier, 0},
@@ -660,8 +669,21 @@ void config_magic_table_fill(char *filename, char **magic_table) {
#endif
*tmp = 0;
}
if (uwsgi_get_last_char(magic_table['d'], '/'))
magic_table['c'] = uwsgi_get_last_char(magic_table['d'], '/') + 1;
if (uwsgi_get_last_char(magic_table['d'], '/')) {
magic_table['c'] = uwsgi_str(uwsgi_get_last_char(magic_table['d'], '/') + 1);
if (magic_table['c'][strlen(magic_table['c']) - 1] == '/') {
magic_table['c'][strlen(magic_table['c']) - 1] = 0;
}
}
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, "/");
}
if (tmp)
*tmp = '/';
@@ -1203,7 +1225,7 @@ static void vacuum(void) {
}
}
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_UNIX) {
if (uwsgi_sock->family == AF_UNIX && uwsgi_sock->name[0] != '@') {
if (unlink(uwsgi_sock->name)) {
uwsgi_error("unlink()");
}
@@ -1515,6 +1537,18 @@ static void clocks_list(void) {
uwsgi_log("--- end of clocks list ---\n\n");
}
#ifdef UWSGI_ALARM
static void alarms_list(void) {
struct uwsgi_alarm *alarms = uwsgi.alarms;
uwsgi_log("\n*** uWSGI loaded alarms ***\n");
while(alarms) {
uwsgi_log("%s\n", alarms->name);
alarms = alarms->next;
}
uwsgi_log("--- end of alarms list ---\n\n");
}
#endif
static time_t uwsgi_unix_seconds() {
return time(NULL);
}
@@ -1522,7 +1556,7 @@ static time_t uwsgi_unix_seconds() {
static uint64_t uwsgi_unix_microseconds() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000) + tv.tv_usec;
return ((uint64_t)tv.tv_sec * 1000000) + tv.tv_usec;
}
static struct uwsgi_clock uwsgi_unix_clock = {
@@ -1729,6 +1763,13 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi_register_imperial_monitor("dir", uwsgi_imperial_monitor_directory_init, uwsgi_imperial_monitor_directory);
uwsgi_register_imperial_monitor("glob", uwsgi_imperial_monitor_glob_init, uwsgi_imperial_monitor_glob);
#ifdef UWSGI_ALARM
// register embedded alarms
uwsgi_register_embedded_alarms();
#endif
/* uWSGI IS CONFIGURED !!! */
if (uwsgi.dump_options) {
@@ -1768,6 +1809,11 @@ int main(int argc, char *argv[], char *envp[]) {
if (uwsgi.clock_list)
clocks_list();
#ifdef UWSGI_ALARM
if (uwsgi.alarms_list)
alarms_list();
#endif
// set the clock
if (uwsgi.requested_clock)
uwsgi_set_clock(uwsgi.requested_clock);
@@ -2026,34 +2072,6 @@ int uwsgi_start(void *v_argv) {
pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
}
#ifdef UWSGI_ASYNC
// TODO rewrite to use uwsgi.max_fd
if (uwsgi.async > 1) {
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
if ((unsigned long) uwsgi.rl.rlim_cur < (unsigned long) uwsgi.async) {
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.rl.rlim_cur);
if (uwsgi.rl.rlim_cur < uwsgi.rl.rlim_max && (unsigned long) uwsgi.rl.rlim_max > (unsigned long) uwsgi.async) {
unsigned long tmp_nofile = (unsigned long) uwsgi.rl.rlim_cur;
uwsgi.rl.rlim_cur = uwsgi.async;
if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_log("max open files limit reset to %lu\n", (unsigned long) uwsgi.rl.rlim_cur);
uwsgi.async = uwsgi.rl.rlim_cur;
}
else {
uwsgi.async = (int) tmp_nofile;
}
}
else {
uwsgi.async = uwsgi.rl.rlim_cur;
}
uwsgi_log("- async cores set to %d -\n", uwsgi.async);
}
}
}
#endif
if (uwsgi.requested_max_fd) {
uwsgi.rl.rlim_cur = uwsgi.requested_max_fd;
uwsgi.rl.rlim_max = uwsgi.requested_max_fd;
@@ -2064,11 +2082,24 @@ int uwsgi_start(void *v_argv) {
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi.max_fd = uwsgi.rl.rlim_cur;
uwsgi_log_initial("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
uwsgi_log_initial("detected max file descriptor number: %lu\n", (unsigned long) uwsgi.max_fd);
}
if (uwsgi.async > 1) {
uwsgi_log("async fd table size: %d\n", uwsgi.max_fd);
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
uwsgi.rl.rlim_cur = uwsgi.async;
uwsgi.rl.rlim_max = uwsgi.async;
if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi_log("max open files limit raised to %lu\n", (unsigned long) uwsgi.rl.rlim_cur);
uwsgi.async = uwsgi.rl.rlim_cur;
uwsgi.max_fd = uwsgi.rl.rlim_cur;
}
else {
uwsgi.async = (int) uwsgi.max_fd;
}
}
uwsgi_log("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
uwsgi.async_waiting_fd_table = malloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
if (!uwsgi.async_waiting_fd_table) {
uwsgi_error("malloc()");
@@ -2386,30 +2417,7 @@ next:
if (uwsgi.daemonize2) {
if (uwsgi.has_emperor) {
logto(uwsgi.daemonize2);
}
else {
if (!uwsgi.is_a_reload) {
uwsgi_log("*** daemonizing uWSGI ***\n");
daemonize(uwsgi.daemonize2);
}
else if (uwsgi.log_reopen) {
logto(uwsgi.daemonize2);
}
}
uwsgi.mypid = getpid();
masterpid = uwsgi.mypid;
uwsgi.workers[0].pid = masterpid;
if (uwsgi.pidfile && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile);
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
masterpid = uwsgi_daemonize2();
}
if (uwsgi.no_server) {
@@ -2421,9 +2429,12 @@ next:
if (!uwsgi.master_process && uwsgi.numproc == 0) {
exit(0);
}
#ifdef UWSGI_MINTERPRETERS
if (!uwsgi.single_interpreter && uwsgi.numproc > 0) {
uwsgi_log("*** uWSGI is running in multiple interpreter mode ***\n");
}
#endif
// check for request plugins, and eventually print a warning
int rp_available = 0;
@@ -2917,7 +2928,7 @@ void uwsgi_stdin_sendto(char *socket_name, uint8_t modifier1, uint8_t modifier2)
#endif
ptr += rlen;
delta -= rlen;
if (delta <= 0)
if (delta == 0)
break;
rlen = read(0, ptr, delta);
}
@@ -3320,6 +3331,12 @@ void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
exit(0);
}
void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
if (!dlopen(value, RTLD_NOW | RTLD_GLOBAL)) {
uwsgi_log( "%s\n", dlerror());
}
}
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
char *p = strtok(uwsgi_concat2(value, ""), ",");
+203
View File
@@ -0,0 +1,203 @@
#include "../../uwsgi.h"
#include <curl/curl.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_alarm_curl_config {
int first;
char *arg;
char *subject;
char *to;
};
struct uwsgi_alarm_curl_opt {
char *name;
CURLoption option;
void (*func)(CURL *, CURLoption, char *, struct uwsgi_alarm_curl_config*);
};
static void uwsgi_alarm_curl_to(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
uacc->to = arg;
struct curl_slist *list = NULL;
char *items = uwsgi_str(arg);
char *ctx = NULL;
char *p = strtok_r(items, ",", &ctx);
while(p) {
list = curl_slist_append(list, p);
p = strtok_r(NULL, ",", &ctx);
}
curl_easy_setopt(curl, option, list);
}
static void uwsgi_alarm_curl_ssl(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
curl_easy_setopt(curl, option, (long)CURLUSESSL_ALL);
}
static void uwsgi_alarm_curl_int(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
curl_easy_setopt(curl, option, atoi(arg));
}
static void uwsgi_alarm_curl_set_subject(CURL *curl, CURLoption option, char *arg, struct uwsgi_alarm_curl_config *uacc) {
uacc->subject = arg;
}
static struct uwsgi_alarm_curl_opt uaco[] = {
{"url", CURLOPT_URL, NULL},
{"mail_to", CURLOPT_MAIL_RCPT, uwsgi_alarm_curl_to },
{"mail_from", CURLOPT_MAIL_FROM, NULL},
{"subject", 0, uwsgi_alarm_curl_set_subject},
{"ssl", CURLOPT_USE_SSL, uwsgi_alarm_curl_ssl},
{"auth_user", CURLOPT_USERNAME, NULL},
{"auth_pass", CURLOPT_PASSWORD, NULL},
{"method", CURLOPT_CUSTOMREQUEST, NULL},
{"timeout", CURLOPT_TIMEOUT, uwsgi_alarm_curl_int},
{"conn_timeout", CURLOPT_CONNECTTIMEOUT, uwsgi_alarm_curl_int},
{NULL, 0, NULL},
};
static void uwsgi_alarm_curl_setopt(CURL *curl, char *opt, struct uwsgi_alarm_curl_config *uacc) {
struct uwsgi_alarm_curl_opt *o = uaco;
char *equal = strchr(opt,'=');
if (!equal) {
if (!uacc->first) {
curl_easy_setopt(curl, CURLOPT_URL, opt);
uacc->first = 1;
}
return;
}
uacc->first = 1;
*equal = 0;
while(o->name) {
if (!strcmp(o->name, opt)) {
if (o->func) {
o->func(curl, o->option, equal+1, uacc);
}
else {
curl_easy_setopt(curl, o->option, equal+1);
}
goto end;
}
o++;
}
end:
*equal = '=';
}
static size_t uwsgi_alarm_curl_read_callback(void *ptr, size_t size, size_t nmemb, void *userp) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) userp;
size_t full_size = size * nmemb;
size_t remains = ut->len - ut->pos;
struct uwsgi_alarm_curl_config *uacc = ut->data;
if (remains == 0) return 0;
if (ut->custom0 == 0) {
size_t newline = 0;
size_t required = 1;
char *addr = ptr;
if (uacc->to) required += 4 + strlen(uacc->to) + 1;
if (uacc->subject) required += 9 + strlen(uacc->subject) + 1;
if (required > full_size) goto skip;
if (uacc->to) {
memcpy(addr, "To: ", 4); addr+=4;
memcpy(addr, uacc->to, strlen(uacc->to)); addr += strlen(uacc->to);
*addr ++= '\n';
newline = 1;
}
if (uacc->subject) {
memcpy(addr, "Subject: ", 9); addr+=9;
memcpy(addr, uacc->subject, strlen(uacc->subject)); addr += strlen(uacc->subject);
*addr ++= '\n';
newline = 1;
}
skip:
if (newline > 0) {
*addr = '\n';
}
ut->custom0 = 1;
return required;
}
if (full_size < remains) {
remains = full_size;
}
memcpy(ptr, ut->buf + ut->pos, remains);
ut->pos += remains;
return remains;
}
static void uwsgi_alarm_curl_loop(struct uwsgi_thread *ut) {
int interesting_fd;
ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);
CURL *curl = curl_easy_init();
// ARGH !!!
if (!curl) return;
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, uwsgi_alarm_curl_read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, ut);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
struct uwsgi_alarm_curl_config *uacc = (struct uwsgi_alarm_curl_config *) ut->data;
char *opts = uwsgi_str(uacc->arg);
// fill curl options
char *ctx = NULL;
char *p = strtok_r(opts, ";", &ctx);
while(p) {
uwsgi_alarm_curl_setopt(curl, uwsgi_str(p), uacc);
p = strtok_r(NULL, ";", &ctx);
}
for(;;) {
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret <= 0) continue;
if (interesting_fd != ut->pipe[1]) continue;
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
if (rlen <= 0) continue;
ut->pos = 0;
ut->len = (size_t) rlen;
ut->custom0 = 0;
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
}
}
static void uwsgi_alarm_curl_init(struct uwsgi_alarm_instance *uai) {
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_curl_loop);
if (!ut) return;
uai->data_ptr = ut;
struct uwsgi_alarm_curl_config *uacc = uwsgi_calloc(sizeof(struct uwsgi_alarm_curl_config));
uacc->arg = uai->arg;
ut->data = uacc;
}
// pipe the message into the thread;
static void uwsgi_alarm_curl_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
ut->rlen = write(ut->pipe[0], msg, len);
}
static void uwsgi_alarm_curl_load(void) {
uwsgi_register_alarm("curl", uwsgi_alarm_curl_init, uwsgi_alarm_curl_func);
}
struct uwsgi_plugin alarm_curl_plugin = {
.name = "alarm_curl",
.on_load = uwsgi_alarm_curl_load,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='alarm_curl'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lcurl']
GCC_LIST = ['alarm_curl_plugin']
+26
View File
@@ -0,0 +1,26 @@
#include "../../uwsgi.h"
void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *);
static void uwsgi_alarm_xmpp_init(struct uwsgi_alarm_instance *uai) {
struct uwsgi_thread *ut = uwsgi_thread_new(uwsgi_alarm_xmpp_loop);
if (!ut) return;
uai->data_ptr = ut;
ut->data = uai->arg;
}
// pipe the message into the thread;
static void uwsgi_alarm_xmpp_func(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
struct uwsgi_thread *ut = (struct uwsgi_thread *) uai->data_ptr;
ut->rlen = write(ut->pipe[0], msg, len);
}
static void uwsgi_alarm_xmpp_load(void) {
uwsgi_register_alarm("xmpp", uwsgi_alarm_xmpp_init, uwsgi_alarm_xmpp_func);
}
struct uwsgi_plugin alarm_xmpp_plugin = {
.name = "alarm_xmpp",
.on_load = uwsgi_alarm_xmpp_load,
};
+139
View File
@@ -0,0 +1,139 @@
#include "../../uwsgi.h"
#include <gloox/client.h>
#include <gloox/message.h>
#include <gloox/connectionlistener.h>
#include <gloox/connectiontcpclient.h>
extern struct uwsgi_server uwsgi;
using namespace gloox;
class Jabbo : public ConnectionListener{
public:
Jabbo(struct uwsgi_thread *ut, char *jab_username, char *jab_password, char *dests) {
u_thread = ut;
dest = NULL;
char *ctx = NULL;
char *p = strtok_r(dests, ",", &ctx);
while(p) {
uwsgi_string_new_list(&dest, p);
p = strtok_r(NULL, ",", &ctx);
}
JID jid(jab_username);
client = new Client( jid, jab_password );
client->registerConnectionListener(this);
u_connected = 0;
client->connect(false);
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
}
~Jabbo() {
delete client;
}
void send(char *buf, size_t len) {
struct uwsgi_string_list *usl = dest;
while(usl) {
JID jid(usl->value);
std::string text(buf, len);
Message msg(Message::Chat, jid, text);
client->send(msg);
usl = usl->next;
}
}
virtual void onConnect() {
event_queue_add_fd_read(u_thread->queue, fd);
u_connected = 1;
}
virtual void onDisconnect(ConnectionError e) {
if (fd >= 0) {
event_queue_del_fd(u_thread->queue, fd, event_queue_read());
}
sleep(1);
u_connected = 0;
client->connect(false);
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
}
virtual bool onTLSConnect(const CertInfo& info) {
return true;
}
Client* client;
int fd;
int u_connected;
struct uwsgi_thread *u_thread;
struct uwsgi_string_list *dest;
};
extern "C" void uwsgi_alarm_xmpp_loop(struct uwsgi_thread *ut) {
int interesting_fd;
ut->buf = (char *) uwsgi_malloc(uwsgi.log_master_bufsize);
char *xmpp_username = (char *) "";
char *xmpp_password = (char *) "";
char *xmpp_dests = (char *) "";
// 0 -> username, 1 -> password, 2-> dest list
int opt_state = 0;
// fill xmpp options
char *ctx = NULL;
char *opts = uwsgi_str((char *)ut->data);
char *p = strtok_r(opts, ";", &ctx);
while(p) {
switch(opt_state) {
case 0:
xmpp_username = p;
opt_state = 1;
break;
case 1:
xmpp_password = p;
opt_state = 2;
break;
case 2:
xmpp_dests = p;
opt_state = 3;
break;
default:
break;
}
p = strtok_r(NULL, ";", &ctx);
}
Jabbo j(ut, xmpp_username, xmpp_password, xmpp_dests);
int timeout = 0;
for(;;) {
if (j.u_connected) {
timeout = -1;
}
else {
timeout = 0;
}
int ret = event_queue_wait(ut->queue, timeout, &interesting_fd);
if (ret < 0) continue;
if (ret > 0 && interesting_fd == ut->pipe[1]) {
ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
if (rlen <= 0) continue;
if (j.u_connected) {
j.send(ut->buf, rlen);
}
}
else if (ret == 0 || (ret > 0 && j.fd > -1 && interesting_fd == j.fd)) {
j.client->recv();
}
}
}
+6
View File
@@ -0,0 +1,6 @@
NAME='alarm_xmpp'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lgloox']
GCC_LIST = ['alarm_xmpp_plugin', 'gloox.cc']
+216 -145
View File
@@ -2,22 +2,37 @@
extern struct uwsgi_server uwsgi;
struct carbon_server_list {
char *value; // server address
int healthy;
int errors;
struct carbon_server_list *next;
};
struct uwsgi_carbon {
struct uwsgi_string_list *servers;
struct carbon_server_list *servers_data;
int freq;
int timeout;
char *id;
int no_workers;
unsigned long long *last_busyness_values;
unsigned long long *current_busyness_values;
int need_retry;
time_t last_update;
time_t next_retry;
int max_retries;
int retry_delay;
} u_carbon;
struct uwsgi_option carbon_options[] = {
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout in seconds (default 3)", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency in seconds (default 60)", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
{"carbon-max-retry", required_argument, 0, "set maximum number of retries in case of connection errors (default 1)", uwsgi_opt_set_int, &u_carbon.max_retries, 0},
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -31,12 +46,23 @@ void carbon_post_init() {
if (!u_carbon.servers) return;
while(usl) {
uwsgi_log("added carbon server %s\n", usl->value);
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
u_server->value = usl->value;
u_server->healthy = 1;
u_server->errors = 0;
if (u_carbon.servers_data) {
u_server->next = u_carbon.servers_data;
}
u_carbon.servers_data = u_server;
uwsgi_log("[carbon] added server %s\n", usl->value);
usl = usl->next;
}
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
@@ -53,153 +79,198 @@ void carbon_post_init() {
u_carbon.current_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
// set next update to now()+retry_delay, this way we will have first flush just after start
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is",
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
}
int carbon_write(int *fd, char *fmt,...) {
va_list ap;
va_start(ap, fmt);
char ptr[4096];
int rlen;
rlen = vsnprintf(ptr, 4096, fmt, ap);
if (rlen < 1) return 0;
if (write(*fd, ptr, rlen) <= 0) {
uwsgi_error("write()");
return 0;
}
return 1;
}
void carbon_push_stats(int retry_cycle) {
struct carbon_server_list *usl = u_carbon.servers_data;
int i;
int fd;
int wok;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
}
u_carbon.need_retry = 0;
while(usl) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
goto nxt;
if (retry_cycle && usl->healthy == 0)
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
if (!retry_cycle) {
usl->healthy = 1;
usl->errors = 0;
}
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (1)\n",
usl->value, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
usl->healthy = 0;
usl->errors++;
goto nxt;
}
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long active_workers = 0; // number of workers used to calculate total avg_rt
unsigned long long total_busyness = 0;
unsigned long long total_avg_busyness = 0;
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
wok = carbon_write(&fd, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
for(i=1;i<=uwsgi.numproc;i++) {
total_tx += uwsgi.workers[i].tx;
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
worker_busyness = 0;
}
else {
// global average response time is calculated from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
active_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
// calculate worker busyness
worker_busyness = ((u_carbon.current_busyness_values[i-1]*100) / (u_carbon.freq*1000000));
if (worker_busyness > 100) worker_busyness = 100;
total_busyness += worker_busyness;
// only running workers are counted in total memory stats
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
total_harakiri += uwsgi.workers[i].harakiri_count/2;
}
//skip per worker metrics when disabled
if (u_carbon.no_workers) continue;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].vsz_size, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) worker_busyness, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count/2, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_vsz, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
if (active_workers > 0) {
total_avg_busyness = total_busyness / active_workers;
if (total_avg_busyness > 100) total_avg_busyness = 100;
} else {
total_avg_busyness = 0;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_avg_busyness, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.active_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) active_workers, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
if (uwsgi.cheaper) {
wok = carbon_write(&fd, "uwsgi.%s.%s.cheaped_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) uwsgi.numproc - active_workers, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
usl->healthy = 1;
usl->errors = 0;
clear:
close(fd);
nxt:
usl = usl->next;
}
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
if (u_carbon.need_retry)
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
u_carbon.last_update -= u_carbon.timeout;
}
void carbon_master_cycle() {
static time_t last_update = 0;
char ptr[4096];
int rlen, i;
int fd;
struct uwsgi_string_list *usl = u_carbon.servers;
if (!u_carbon.servers) return;
if (!u_carbon.servers) return ;
if (last_update == 0) last_update = uwsgi_now();
// update
if (uwsgi.current_time - last_update >= u_carbon.freq || uwsgi.cleaning) {
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
}
while(usl) {
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (fd < 0) goto nxt;
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long active_workers = 0; // number of workers used to calculate total avg_rt
unsigned long long total_busyness = 0;
unsigned long long total_avg_busyness = 0;
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
for(i=1;i<=uwsgi.numproc;i++) {
total_tx += uwsgi.workers[i].tx;
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
worker_busyness = 0;
}
else {
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
active_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
// calculate worker busyness
worker_busyness = ((u_carbon.current_busyness_values[i-1]*100) / (u_carbon.freq*1000000));
if (worker_busyness > 100) worker_busyness = 100;
total_busyness += worker_busyness;
// only running workers are counted in total memory stats
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
total_harakiri += uwsgi.workers[i].harakiri_count/2;
}
//skip per worker metrics when disabled
if (u_carbon.no_workers) continue;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) worker_busyness, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].harakiri_count/2, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (active_workers > 0) {
total_avg_busyness = total_busyness / active_workers;
if (total_avg_busyness > 100) total_avg_busyness = 100;
} else {
total_avg_busyness = 0;
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_avg_busyness, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.active_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) active_workers, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (uwsgi.cheaper) {
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.cheaped_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.numproc - active_workers, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_harakiri, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
clear:
close(fd);
nxt:
usl = usl->next;
}
last_update = uwsgi_now();
if (uwsgi.current_time - u_carbon.last_update >= u_carbon.freq || uwsgi.cleaning) {
// update
u_carbon.need_retry = 0;
carbon_push_stats(0);
} else if (u_carbon.need_retry && (uwsgi.current_time >= u_carbon.next_retry)) {
// retry failed servers
carbon_push_stats(1);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ time_t uwsgi_monotonic_seconds() {
uint64_t uwsgi_monotonic_microseconds() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
return ((uint64_t)ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
}
+1 -1
View File
@@ -11,7 +11,7 @@ time_t uwsgi_realtime_seconds() {
uint64_t uwsgi_realtime_microseconds() {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec/1000);
}
+2
View File
@@ -89,7 +89,9 @@ struct corerouter_session {
int instance_fd;
int instance_stopped;
int status;
uint8_t h_pos;
uint16_t pos;
struct uwsgi_gateway_socket *ugs;
+121
View File
@@ -0,0 +1,121 @@
#include "../../uwsgi.h"
#include "client/dbclient.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_instance *ui;
// one for each mongodb imperial monitor
struct uwsgi_emperor_mongodb_state {
char *address;
char *collection;
char *json;
};
extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
try {
// requested fields
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 );
mongo::BSONObj q = mongo::fromjson(uems->json);
// the connection object (will be automatically destroyed at each cycle)
mongo::DBClientConnection c;
// set the socket timeout
c.setSoTimeout(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
// connect
c.connect(uems->address);
// run the query
std::auto_ptr<mongo::DBClientCursor> cursor = c.query(uems->collection, q, 0, 0, &p);
while( cursor->more() ) {
mongo::BSONObj p = cursor->next();
// checking for an empty string is not required, but we reduce the load
// in case of badly strctured databases
const char *name = p.getStringField("name");
if (strlen(name) == 0) continue;
const char *config = p.getStringField("config");
time_t vassal_ts = 0;
// ts must be a Date object !!!
mongo::BSONElement ts = p.getField("ts");
if (ts.type() == mongo::Date) {
vassal_ts = ts.date();
}
uid_t vassal_uid = 0;
gid_t vassal_gid = 0;
// check for tyrant mode
if (uwsgi.emperor_tyrant) {
int tmp_uid = p.getIntField("uid");
int tmp_gid = p.getIntField("gid");
if (tmp_uid < 0) tmp_uid = 0;
if (tmp_gid < 0) tmp_gid = 0;
vassal_uid = tmp_uid;
vassal_gid = tmp_gid;
}
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
}
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
if (c_ui->scanner == ues) {
mongo::BSONObjBuilder b;
b.appendElements(q);
b.append("name", c_ui->name);
mongo::BSONObj q2 = b.obj();
cursor = c.query(uems->collection, q2, 0, 0, &p);
#ifdef UWSGI_DEBUG
uwsgi_log("JSON: %s\n", q2.toString().c_str());
#endif
if (!cursor->more()) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
}
catch ( mongo::DBException &e ) {
uwsgi_log("[emperor-mongodb] ERROR(%s/%s): %s\n", uems->address, uems->collection, e.what());
}
}
// setup a new mongodb imperial monitor
extern "C" void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *ues) {
// allocate a new state
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
size_t arg_len = strlen(ues->arg);
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
// parse args/ set defaults
uems->address = (char *) "127.0.0.1:27017";
uems->collection = (char *) "uwsgi.emperor.vassals";
uems->json = (char *) "";
if (arg_len > 10) {
uems->address = uwsgi_str(ues->arg+10);
char *comma = strchr(uems->address, ',');
if (!comma) goto done;
*comma = 0;
uems->collection = comma+1;
comma = strchr(uems->collection, ',');
if (!comma) goto done;
*comma = 0;
uems->json = comma+1;
}
done:
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
}
+14
View File
@@ -0,0 +1,14 @@
#include "../../uwsgi.h"
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
void emperor_mongodb_init(void) {
uwsgi_register_imperial_monitor("mongodb", uwsgi_imperial_monitor_mongodb_init, uwsgi_imperial_monitor_mongodb);
}
struct uwsgi_plugin emperor_mongodb_plugin = {
.name = "emperor_mongodb",
.on_load = emperor_mongodb_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='emperor_mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
+1 -35
View File
@@ -7,7 +7,6 @@ extern struct uwsgi_instance *ui;
void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *);
void emperor_pg_init(void);
void emperor_pg_do(struct uwsgi_emperor_scanner *, char *, char *, time_t, uid_t, gid_t);
void emperor_pg_init(void) {
uwsgi_register_imperial_monitor("pg", uwsgi_imperial_monitor_pg_init, uwsgi_imperial_monitor_pg);
@@ -17,39 +16,6 @@ void uwsgi_imperial_monitor_pg_init(struct uwsgi_emperor_scanner *ues) {
uwsgi_log("[emperor] enabled emperor PostgreSQL monitor\n");
}
void emperor_pg_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
struct uwsgi_instance *ui_current = emperor_get(name);
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (uid != ui_current->uid || gid != ui_current->gid) {
uwsgi_log("[emperor-tyrant] !!! permissions of vassal %s changed. stopping the instance... !!!\n", name);
emperor_stop(ui_current);
return;
}
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one)
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = strlen(config);
// always respawn (no need for amqp-style rules)
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
emperor_add(ues, name, ts, uwsgi_str(config), strlen(config), uid, gid);
}
}
void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
PGconn *conn = NULL;
@@ -102,7 +68,7 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
}
emperor_pg_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
}
}
+2
View File
@@ -4,4 +4,6 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
REQUIRES = ['corerouter']
GCC_LIST = ['fastrouter', 'fr_events']
+2 -2
View File
@@ -15,7 +15,7 @@ VALUE uwsgi_fiber_request() {
return Qnil;
}
inline static void fiber_schedule_to_req() {
static inline void fiber_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -33,7 +33,7 @@ inline static void fiber_schedule_to_req() {
}
inline static void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline void fiber_schedule_to_main(struct wsgi_request *wsgi_req) {
rb_fiber_yield(0, NULL);
uwsgi.wsgi_req = wsgi_req;
+10 -7
View File
@@ -1,27 +1,30 @@
import os
NAME='fiber'
try:
RUBYPATH = os.environ['UWSGICONFIG_RUBYPATH']
except:
RUBYPATH = 'ruby'
NAME='fiber'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
rbconfig = 'RbConfig'
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['rubyhdrdir']\"" % rbconfig).read().rstrip()
if includedir == 'nil':
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + includedir)
else:
CFLAGS.append('-I' + includedir)
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['archdir']\"").read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['arch']\"").read().rstrip()
archdir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['archdir']\"" % rbconfig).read().rstrip()
arch = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['arch']\"" % rbconfig).read().rstrip()
CFLAGS.append('-I' + archdir)
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = []
LIBS = []
+2 -2
View File
@@ -28,7 +28,7 @@ PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
inline static void greenlet_schedule_to_req() {
static inline void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -45,7 +45,7 @@ inline static void greenlet_schedule_to_req() {
}
inline static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
PyGreenlet_Switch(ugl.main, NULL, NULL);
uwsgi.wsgi_req = wsgi_req;
+5 -5
View File
@@ -506,7 +506,8 @@ void uwsgi_http_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_se
goto choose_node;
}
len = cs->recv(&uhttp.cr, cs, hs->buffer + cs->h_pos, UMAX16 - cs->h_pos);
len = cs->recv(&uhttp.cr, cs, hs->buffer + cs->pos, UMAX16 - cs->pos);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ucr->queue, cs->fd);
#endif
@@ -517,10 +518,9 @@ void uwsgi_http_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_se
break;
}
cs->h_pos += len;
cs->pos += len;
for (j = 0; j < len; j++) {
//uwsgi_log("%d %d %d\n", j, *cs->ptr, cs->rnrn);
if (*hs->ptr == '\r' && (hs->rnrn == 0 || hs->rnrn == 2)) {
hs->rnrn++;
}
@@ -531,6 +531,7 @@ void uwsgi_http_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_se
hs->rnrn = 2;
}
else if (*hs->ptr == '\n' && hs->rnrn == 3) {
hs->ptr++;
cs->post_remains = len - (j + 1);
hs->iov_len = http_parse(hs);
@@ -597,7 +598,6 @@ void uwsgi_http_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_se
}
cs->pass_fd = is_unix(cs->instance_address, cs->instance_address_len);
cs->instance_fd = uwsgi_connectn(cs->instance_address, cs->instance_address_len, 0, 1);
@@ -620,6 +620,7 @@ void uwsgi_http_switch_events(struct uwsgi_corerouter *ucr, struct corerouter_se
else {
hs->rnrn = 0;
}
hs->ptr++;
}
@@ -767,7 +768,6 @@ To have a reliable implementation, we need to reset a bunch of values
hs->ptr = hs->buffer;
hs->rnrn = 0;
cs->pos = 0;
cs->h_pos = 0;
hs->received_body = 0;
cs->post_cl = 0;
cs->instance_fd = -1;
+2
View File
@@ -4,4 +4,6 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
REQUIRES = ['corerouter']
GCC_LIST = ['http']
+164
View File
@@ -0,0 +1,164 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
struct uwsgi_mongodb_header {
int32_t len;
int32_t request_id;
int32_t response_id;
int32_t opcode;
};
struct uwsgi_mongodb_state {
int fd;
char *address;
int32_t base_len;
struct uwsgi_mongodb_header header;
int32_t flags;
char *collection;
int32_t bson_base_len;
int32_t bson_len;
int64_t ts;
int32_t bson_node_len;
char *bson_node;
int32_t bson_msg_len;
struct iovec iovec[13];
};
ssize_t uwsgi_mongodb_logger(struct uwsgi_logger *ul, char *message, size_t len) {
struct uwsgi_mongodb_state *ums = NULL;
if (!ul->configured) {
ul->data = uwsgi_calloc(sizeof(struct uwsgi_mongodb_state));
ums = (struct uwsgi_mongodb_state *) ul->data;
// full default
if (ul->arg == NULL) {
ums->address = uwsgi_str("127.0.0.1:27017");
ums->collection = "uwsgi.logs";
ums->bson_node = uwsgi.hostname;
ums->bson_node_len = uwsgi.hostname_len;
goto done;
}
ums->address = uwsgi_str(ul->arg);
char *collection = strchr(ums->address, ',');
// default to uwsgi.logs
if (!collection) {
ums->collection = "uwsgi.logs";
ums->bson_node = uwsgi.hostname;
ums->bson_node_len = uwsgi.hostname_len;
goto done;
}
*collection = 0;
ums->collection = collection+1;
char *node = strchr(ums->collection, ',');
// default to hostname
if (!node) {
ums->bson_node = uwsgi.hostname;
ums->bson_node_len = uwsgi.hostname_len;
goto done;
}
*node = 0;
ums->bson_node = node+1;
ums->bson_node_len = strlen(ums->bson_node)+1;
done:
ums->fd = -1;
// header
ums->iovec[0].iov_base = &ums->header;
ums->iovec[0].iov_len = sizeof(struct uwsgi_mongodb_header);
// OPCODE INSERT
ums->header.opcode = 2002;
// flags
ums->iovec[1].iov_base = &ums->flags;
ums->iovec[1].iov_len = sizeof(int32_t);
// collection name
ums->iovec[2].iov_base = ums->collection;
ums->iovec[2].iov_len = strlen(ums->collection)+1;
// BSON len
ums->iovec[3].iov_base = &ums->bson_len;
ums->iovec[3].iov_len = sizeof(int32_t);
// BSON node
ums->iovec[4].iov_base = "\x02node\0";
ums->iovec[4].iov_len = 6;
ums->iovec[5].iov_base = &ums->bson_node_len;
ums->iovec[5].iov_len = sizeof(int32_t);
ums->iovec[6].iov_base = ums->bson_node;
ums->iovec[6].iov_len = ums->bson_node_len;
// BSON timestamp (ts)
ums->iovec[7].iov_base = "\x09ts\0";
ums->iovec[7].iov_len = 4;
ums->iovec[8].iov_base = &ums->ts;
ums->iovec[8].iov_len = sizeof(int64_t);
// BSON msg
ums->iovec[9].iov_base = "\2msg\0";
ums->iovec[9].iov_len = 5;
ums->iovec[10].iov_base = &ums->bson_msg_len;
ums->iovec[10].iov_len = sizeof(int32_t);
// iov 11 is reset at each cycle
// ...
// BSON end (msg_zero + bson_zero);
ums->iovec[12].iov_base = "\0\0";
ums->iovec[12].iov_len = 2;
ums->bson_base_len = ums->iovec[3].iov_len + ums->iovec[4].iov_len + ums->iovec[5].iov_len + ums->iovec[6].iov_len +
ums->iovec[7].iov_len + ums->iovec[8].iov_len + ums->iovec[9].iov_len + ums->iovec[10].iov_len +
ums->iovec[12].iov_len;
ums->base_len = ums->iovec[0].iov_len + ums->iovec[1].iov_len + ums->iovec[2].iov_len + ums->bson_base_len;
ul->configured = 1;
}
ums = (struct uwsgi_mongodb_state *) ul->data;
if (ums->fd == -1) {
ums->fd = uwsgi_connect(ums->address, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
}
if (ums->fd == -1) return -1;
// fix the packet
ums->bson_msg_len = len+1;
ums->bson_len = ums->bson_base_len + len;
ums->header.len = ums->base_len + len;
ums->header.request_id++;
// get milliseconds time
ums->ts = uwsgi_micros()/1000;
ums->iovec[11].iov_base = message;
ums->iovec[11].iov_len = len;
ssize_t ret = writev(ums->fd, ums->iovec, 13);
if (ret <= 0) {
close(ums->fd);
ums->fd = -1;
return -1;
}
return ret;
}
void uwsgi_mongodblog_register() {
uwsgi_register_logger("mongodblog", uwsgi_mongodb_logger);
}
struct uwsgi_plugin mongodblog_plugin = {
.name = "mongodblog",
.on_load = uwsgi_mongodblog_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='mongodblog'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['mongodblog_plugin']
+1 -1
View File
@@ -208,7 +208,7 @@ static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
{
uint read_bytes = 0;
size_t len;
ssize_t len;
int fd = -1;
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
+4
View File
@@ -483,7 +483,9 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
PyObject *tmp_callable;
PyObject *applications;
#ifdef UWSGI_EMBEDDED
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
#endif
char *module = (char *) arg1;
@@ -506,8 +508,10 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
return NULL;
}
#ifdef UWSGI_EMBEDDED
applications = PyDict_GetItemString(uwsgi_dict, "applications");
if (applications && PyDict_Check(applications)) return applications;
#endif
applications = PyDict_GetItemString(wsgi_dict, "applications");
if (applications && PyDict_Check(applications)) return applications;
+14 -3
View File
@@ -282,6 +282,7 @@ realstuff:
if (uwsgi.has_threads)
PyGILState_Ensure();
// no need to worry about freeing memory
#ifdef UWSGI_EMBEDDED
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
@@ -289,6 +290,7 @@ realstuff:
python_call(ae, PyTuple_New(0), 0, NULL);
}
}
#endif
// this part is a 1:1 copy of mod_wsgi 3.x
// it is required to fix some atexit bug with python 3
@@ -528,8 +530,6 @@ next:
#ifdef UWSGI_EMBEDDED
PyDoc_STRVAR(uwsgi_py_doc, "uWSGI api module.");
#endif
#ifdef PYTHREE
static PyModuleDef uwsgi_module3 = {
@@ -544,7 +544,6 @@ PyObject *init_uwsgi3(void) {
}
#endif
#ifdef UWSGI_EMBEDDED
void init_uwsgi_embedded_module() {
PyObject *new_uwsgi_module, *zero;
int i;
@@ -1050,6 +1049,11 @@ void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
// lazy ?
if (uwsgi.mywid > 0) {
UWSGI_GET_GIL;
}
#ifndef UWSGI_PYPY
// prepare for stack suspend/resume
if (uwsgi.async > 1) {
@@ -1160,6 +1164,7 @@ next:
}
#endif
#ifdef UWSGI_EMBEDDED
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
up.after_req_hook = PyDict_GetItemString(uwsgi_dict, "after_req_hook");
@@ -1169,6 +1174,12 @@ next:
Py_INCREF(up.after_req_hook_args);
}
}
#endif
// lazy ?
if (uwsgi.mywid > 0) {
UWSGI_RELEASE_GIL;
}
}
+6 -1
View File
@@ -10,7 +10,7 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int received_signal;
wsgi_req->signal_received = -1;
@@ -30,6 +30,11 @@ PyObject *py_uwsgi_signal_wait(PyObject * self, PyObject * args) {
received_signal = uwsgi_signal_wait(-1);
}
if (received_signal < 0) {
UWSGI_GET_GIL;
return PyErr_Format(PyExc_SystemError, "error waiting for signal");
}
wsgi_req->signal_received = received_signal;
UWSGI_GET_GIL;
+4 -2
View File
@@ -152,14 +152,14 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
if (uwsgi_waitfd(self->wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) self->wsgi_req->post_cl - remains);
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains + tmp_pos, (unsigned long long) tmp_pos);
}
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
if (rlen <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data: Content-Length %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) self->wsgi_req->post_cl - remains);
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains + tmp_pos, (unsigned long long) tmp_pos);
}
tmp_pos += rlen;
remains -= rlen;
@@ -510,7 +510,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
// this object must be freed/cleared always
#ifdef UWSGI_ASYNC
end:
#endif
if (wsgi_req->async_input) {
Py_DECREF((PyObject *)wsgi_req->async_input);
}
+13 -2
View File
@@ -488,6 +488,7 @@ VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename
}
#ifdef UWSGI_ASYNC
VALUE uwsgi_ruby_wait_fd_read(VALUE *class, VALUE arg1, VALUE arg2) {
Check_Type(arg1, T_FIXNUM);
@@ -522,6 +523,7 @@ VALUE uwsgi_ruby_wait_fd_write(VALUE *class, VALUE arg1, VALUE arg2) {
return Qtrue;
}
#endif
@@ -535,6 +537,7 @@ VALUE uwsgi_ruby_async_connect(VALUE *class, VALUE arg) {
}
#ifdef UWSGI_ASYNC
VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
Check_Type(arg, T_FIXNUM);
@@ -548,6 +551,7 @@ VALUE uwsgi_ruby_async_sleep(VALUE *class, VALUE arg) {
return Qtrue;
}
#endif
VALUE uwsgi_ruby_masterpid(VALUE *class) {
@@ -573,7 +577,7 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
struct wsgi_request *wsgi_req = current_wsgi_req();
int wait_for_specific_signal = 0;
uint8_t uwsgi_signal = 0;
uint8_t received_signal;
int received_signal;
wsgi_req->signal_received = -1;
@@ -590,7 +594,12 @@ VALUE uwsgi_ruby_signal_wait(int argc, VALUE *argv, VALUE *class) {
received_signal = uwsgi_signal_wait(-1);
}
wsgi_req->signal_received = received_signal;
if (received_signal < 0) {
rb_raise(rb_eRuntimeError, "unable to call rpc function");
}
else {
wsgi_req->signal_received = received_signal;
}
return Qnil;
}
@@ -868,9 +877,11 @@ void uwsgi_rack_init_api() {
VALUE rb_uwsgi_embedded = rb_define_module("UWSGI");
uwsgi_rack_api("suspend", uwsgi_ruby_suspend, 0);
uwsgi_rack_api("masterpid", uwsgi_ruby_masterpid, 0);
#ifdef UWSGI_ASYNC
uwsgi_rack_api("async_sleep", uwsgi_ruby_async_sleep, 1);
uwsgi_rack_api("wait_fd_read", uwsgi_ruby_wait_fd_read, 2);
uwsgi_rack_api("wait_fd_write", uwsgi_ruby_wait_fd_write, 2);
#endif
uwsgi_rack_api("async_connect", uwsgi_ruby_async_connect, 1);
uwsgi_rack_api("signal", uwsgi_ruby_signal, -1);
uwsgi_rack_api("register_signal", uwsgi_ruby_register_signal, 3);
+100 -58
View File
@@ -79,6 +79,14 @@ VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
VALUE line;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
char linebuf[4096];
if (wsgi_req->async_post) {
if (fgets(linebuf, 4096, (FILE *) wsgi_req->async_post) == NULL) {
return Qnil;
}
return rb_str_new2(linebuf);
}
// return a line of body
for(i=wsgi_req->buf_pos;i<wsgi_req->post_cl;i++) {
@@ -100,12 +108,18 @@ VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
VALUE rb_uwsgi_io_each(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
if (!rb_block_given_p())
rb_raise(rb_eArgError, "Expected block on rack.input 'each' method");
// yield strings chunks
rb_raise(rb_eRuntimeError, "rack.input::each is not implemented (req %p)\n", wsgi_req);
for(;;) {
VALUE chunk = rb_uwsgi_io_gets(obj, Qnil);
if (chunk == Qnil) {
return Qnil;
}
rb_yield(chunk);
}
// never here
return Qnil;
}
@@ -114,13 +128,65 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
struct wsgi_request *wsgi_req;
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
VALUE chunk;
unsigned int chunk_size;
long chunk_size;
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
/*
When EOF is reached, this method returns nil if length is given and not nil, or "" if length is not given or is nil.
If buffer is given, then the read data will be placed into buffer instead of a newly created String object.
*/
// --- disk buffering ---
if (wsgi_req->async_post) {
// 0 size, read the whole body from the file...
if (RARRAY_LEN(args) == 0) {
char *tmp_chunk = uwsgi_malloc(wsgi_req->post_cl);
size_t rlen = fread(tmp_chunk, 1, wsgi_req->post_cl, (FILE *) wsgi_req->async_post);
if (rlen == 0) {
free(tmp_chunk);
return rb_str_new("", 0);
}
// return a new string
chunk = rb_str_new(tmp_chunk, rlen);
free(tmp_chunk);
return chunk;
}
// size specified
else if (RARRAY_LEN(args) > 0) {
if (RARRAY_PTR(args)[0] == Qnil) {
chunk_size = wsgi_req->post_cl;
}
else {
chunk_size = NUM2LONG(RARRAY_PTR(args)[0]);
// hack to tolerate broken middlewares
if (chunk_size <= 0) {
chunk_size = wsgi_req->post_cl;
}
}
char *tmp_chunk = uwsgi_malloc(chunk_size);
size_t rlen = fread(tmp_chunk, 1, chunk_size, (FILE *) wsgi_req->async_post);
// error, return Qnil
if (rlen == 0) {
free(tmp_chunk);
return Qnil;
}
// push in the specified buffer
if (RARRAY_LEN(args) > 1) {
rb_str_cat(RARRAY_PTR(args)[1], tmp_chunk, rlen);
}
// return a new string
chunk = rb_str_new(tmp_chunk, rlen);
free(tmp_chunk);
return chunk;
}
// never happend...
return Qnil;
}
// --- memory buffering ---
// first check for virtual EOF
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
if (RARRAY_LEN(args) > 0) {
if (RARRAY_PTR(args)[0] == Qnil) {
return rb_str_new("", 0);
@@ -137,14 +203,21 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
return chunk;
}
else if (RARRAY_LEN(args) > 0) {
chunk_size = NUM2UINT(RARRAY_PTR(args)[0]);
if (RARRAY_PTR(args)[0] == Qnil) {
chunk_size = wsgi_req->post_cl;
}
else {
chunk_size = NUM2LONG(RARRAY_PTR(args)[0]);
// hack to tolerate broken middlewares
if (chunk_size <= 0) {
chunk_size = wsgi_req->post_cl;
}
}
if (wsgi_req->buf_pos+chunk_size > wsgi_req->post_cl) {
chunk_size = wsgi_req->post_cl-wsgi_req->buf_pos;
}
if (RARRAY_LEN(args) > 1) {
rb_str_cat(RARRAY_PTR(args)[1], wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
wsgi_req->buf_pos+=chunk_size;
return RARRAY_PTR(args)[1];
}
chunk = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
wsgi_req->buf_pos+=chunk_size;
@@ -163,8 +236,14 @@ VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
return Qnil;
}
wsgi_req->buf_pos = 0;
// buffered to disk ?
if (wsgi_req->async_post) {
rewind((FILE *) wsgi_req->async_post);
}
// or memory ???
else {
wsgi_req->buf_pos = 0;
}
return Qnil;
}
@@ -673,6 +752,11 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
struct http_status_codes *http_sc;
if (!ur.call) {
internal_server_error(wsgi_req, "Ruby application not found");
return -1;
}
/* Standard RACK request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid RACK request. skip.\n");
@@ -748,12 +832,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
VALUE dws_wr = Data_Wrap_Struct(ur.rb_uwsgi_io_class, 0, 0, wsgi_req);
if (wsgi_req->async_post) {
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno((FILE*)wsgi_req->async_post)), rb_str_new("r",1) ));
}
else {
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(ur.rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
}
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(ur.rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
@@ -909,44 +988,6 @@ void uwsgi_rack_resume(struct wsgi_request *wsgi_req) {
uwsgi_log("RESUMING RUBY\n");
}
#ifdef RUBY19
VALUE uwsgi_call_block(VALUE body, VALUE block) {
return rb_funcall(block, rb_intern("call"), 1, body );
}
VALUE uwsgi_rack_patch_body_proxy_each(int argc, VALUE *argv, VALUE self) {
VALUE block = Qnil;
rb_scan_args(argc, argv, "0&", &block);
if(!RTEST(block)) {
rb_raise(rb_eArgError, "a block is required");
return Qnil;
}
VALUE original_body = rb_iv_get(self, "@body");
if (original_body != Qnil) {
return rb_block_call(original_body, rb_intern("each"), 0, 0, uwsgi_call_block, block);
}
return Qnil;
}
VALUE uwsgi_rack_patch_body_proxy(VALUE foo) {
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
VALUE rack_body_proxy = rb_const_get(rack, rb_intern("BodyProxy"));
if (!rb_respond_to(rack_body_proxy, rb_intern("each"))) {
rb_define_method(rack_body_proxy, "each", uwsgi_rack_patch_body_proxy_each, -1);
return Qtrue;
}
return Qnil;
}
#endif
VALUE init_rack_app( VALUE script ) {
int error;
@@ -963,9 +1004,10 @@ VALUE init_rack_app( VALUE script ) {
VALUE rack = rb_const_get(rb_cObject, rb_intern("Rack"));
#ifdef RUBY19
VALUE ret = rb_protect(uwsgi_rack_patch_body_proxy, rack, &error);
if (!error && ret != Qnil) {
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
if (rb_eval_string("module Rack;class BodyProxy;def each(&block);@body.each(&block);end;end;end")) {
if (uwsgi.mywid <= 1) {
uwsgi_log("Rack::BodyProxy successfully patched for ruby 1.9.x\n");
}
}
#endif
+2
View File
@@ -4,4 +4,6 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
REQUIRES = ['corerouter']
GCC_LIST = ['rawrouter', 'rr_events']
+42 -35
View File
@@ -10,7 +10,7 @@ struct uwsgi_redislog_state {
char msgsize[11];
struct iovec iovec[7];
char response[8];
} uredislog;
};
static char *uwsgi_redis_logger_build_command(char *src) {
ssize_t len = 4096;
@@ -53,95 +53,102 @@ static char *uwsgi_redis_logger_build_command(char *src) {
ssize_t uwsgi_redis_logger(struct uwsgi_logger *ul, char *message, size_t len) {
ssize_t ret,ret2;
struct uwsgi_redislog_state *uredislog = NULL;
if (!ul->configured) {
if (!ul->data) {
ul->data = uwsgi_calloc(sizeof(struct uwsgi_redislog_state));
uredislog = (struct uwsgi_redislog_state *) ul->data;
}
if (ul->arg != NULL) {
char *logarg = uwsgi_str(ul->arg);
char *comma1 = strchr(logarg, ',');
if (!comma1) {
uredislog.address = logarg;
uredislog->address = logarg;
goto done;
}
*comma1 = 0;
uredislog.address = logarg;
uredislog->address = logarg;
comma1++;
if (*comma1 == 0) goto done;
char *comma2 = strchr(comma1,',');
if (!comma2) {
uredislog.command = uwsgi_redis_logger_build_command(comma1);
uredislog->command = uwsgi_redis_logger_build_command(comma1);
goto done;
}
*comma2 = 0;
uredislog.command = uwsgi_redis_logger_build_command(comma1);
uredislog->command = uwsgi_redis_logger_build_command(comma1);
comma2++;
if (*comma2 == 0) goto done;
uredislog.prefix = comma2;
uredislog->prefix = comma2;
}
done:
if (!uredislog.address) uredislog.address = uwsgi_str("127.0.0.1:6379");
if (!uredislog.command) uredislog.command = "*3\r\n$7\r\npublish\r\n$5\r\nuwsgi\r\n";
if (!uredislog.prefix) uredislog.prefix = "";
if (!uredislog->address) uredislog->address = uwsgi_str("127.0.0.1:6379");
if (!uredislog->command) uredislog->command = "*3\r\n$7\r\npublish\r\n$5\r\nuwsgi\r\n";
if (!uredislog->prefix) uredislog->prefix = "";
uredislog.fd = -1;
uredislog->fd = -1;
uredislog.iovec[0].iov_base = uredislog.command;
uredislog.iovec[0].iov_len = strlen(uredislog.command);
uredislog.iovec[1].iov_base = "$";
uredislog.iovec[1].iov_len = 1;
uredislog->iovec[0].iov_base = uredislog->command;
uredislog->iovec[0].iov_len = strlen(uredislog->command);
uredislog->iovec[1].iov_base = "$";
uredislog->iovec[1].iov_len = 1;
uredislog.iovec[2].iov_base = uredislog.msgsize;
uredislog->iovec[2].iov_base = uredislog->msgsize;
uredislog.iovec[3].iov_base = "\r\n";
uredislog.iovec[3].iov_len = 2;
uredislog->iovec[3].iov_base = "\r\n";
uredislog->iovec[3].iov_len = 2;
uredislog.iovec[4].iov_base = uredislog.prefix;
uredislog.iovec[4].iov_len = strlen(uredislog.prefix);
uredislog->iovec[4].iov_base = uredislog->prefix;
uredislog->iovec[4].iov_len = strlen(uredislog->prefix);
uredislog.iovec[6].iov_base = "\r\n";
uredislog.iovec[6].iov_len = 2;
uredislog->iovec[6].iov_base = "\r\n";
uredislog->iovec[6].iov_len = 2;
ul->configured = 1;
}
if (uredislog.fd == -1) {
uredislog.fd = uwsgi_connect(uredislog.address, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
uredislog = (struct uwsgi_redislog_state *) ul->data;
if (uredislog->fd == -1) {
uredislog->fd = uwsgi_connect(uredislog->address, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
}
if (uredislog.fd == -1) return -1;
if (uredislog->fd == -1) return -1;
// drop newline
if (message[len-1] == '\n') len--;
uwsgi_num2str2(len + uredislog.iovec[4].iov_len, uredislog.msgsize);
uredislog.iovec[2].iov_len = strlen(uredislog.msgsize);
uwsgi_num2str2(len + uredislog->iovec[4].iov_len, uredislog->msgsize);
uredislog->iovec[2].iov_len = strlen(uredislog->msgsize);
uredislog.iovec[5].iov_base = message;
uredislog.iovec[5].iov_len = len;
uredislog->iovec[5].iov_base = message;
uredislog->iovec[5].iov_len = len;
ret = writev(uredislog.fd, uredislog.iovec, 7);
ret = writev(uredislog->fd, uredislog->iovec, 7);
if (ret <= 0) {
close(uredislog.fd);
uredislog.fd = -1;
close(uredislog->fd);
uredislog->fd = -1;
return -1;
}
again:
// read til a \n is found (ugly but fast)
ret2 = read(uredislog.fd, uredislog.response, 8);
ret2 = read(uredislog->fd, uredislog->response, 8);
if (ret2 <= 0) {
close(uredislog.fd);
uredislog.fd = -1;
close(uredislog->fd);
uredislog->fd = -1;
return -1;
}
if (!memchr(uredislog.response, '\n', ret2)) {
if (!memchr(uredislog->response, '\n', ret2)) {
goto again;
}
+2 -2
View File
@@ -27,7 +27,7 @@ PyObject *py_uwsgi_stackless_request(PyObject * self, PyObject *args) {
PyMethodDef uwsgi_stackless_request_method[] = {{"uwsgi_stackless_request", py_uwsgi_stackless_request, METH_VARARGS, ""}};
inline static void stackless_schedule_to_req() {
static inline static void stackless_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -47,7 +47,7 @@ inline static void stackless_schedule_to_req() {
}
inline static void stackless_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline static void stackless_schedule_to_main(struct wsgi_request *wsgi_req) {
PyStackless_Schedule(Py_None, 1);
uwsgi.wsgi_req = wsgi_req;
+2 -2
View File
@@ -32,7 +32,7 @@ void u_green_request() {
uwsgi.wsgi_req->suspended = 0;
}
inline static void u_green_schedule_to_req() {
static inline void u_green_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
@@ -58,7 +58,7 @@ inline static void u_green_schedule_to_req() {
}
inline static void u_green_schedule_to_main(struct wsgi_request *wsgi_req) {
static inline void u_green_schedule_to_main(struct wsgi_request *wsgi_req) {
if (uwsgi.p[wsgi_req->uh.modifier1]->suspend) {
uwsgi.p[wsgi_req->uh.modifier1]->suspend(wsgi_req);
+104 -22
View File
@@ -15,13 +15,16 @@ extern "C" {
#define uwsgi_log_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log(x);
#define uwsgi_error_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
#ifdef UWSGI_ALARM
#define uwsgi_log_alarm(x, ...) uwsgi_log("[uwsgi-alarm" x, __VA_ARGS__)
#endif
#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1);
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_req_error(x) if (wsgi_req->uri_len > 0 && wsgi_req->method_len > 0 && wsgi_req->remote_addr_len > 0) uwsgi_log_verbose("%s: %s [%s line %d] during %.*s %.*s (%.*s)\n", x, strerror(errno), __FILE__, __LINE__,\
wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); else uwsgi_log_verbose("%s %s [%s line %d] \n",x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
#define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()")
#define uwsgi_str(x) uwsgi_concat2(x, "")
#define uwsgi_str(x) uwsgi_concat2(x, (char *)"")
#define uwsgi_notify(x) if (uwsgi.notify) uwsgi.notify(x)
#define uwsgi_notify_ready() uwsgi.shared->ready = 1 ; if (uwsgi.notify_ready) uwsgi.notify_ready()
@@ -34,7 +37,7 @@ extern "C" {
#define thunder_lock if (uwsgi.threads > 1 && !uwsgi.is_et) {pthread_mutex_lock(&uwsgi.thunder_mutex);}
#define thunder_unlock if (uwsgi.threads > 1 && !uwsgi.is_et) {pthread_mutex_unlock(&uwsgi.thunder_mutex);}
#define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5) || !uwsgi_startswith(file, "exec://", 7))
#define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5) || !uwsgi_startswith(file, "exec://", 7) || !uwsgi_startswith(file, "section://", 10))
#define ushared uwsgi.shared
@@ -73,10 +76,6 @@ extern char UWSGI_EMBED_CONFIG;
extern char UWSGI_EMBED_CONFIG_END;
#endif
#ifdef __clang__
#define inline
#endif
#define UDEP(pname) extern struct uwsgi_plugin pname##_plugin;
#define ULEP(pname)\
@@ -842,6 +841,46 @@ struct uwsgi_router {
#endif
#ifdef UWSGI_ALARM
struct uwsgi_alarm;
struct uwsgi_alarm_instance {
char *name;
char *arg;
void *data_ptr;
uint8_t data8;
uint16_t data16;
uint32_t data32;
uint64_t data64;
time_t last_run;
char *last_msg;
size_t last_msg_size;
struct uwsgi_alarm *alarm;
struct uwsgi_alarm_instance *next;
};
struct uwsgi_alarm {
char *name;
void (*init)(struct uwsgi_alarm_instance *);
void (*func)(struct uwsgi_alarm_instance *, char *, size_t);
struct uwsgi_alarm *next;
};
struct uwsgi_alarm_ll {
struct uwsgi_alarm_instance *alarm;
struct uwsgi_alarm_ll *next;
};
struct uwsgi_alarm_log {
pcre *pattern;
pcre_extra *pattern_extra;
struct uwsgi_alarm_ll *alarms;
struct uwsgi_alarm_log *next;
};
#endif
struct __attribute__ ((packed)) uwsgi_header {
uint8_t modifier1;
uint16_t pktsize;
@@ -1286,6 +1325,9 @@ struct uwsgi_server {
int loggers_list;
int loop_list;
int clock_list;
#ifdef UWSGI_ALARM
int alarms_list;
#endif
struct wsgi_request *wsgi_req;
@@ -1403,6 +1445,15 @@ struct uwsgi_server {
struct uwsgi_regexp_list *log_drain_rules;
#endif
#ifdef UWSGI_ALARM
int alarm_freq;
struct uwsgi_string_list *alarm_list;
struct uwsgi_string_list *alarm_logs_list;
struct uwsgi_alarm *alarms;
struct uwsgi_alarm_instance *alarm_instances;
struct uwsgi_alarm_log *alarm_logs;
#endif
int threaded_logger;
pthread_mutex_t threaded_logger_lock;
@@ -1497,6 +1548,7 @@ struct uwsgi_server {
#endif
#ifdef UWSGI_MULTICAST
int multicast_ttl;
char *multicast_group;
#endif
@@ -2179,7 +2231,7 @@ struct wsgi_request *find_wsgi_req_by_id(int);
void async_add_fd_write(struct wsgi_request *, int, int);
void async_add_fd_read(struct wsgi_request *, int, int);
inline struct wsgi_request *next_wsgi_req(struct wsgi_request *);
struct wsgi_request *next_wsgi_req(struct wsgi_request *);
void async_add_timeout(struct wsgi_request *, int);
@@ -2240,8 +2292,8 @@ void uwsgi_opt_ldap_dump_ldif(char *, char *, void *);
void uwsgi_ldap_config(char *);
#endif
inline int uwsgi_strncmp(char *, int, char *, int);
inline int uwsgi_startswith(char *, char *, int);
int uwsgi_strncmp(char *, int, char *, int);
int uwsgi_startswith(char *, char *, int);
char *uwsgi_concat(int, ...);
@@ -2321,9 +2373,8 @@ char *uwsgi_cache_get(char *, uint16_t, uint64_t *);
uint32_t uwsgi_cache_exists(char *, uint16_t);
inline void *uwsgi_malloc(size_t);
inline void *uwsgi_calloc(size_t);
void *uwsgi_malloc(size_t);
void *uwsgi_calloc(size_t);
int event_queue_init(void);
@@ -2538,14 +2589,8 @@ struct rb_root
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
#ifdef __clang__
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#else
inline void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
#endif
struct uwsgi_rb_timer {
@@ -2584,8 +2629,8 @@ struct uwsgi_async_request {
struct uwsgi_async_request *next;
};
inline int event_queue_read(void);
inline int event_queue_write(void);
int event_queue_read(void);
int event_queue_write(void);
void uwsgi_help(char *opt, char *val, void *);
@@ -2610,7 +2655,7 @@ int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *
char *uwsgi_amqp_consume(int, uint64_t *, char **);
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int);
inline int uwsgi_starts_with(char *, int, char *, int);
int uwsgi_starts_with(char *, int, char *, int);
#ifdef __sun__
time_t timegm(struct tm *);
@@ -2841,7 +2886,7 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
ssize_t uwsgi_mule_get_msg(int, int, char *, size_t, int);
uint8_t uwsgi_signal_wait(int);
int uwsgi_signal_wait(int);
struct uwsgi_app *uwsgi_add_app(int, uint8_t, char *, int, void *, void *);
int uwsgi_signal_send(int, uint8_t);
int uwsgi_remote_signal_send(char *, uint8_t);
@@ -2923,6 +2968,7 @@ void uwsgi_opt_add_socket(char *, char *, void *);
void uwsgi_opt_add_lazy_socket(char *, char *, void *);
void uwsgi_opt_add_cron(char *, char *, void *);
void uwsgi_opt_load_plugin(char *, char *, void *);
void uwsgi_opt_load_dl(char *, char *, void *);
void uwsgi_opt_load(char *, char *, void *);
void uwsgi_opt_cluster_log(char *, char *, void *);
void uwsgi_opt_cluster_reload(char *, char *, void *);
@@ -3147,6 +3193,7 @@ void uwsgi_logvar_add(struct wsgi_request *, char *, uint8_t, char *, uint8_t);
struct uwsgi_emperor_scanner {
char *arg;
int fd;
void *data;
void (*event_func)(struct uwsgi_emperor_scanner *);
struct uwsgi_imperial_monitor *monitor;
struct uwsgi_emperor_scanner *next;
@@ -3247,6 +3294,41 @@ ssize_t uwsgi_pipe_sized(int, int, size_t, int);
int uwsgi_buffer_send(struct uwsgi_buffer *, int);
void uwsgi_master_cleanup_hooks(void);
pid_t uwsgi_daemonize2();
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *, char *, char *, time_t, uid_t, gid_t);
#if defined(__linux__)
#define UWSGI_ELF
char *uwsgi_elf_section(char *, char *, size_t *);
#endif
#ifdef UWSGI_ALARM
void uwsgi_alarm_log_check(char *, size_t);
void uwsgi_alarm_run(struct uwsgi_alarm_instance *, char *, size_t);
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *, char *, size_t);
void uwsgi_register_alarm(char *, void (*)(struct uwsgi_alarm_instance *), void (*)(struct uwsgi_alarm_instance *, char *, size_t));
void uwsgi_register_embedded_alarms();
void uwsgi_alarms_init();
#endif
struct uwsgi_thread {
pthread_t tid;
int pipe[2];
int queue;
ssize_t rlen;
void *data;
char *buf;
off_t pos;
size_t len;
uint64_t custom0;
uint64_t custom1;
uint64_t custom2;
uint64_t custom3;
void (*func)(struct uwsgi_thread *);
};
struct uwsgi_thread *uwsgi_thread_new(void (*)(struct uwsgi_thread *));
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
+39 -2
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.3-rc3'
uwsgi_version = '1.3'
import os
import re
@@ -42,6 +42,7 @@ report['filemonitor'] = False
report['udp'] = False
report['pcre'] = False
report['routing'] = False
report['alarm'] = False
report['capabilities'] = False
report['async'] = False
report['minterpreters'] = False
@@ -725,7 +726,7 @@ class uConf(object):
report['pcre'] = True
if self.get('routing'):
if self.get('pcre') == 'auto':
if self.get('routing') == 'auto':
if has_pcre:
self.gcc_list.append('core/routing')
self.cflags.append("-DUWSGI_ROUTING")
@@ -735,6 +736,17 @@ class uConf(object):
self.cflags.append("-DUWSGI_ROUTING")
report['routing'] = True
if self.get('alarm'):
if self.get('alarm') == 'auto':
if has_pcre:
self.gcc_list.append('core/alarm')
self.cflags.append("-DUWSGI_ALARM")
report['alarm'] = True
else:
self.gcc_list.append('core/alarm')
self.cflags.append("-DUWSGI_ALARM")
report['alarm'] = True
if self.has_include('sys/capability.h') and uwsgi_os == 'Linux':
self.cflags.append("-DUWSGI_CAP")
@@ -1020,6 +1032,8 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
import uwsgiplugin as up
reload(up)
requires = []
p_cflags = cflags[:]
p_ldflags = ldflags[:]
@@ -1027,6 +1041,11 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
p_ldflags += up.LDFLAGS
p_libs = up.LIBS
try:
requires = up.REQUIRES
except:
pass
p_cflags.insert(0, '-I.')
if name is None:
@@ -1090,6 +1109,11 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
try:
p_cflags.remove('-pie')
except:
pass
#for ofile in up.OBJ_LIST:
# gcc_list.insert(0,ofile)
@@ -1102,6 +1126,17 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
print("*** unable to build %s plugin ***" % name)
sys.exit(1)
try:
if requires:
f = open('.uwsgi_plugin_section', 'w')
for rp in requires:
f.write("requires=%s\n" % rp)
f.close()
os.system("objcopy %s.so --add-section uwsgi=.uwsgi_plugin_section %s.so" % (plugin_dest, plugin_dest))
os.unlink('.uwsgi_plugin_section')
except:
pass
print("*** %s plugin built and available in %s ***" % (name, plugin_dest + '.so'))
if __name__ == "__main__":
@@ -1167,6 +1202,8 @@ if __name__ == "__main__":
os.system("rm -f lib/*.o")
os.system("rm -f plugins/*/*.o")
os.system("rm -f build/*.o")
elif cmd == '--check':
os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/ proto/ lib/ apache2/")
else:
print("unknown uwsgiconfig command")