diff --git a/core/alarm.c b/core/alarm.c index 3df689ff..595a2526 100644 --- a/core/alarm.c +++ b/core/alarm.c @@ -136,6 +136,7 @@ static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) { } +#ifdef UWSGI_PCRE static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) { struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs; @@ -182,10 +183,33 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) { } return 0; } +#endif + +static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) { + char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long)); + for (;;) { + int interesting_fd = -1; + int ret = event_queue_wait(ut->queue, -1, &interesting_fd); + if (ret > 0) { + ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long)); + if (len > (ssize_t)(sizeof(long) + 1)) { + size_t msg_size = len - sizeof(long); + char *msg = buf + sizeof(long); + long ptr = 0; + memcpy(&ptr, buf, sizeof(long)); + struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr; + if (!uai) return; + uwsgi_alarm_run(uai, msg, msg_size); + } + } + } +} // initialize alarms, instances and log regexps void uwsgi_alarms_init() { + if (!uwsgi.master_process) return; + // first of all, create instance of alarms struct uwsgi_string_list *usl = uwsgi.alarm_list; while (usl) { @@ -212,6 +236,9 @@ void uwsgi_alarms_init() { usl = usl->next; } + if (!uwsgi.alarm_instances) return; + +#ifdef UWSGI_PCRE // then map log-alarm usl = uwsgi.alarm_logs_list; while (usl) { @@ -231,8 +258,17 @@ void uwsgi_alarms_init() { usl = usl->next; } +#endif + + // start the alarm_threa + uwsgi.alarm_thread = uwsgi_thread_new(uwsgi_alarm_thread_loop); + if (!uwsgi.alarm_thread) { + uwsgi_log("unable to spawn alarm thread\n"); + exit(1); + } } +#ifdef UWSGI_PCRE // 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)) @@ -250,6 +286,7 @@ void uwsgi_alarm_log_check(char *msg, size_t len) { ual = ual->next; } } +#endif // call the alarm func void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { @@ -265,6 +302,7 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { uai->last_msg_size = len; } +#ifdef UWSGI_PCRE // call the alarms mapped to a log line void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) { struct uwsgi_alarm_ll *uall = ual->alarms; @@ -273,3 +311,24 @@ void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) { uall = uall->next; } } +#endif + + +// this is the api function workers,mules and whatever you want can call from code +void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) { + if (!uwsgi.alarm_thread) return; + if (len > uwsgi.alarm_msg_size) return; + struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name); + if (!uai) return; + + struct iovec iov[2]; + iov[0].iov_base = &uai; + iov[0].iov_len = sizeof(long); + iov[1].iov_base = msg; + iov[1].iov_len = len; + + // now send the message to the alarm thread + if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) { + uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/write()"); + } +} diff --git a/core/init.c b/core/init.c index 218b3bd8..86981e55 100644 --- a/core/init.c +++ b/core/init.c @@ -146,9 +146,8 @@ void uwsgi_init_default() { uwsgi.ssl_sessions_timeout = 300; #endif -#ifdef UWSGI_ALARM uwsgi.alarm_freq = 3; -#endif + uwsgi.alarm_msg_size = 8192; uwsgi.multicast_ttl = 1; diff --git a/core/logging.c b/core/logging.c index 299994fb..7785a3cd 100644 --- a/core/logging.c +++ b/core/logging.c @@ -1182,10 +1182,8 @@ 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 + uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen); struct uwsgi_regexp_list *url = uwsgi.log_drain_rules; while (url) { if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) { diff --git a/core/master.c b/core/master.c index b82c10b9..dd4c2e63 100644 --- a/core/master.c +++ b/core/master.c @@ -369,10 +369,6 @@ int master_loop(char **argv, char **environ) { uwsgi_threaded_logger_spawn(); } -#ifdef UWSGI_ALARM - // initialize the alarm subsystem - uwsgi_alarms_init(); -#endif } #ifdef UWSGI_SSL diff --git a/core/uwsgi.c b/core/uwsgi.c index d0c4788e..d328904c 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -409,16 +409,17 @@ static struct uwsgi_option uwsgi_base_options[] = { {"log-route", required_argument, 0, "log to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_route, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, {"log-req-route", required_argument, 0, "log requests to the specified named logger if regexp applied on logline matches", uwsgi_opt_add_regexp_custom_list, &uwsgi.log_req_route, UWSGI_OPT_REQ_LOG_MASTER}, #endif -#ifdef UWSGI_ALARM - {"alarm", required_argument, 0, "create a new alarm, syntax: ", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, + {"alarm", required_argument, 0, "create a new alarm, syntax: ", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER}, {"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0}, +#ifdef UWSGI_PCRE {"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: [,alarm...] ", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, {"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: [,alarm...] ", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, {"not-log-alarm", required_argument, 0, "skip the specified alarm when a log line matches the specified regexp, syntax: [,alarm...] ", uwsgi_opt_add_string_list_custom, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, {"not-alarm-log", required_argument, 0, "skip the specified alarm when a log line matches the specified regexp, syntax: [,alarm...] ", uwsgi_opt_add_string_list_custom, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER}, +#endif {"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 + {"alarm-msg-size", required_argument, 0, "set the max size of an alarm message (default 8192)", uwsgi_opt_set_64bit, &uwsgi.alarm_msg_size, 0}, #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 @@ -1530,7 +1531,6 @@ 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"); @@ -1540,7 +1540,6 @@ static void alarms_list(void) { } uwsgi_log("--- end of alarms list ---\n\n"); } -#endif static time_t uwsgi_unix_seconds() { return time(NULL); @@ -1797,12 +1796,8 @@ int main(int argc, char *argv[], char *envp[]) { uwsgi_register_stats_pusher("file", uwsgi_stats_pusher_file); uwsgi_stats_pusher_setup(); - -#ifdef UWSGI_ALARM // register embedded alarms uwsgi_register_embedded_alarms(); -#endif - /* uWSGI IS CONFIGURED !!! */ @@ -1843,10 +1838,8 @@ 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) @@ -2190,6 +2183,9 @@ int uwsgi_start(void *v_argv) { } } + // initialize the alarm subsystem + uwsgi_alarms_init(); + /* plugin initialization */ for (i = 0; i < uwsgi.gp_cnt; i++) { if (uwsgi.gp[i]->init) { diff --git a/plugins/alarm_xmpp/gloox.cc b/plugins/alarm_xmpp/gloox.cc index dfdb2476..767d3c5a 100644 --- a/plugins/alarm_xmpp/gloox.cc +++ b/plugins/alarm_xmpp/gloox.cc @@ -52,11 +52,11 @@ class Jabbo : public ConnectionListener{ event_queue_add_fd_read(u_thread->queue, fd); event_queue_add_fd_read(u_thread->queue, u_thread->pipe[1]); u_connected = 1; - uwsgi_log("[uwsgi-xmpp] connected to the XMPP server\n"); + uwsgi_log("[uwsgi-alarm-xmpp] connected to the XMPP server\n"); } virtual void onDisconnect(ConnectionError e) { - uwsgi_log("[uwsgi-xmpp] trying reconnect to the XMPP server...\n"); + uwsgi_log("[uwsgi-alarm-xmpp] trying reconnect to the XMPP server...\n"); if (u_connected) { // no need to remove it as it is already closed... //event_queue_del_fd(u_thread->queue, fd, event_queue_read()); @@ -69,12 +69,12 @@ class Jabbo : public ConnectionListener{ } virtual void onResourceBindError(const Error *error) { - uwsgi_log("[uwsgi-xmpp] onResourceBindError(): %s\n", error->text().c_str()); + uwsgi_log("[uwsgi-alarm-xmpp] onResourceBindError(): %s\n", error->text().c_str()); client->disconnect(); } virtual void onSessionCreateError(const Error *error) { - uwsgi_log("[uwsgi-xmpp] onSessionCreateError(): %s\n", error->text().c_str()); + uwsgi_log("[uwsgi-alarm-xmpp] onSessionCreateError(): %s\n", error->text().c_str()); client->disconnect(); } diff --git a/plugins/go/go_plugin.c b/plugins/go/go_plugin.c index 9ec9d81c..356571a5 100644 --- a/plugins/go/go_plugin.c +++ b/plugins/go/go_plugin.c @@ -33,7 +33,7 @@ struct uwsgi_option uwsgi_go_options[] = { uwsgi_log("[uwsgi-go] unable to load " #x " function\n"); exit(1);\ } -int uwsgi_go_init() { +static int uwsgi_go_init() { // build the functions table @@ -54,7 +54,7 @@ int uwsgi_go_init() { return 0; } -int uwsgi_go_request(struct wsgi_request *wsgi_req) { +static int uwsgi_go_request(struct wsgi_request *wsgi_req) { /* Standard GO request */ if (!wsgi_req->uh->pktsize) { uwsgi_log("Empty GO request. skip.\n"); @@ -79,17 +79,17 @@ int uwsgi_go_request(struct wsgi_request *wsgi_req) { return UWSGI_OK; } -void uwsgi_go_after_request(struct wsgi_request *wsgi_req) { +static void uwsgi_go_after_request(struct wsgi_request *wsgi_req) { log_request(wsgi_req); } -int uwsgi_go_signal_handler(uint8_t signum, void *handler) { +static int uwsgi_go_signal_handler(uint8_t signum, void *handler) { return uwsgi_go_helper_signal_handler_c((int)signum, handler); } -void goroutines_loop() { +static void goroutines_loop() { int i; for (i = 1; i < uwsgi.async; i++) { uwsgi_go_helper_run_core_c(i); @@ -97,7 +97,7 @@ void goroutines_loop() { simple_loop_run_int(0); } -void uwsgi_go_on_load() { +static void uwsgi_go_on_load() { uwsgi_register_loop("goroutines", goroutines_loop); } diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index 1d4b4672..d90b4a84 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -669,7 +669,7 @@ static void uwsgi_perl_atexit() { return; // if busy do not run atexit hooks - if (uwsgi.workers[uwsgi.mywid].busy) + if (uwsgi_worker_is_busy(uwsgi.mywid)) return; // managing atexit in async mode is a real pain...skip it for now diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index 2459f70a..bcfd143f 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -198,6 +198,24 @@ XS(XS_log) { XSRETURN_UNDEF; } +XS(XS_alarm) { + + dXSARGS; + + char *alarm; + char *msg; + STRLEN msg_len; + + psgi_check_args(2); + + alarm = SvPV_nolen(ST(0)); + msg = SvPV(ST(1), msg_len); + + uwsgi_alarm_trigger(alarm, msg, msg_len); + + XSRETURN_UNDEF; +} + XS(XS_async_connect) { dXSARGS; @@ -379,6 +397,7 @@ void init_perl_embedded_module() { #ifdef UWSGI_SSL psgi_xs(i_am_the_lord); #endif + psgi_xs(alarm); psgi_xs(websocket_handshake); psgi_xs(websocket_recv); psgi_xs(websocket_send); diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index a1ad7017..a3f63e13 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -514,6 +514,20 @@ PyObject *py_uwsgi_log_this(PyObject * self, PyObject * args) { return Py_None; } +PyObject *py_uwsgi_alarm(PyObject * self, PyObject * args) { + char *alarm = NULL; + char *msg = NULL; + Py_ssize_t msg_len = 0; + if (!PyArg_ParseTuple(args, "ss#:alarm", &alarm, &msg, &msg_len)) { + return NULL; + } + + uwsgi_alarm_trigger(alarm, msg, msg_len); + + Py_INCREF(Py_None); + return Py_None; +} + PyObject *py_uwsgi_get_logvar(PyObject * self, PyObject * args) { char *key = NULL; @@ -2438,6 +2452,7 @@ static PyMethodDef uwsgi_advanced_methods[] = { {"log_this_request", py_uwsgi_log_this, METH_VARARGS, ""}, {"set_logvar", py_uwsgi_set_logvar, METH_VARARGS, ""}, {"get_logvar", py_uwsgi_get_logvar, METH_VARARGS, ""}, + {"alarm", py_uwsgi_alarm, METH_VARARGS, ""}, {"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""}, {"grunt", py_uwsgi_grunt, METH_VARARGS, ""}, {"lock", py_uwsgi_lock, METH_VARARGS, ""}, diff --git a/plugins/rack/rack_api.c b/plugins/rack/rack_api.c index 9c1f32ac..32282d72 100644 --- a/plugins/rack/rack_api.c +++ b/plugins/rack/rack_api.c @@ -477,6 +477,15 @@ VALUE rack_uwsgi_add_rb_timer(VALUE *class, VALUE rbsignum, VALUE secs) { } +VALUE rack_uwsgi_alarm(VALUE *class, VALUE alarm, VALUE msg) { + + Check_Type(alarm, T_STRING); + Check_Type(msg, T_STRING); + + uwsgi_alarm_trigger(RSTRING_PTR(alarm), RSTRING_PTR(msg), RSTRING_LEN(msg)); + + return Qnil; +} VALUE rack_uwsgi_add_file_monitor(VALUE *class, VALUE rbsignum, VALUE rbfilename) { @@ -943,6 +952,8 @@ void uwsgi_rack_init_api() { uwsgi_rack_api("add_rb_timer", rack_uwsgi_add_rb_timer, 2); uwsgi_rack_api("add_file_monitor", rack_uwsgi_add_file_monitor, 2); + uwsgi_rack_api("alarm", rack_uwsgi_alarm, 2); + uwsgi_rack_api("websocket_handshake", uwsgi_ruby_websocket_handshake, -1); uwsgi_rack_api("websocket_send", uwsgi_ruby_websocket_send, 1); uwsgi_rack_api("websocket_recv", uwsgi_ruby_websocket_recv, 0); @@ -977,7 +988,7 @@ void uwsgi_rack_init_api() { #endif - if (uwsgi.cache_max_items > 0) { + if (uwsgi.caches) { uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, 1); uwsgi_rack_api("cache_get!", rack_uwsgi_cache_get_exc, 1); uwsgi_rack_api("cache_exists", rack_uwsgi_cache_exists, 1); diff --git a/uwsgi.h b/uwsgi.h index 2da0f379..963f216f 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -15,9 +15,7 @@ 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__,\ @@ -1061,7 +1059,6 @@ struct uwsgi_cache { #endif -#ifdef UWSGI_ALARM struct uwsgi_alarm; struct uwsgi_alarm_instance { char *name; @@ -1088,6 +1085,7 @@ struct uwsgi_cache { struct uwsgi_alarm *next; }; +#ifdef UWSGI_PCRE struct uwsgi_alarm_ll { struct uwsgi_alarm_instance *alarm; struct uwsgi_alarm_ll *next; @@ -1619,9 +1617,7 @@ struct uwsgi_server { int loggers_list; int loop_list; int clock_list; -#ifdef UWSGI_ALARM int alarms_list; -#endif struct wsgi_request *wsgi_req; @@ -1747,14 +1743,14 @@ struct uwsgi_server { struct uwsgi_regexp_list *log_req_route; #endif -#ifdef UWSGI_ALARM int alarm_freq; + uint64_t alarm_msg_size; 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 + struct uwsgi_thread *alarm_thread; int threaded_logger; pthread_mutex_t threaded_logger_lock; @@ -3565,14 +3561,13 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *, char *, char *, tim 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 +void uwsgi_alarm_trigger(char *, char *, size_t); struct uwsgi_thread { pthread_t tid; diff --git a/uwsgiconfig.py b/uwsgiconfig.py index 189d6867..57888809 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -63,7 +63,6 @@ report['filemonitor'] = False report['pcre'] = False report['matheval'] = False report['routing'] = False -report['alarm'] = False report['capabilities'] = False report['ini'] = False report['yaml'] = False @@ -448,7 +447,7 @@ class uConf(object): self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor', 'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks', 'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', - 'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', + 'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi'] @@ -818,17 +817,6 @@ 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")