From f8e64d17e8ee7e0c0e16bc426dc20e4e6dcafbcd Mon Sep 17 00:00:00 2001 From: Unbit Date: Sat, 20 Apr 2013 13:24:36 +0200 Subject: [PATCH] added safe-fd concept and --alarm-fd --- core/alarm.c | 149 +++++++++++++++++++++++++++++++++++++++++--- core/io.c | 24 +++++++ core/master_utils.c | 3 + core/setup_utils.c | 3 + core/uwsgi.c | 12 ++++ uwsgi.h | 21 +++++++ 6 files changed, 202 insertions(+), 10 deletions(-) diff --git a/core/alarm.c b/core/alarm.c index 7bd9264e..308a450b 100644 --- a/core/alarm.c +++ b/core/alarm.c @@ -11,6 +11,29 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t uwsgi_route_signal(uai->data8); } +// simply log an alarm +void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) { +} + +void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) { + if (msg[len-1] != '\n') { + if (uai->arg && strlen(uai->arg) > 0) { + uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg); + } + else { + uwsgi_log_alarm("] %.*s\n", len, msg); + } + } + else { + if (uai->arg && strlen(uai->arg) > 0) { + uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg); + } + else { + uwsgi_log_alarm("] %.*s", len, msg); + } + } +} + // run a command on alarm void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) { uai->data_ptr = uai->arg; @@ -86,6 +109,7 @@ 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); + uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log); } static int uwsgi_alarm_add(char *name, char *plugin, char *arg) { @@ -189,21 +213,54 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) { #endif static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) { + // add uwsgi_alarm_fd; + struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds; + while(uafd) { + event_queue_add_fd_read(ut->queue, uafd->fd); + uafd = uafd->next; + } 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) - break; - uwsgi_alarm_run(uai, msg, msg_size); + if (interesting_fd == ut->pipe[1]) { + 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) + break; + uwsgi_alarm_run(uai, msg, msg_size); + } + } + // check for alarm_fd + else { + uafd = uwsgi.alarm_fds; + int fd_read = 0; + while(uafd) { + if (interesting_fd == uafd->fd) { + if (fd_read) goto raise; + size_t remains = uafd->buf_len; + while(remains) { + ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains); + if (len <= 0) { + uwsgi_error("[uwsgi-alarm-fd]/read()"); + uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd); + event_queue_del_fd(ut->queue, uafd->fd, event_queue_read()); + break; + } + remains-=len; + } + fd_read = 1; +raise: + uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len); + } + uafd = uafd->next; + } } } } @@ -243,6 +300,37 @@ void uwsgi_alarms_init() { if (!uwsgi.alarm_instances) return; + // map alarm file descriptors + usl = uwsgi.alarm_fd_list; + while(usl) { + char *space0 = strchr(usl->value, ' '); + if (!space0) { + uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value); + exit(1); + } + *space0 = 0; + size_t buf_len = 1; + char *space1 = strchr(space0+1, ' '); + if (!space1) { + uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value); + exit(1); + } + + char *colon = strchr(space0+1, ':'); + if (colon) { + buf_len = strtoul(colon+1, NULL, 10); + *colon = 0; + } + int fd = atoi(space0+1); + uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1)); + *space0 = ' '; + *space1 = ' '; + if (colon) { + *colon = ':'; + } + usl = usl->next; + } + #ifdef UWSGI_PCRE // then map log-alarm usl = uwsgi.alarm_logs_list; @@ -340,3 +428,44 @@ void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) { uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()"); } } + +struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) { + struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds; + struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm); + if (!uai) { + uwsgi_log("unable to find alarm \"%s\"\n", alarm); + exit(1); + } + + if (!buf_len) buf_len = 1; + + while(uafd) { + // check if an equal alarm has been added + if (uafd->fd == fd && uafd->alarm == uai) { + return uafd; + } + old_uafd = uafd; + uafd = uafd->next; + } + + uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd)); + uafd->fd = fd; + uafd->buf = uwsgi_malloc(buf_len); + uafd->buf_len = buf_len; + uafd->msg = msg; + uafd->msg_len = msg_len; + uafd->alarm = uai; + + if (!old_uafd) { + uwsgi.alarm_fds = uafd; + } + else { + old_uafd->next = uafd; + } + + // avoid the fd to be closed + uwsgi_add_safe_fd(fd); + uwsgi_log("[uwsgi-alarm] added fd %d\n", fd); + + return uafd; +} diff --git a/core/io.c b/core/io.c index 9bd53d1b..056a6207 100644 --- a/core/io.c +++ b/core/io.c @@ -1054,3 +1054,27 @@ void uwsgi_file_write_do(struct uwsgi_string_list *usl) { fl = fl->next; } } + +int uwsgi_fd_is_safe(int fd) { + int i; + for(i=0;i 2 (max_fd = %d)...\n", (int) uwsgi.max_fd); for (i = 3; i < (int) uwsgi.max_fd; i++) { + + if (uwsgi_fd_is_safe(i)) continue; + int found = 0; struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; diff --git a/core/setup_utils.c b/core/setup_utils.c index 26e7367d..ef958dd8 100644 --- a/core/setup_utils.c +++ b/core/setup_utils.c @@ -106,6 +106,9 @@ void uwsgi_setup_inherited_sockets() { //now close all the unbound fd for (j = 3; j < (int) uwsgi.max_fd; j++) { int useless = 1; + + if (uwsgi_fd_is_safe(j)) continue; + if (uwsgi.has_emperor) { if (j == uwsgi.emperor_fd) continue; diff --git a/core/uwsgi.c b/core/uwsgi.c index b1265a83..5ae23831 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -218,6 +218,9 @@ static struct uwsgi_option uwsgi_base_options[] = { {"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0}, {"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0}, + {"safe-fd", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0}, + {"fd-safe", no_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0}, + {"cache", required_argument, 0, "create a shared cache containing given elements", uwsgi_opt_set_64bit, &uwsgi.cache_max_items, 0}, {"cache-blocksize", required_argument, 0, "set cache blocksize", uwsgi_opt_set_64bit, &uwsgi.cache_blocksize, 0}, {"cache-store", required_argument, 0, "enable persistent cache to disk", uwsgi_opt_set_str, &uwsgi.cache_store, UWSGI_OPT_MASTER}, @@ -453,6 +456,7 @@ static struct uwsgi_option uwsgi_base_options[] = { #endif {"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}, + {"alarm-fd", required_argument, 0, "raise the specified alarm when an fd is read for read (by default it reads 1 byte, set 8 for eventfd)", uwsgi_opt_add_string_list, &uwsgi.alarm_fd_list, UWSGI_OPT_MASTER}, #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}, @@ -3269,6 +3273,14 @@ void uwsgi_opt_set_immediate_uid(char *opt, char *value, void *none) { uwsgi_log("immediate uid: %d\n", (int) uid); } +void uwsgi_opt_safe_fd(char *opt, char *value, void *foobar) { + int fd = atoi(value); + if (fd < 0) { + uwsgi_log("invalid file descriptor: %d\n", fd); + exit(1); + } + uwsgi_add_safe_fd(fd); +} void uwsgi_opt_set_int(char *opt, char *value, void *key) { int *ptr = (int *) key; diff --git a/uwsgi.h b/uwsgi.h index 96198252..0be64d09 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1146,6 +1146,18 @@ struct uwsgi_alarm { struct uwsgi_alarm *next; }; +struct uwsgi_alarm_fd { + int fd; + size_t buf_len; + void *buf; + char *msg; + size_t msg_len; + struct uwsgi_alarm_instance *alarm; + struct uwsgi_alarm_fd *next; +}; + +struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int, char *, size_t, char *, size_t); + #ifdef UWSGI_PCRE struct uwsgi_alarm_ll { struct uwsgi_alarm_instance *alarm; @@ -1836,6 +1848,8 @@ struct uwsgi_server { uint64_t alarm_msg_size; struct uwsgi_string_list *alarm_list; struct uwsgi_string_list *alarm_logs_list; + struct uwsgi_alarm_fd *alarm_fds; + struct uwsgi_string_list *alarm_fd_list; struct uwsgi_alarm *alarms; struct uwsgi_alarm_instance *alarm_instances; struct uwsgi_alarm_log *alarm_logs; @@ -1844,6 +1858,9 @@ struct uwsgi_server { int threaded_logger; pthread_mutex_t threaded_logger_lock; + int *safe_fds; + int safe_fds_cnt; + int daemons_honour_stdin; struct uwsgi_daemon *daemons; int daemons_cnt; @@ -3205,6 +3222,7 @@ 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_safe_fd(char *, char *, void *); #ifdef UWSGI_SSL void uwsgi_opt_add_legion_cron(char *, char *, void *); void uwsgi_opt_sni(char *, char *, void *); @@ -3938,6 +3956,9 @@ struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_ void uwsgi_file_write_do(struct uwsgi_string_list *); +int uwsgi_fd_is_safe(int); +void uwsgi_add_safe_fd(int); + void uwsgi_check_emperor(void); #ifdef UWSGI_AS_SHARED_LIBRARY int uwsgi_init(int, char **, char **);