diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index b0500f5671..89f63f868d 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -69,6 +69,8 @@ struct listener { switch_hash_t *event_hash; switch_thread_rwlock_t *rwlock; switch_core_session_t *session; + int lost_events; + int lost_logs; struct listener *next; }; @@ -106,7 +108,19 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { char *data = strdup(node->data); if (data) { - switch_queue_push(l->log_queue, data); + if (switch_queue_trypush(l->log_queue, data) == SWITCH_STATUS_SUCCESS) { + int ll = l->lost_logs; + switch_event_t *event; + l->lost_logs = 0; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Lost %d log lines!\n", ll); + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "info", "lost %d log lines", ll); + switch_event_fire(&event); + } + } else { + switch_safe_free(data); + l->lost_logs++; + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); } @@ -153,7 +167,21 @@ static void event_handler(switch_event_t *event) if (send) { if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { - switch_queue_push(l->event_queue, clone); + if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) { + if (l->lost_events) { + int le = l->lost_events; + l->lost_events = 0; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Lost %d events!\n", le); + clone = NULL; + if (switch_event_create(&clone, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(clone, SWITCH_STACK_BOTTOM, "info", "lost %d events", le); + switch_event_fire(&clone); + } + } + } else { + l->lost_events++; + switch_event_destroy(&clone); + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); } diff --git a/src/mod/loggers/mod_console/mod_console.c b/src/mod/loggers/mod_console/mod_console.c index c3c59464af..25039f29d0 100644 --- a/src/mod/loggers/mod_console/mod_console.c +++ b/src/mod/loggers/mod_console/mod_console.c @@ -62,7 +62,7 @@ static switch_memory_pool_t *module_pool = NULL; static switch_hash_t *log_hash = NULL; static uint32_t all_level = 0; static int32_t hard_log_level = SWITCH_LOG_DEBUG; - +static int32_t failed_write = 0; static void del_mapping(char *var) { switch_core_hash_insert(log_hash, var, NULL); @@ -147,6 +147,36 @@ static switch_status_t config_logger(void) return SWITCH_STATUS_SUCCESS; } +static int can_write(FILE *handle, int ms) +{ +#ifndef WIN32 + int aok = 1; + fd_set can_write; + int fd; + struct timeval to; + int sec, usec; + + sec = ms / 1000; + usec = ms % 1000; + + fd = fileno(handle); + memset(&to, 0, sizeof(to)); + FD_SET(fd, &can_write); + to.tv_sec = sec; + to.tv_usec = usec; + if (select(fd+1, NULL, &can_write, NULL, &to) > 0) { + aok = FD_ISSET(fd, &can_write); + } else { + aok = 0; + } + + return aok; +#else + return 1; +#endif +} + + static switch_status_t switch_console_logger(const switch_log_node_t *node, switch_log_level_t level) { FILE *handle; @@ -155,6 +185,21 @@ static switch_status_t switch_console_logger(const switch_log_node_t *node, swit return SWITCH_STATUS_SUCCESS; } + if (failed_write) { + if ((handle = switch_core_data_channel(SWITCH_CHANNEL_ID_LOG))) { + int aok = can_write(handle, 5); + if (aok) { + const char *msg = "Failed to write to the console! Logging disabled! RE-enable with the 'console loglevel' command\n"; + if (COLORIZE) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s", COLORS[1], msg, SWITCH_SEQ_DEFAULT_COLOR); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s", msg); + } + failed_write = 0; + } + } + } + if (level > hard_log_level) { return SWITCH_STATUS_SUCCESS; } @@ -162,7 +207,7 @@ static switch_status_t switch_console_logger(const switch_log_node_t *node, swit if ((handle = switch_core_data_channel(SWITCH_CHANNEL_ID_LOG))) { size_t mask = 0; size_t ok = 0; - + ok = switch_log_check_mask(all_level, level); if (log_hash) { @@ -178,6 +223,16 @@ static switch_status_t switch_console_logger(const switch_log_node_t *node, swit } if (ok) { +#ifndef WIN32 + int aok = can_write(handle, 2000); + + if (!aok) { + hard_log_level = 0; + failed_write++; + return SWITCH_STATUS_SUCCESS; + } +#endif + if (COLORIZE) { #ifdef WIN32 SetConsoleTextAttribute(hStdout, COLORS[node->level]); @@ -213,18 +268,20 @@ SWITCH_STANDARD_API(console_api_function) if (argc > 0) { - if (argc < 2) { + if (argc < 1) { err = "missing arg"; goto end; } if (!strcasecmp(argv[0], "loglevel")) { - int level; + int level = hard_log_level; - if (*argv[1] > 47 && *argv[1] < 58) { - level = atoi(argv[1]); - } else { - level = switch_log_str2level(argv[1]); + if (argc > 1) { + if (*argv[1] > 47 && *argv[1] < 58) { + level = atoi(argv[1]); + } else { + level = switch_log_str2level(argv[1]); + } } if (level == SWITCH_LOG_INVALID) { @@ -235,7 +292,9 @@ SWITCH_STANDARD_API(console_api_function) } goto end; } else if (!strcasecmp(argv[0], "colorize")) { - COLORIZE = switch_true(argv[1]); + if (argc > 1) { + COLORIZE = switch_true(argv[1]); + } stream->write_function(stream, "+OK console color %s\n", COLORIZE ? "enabled" : "disabled"); goto end; } diff --git a/src/switch_event.c b/src/switch_event.c index b1170fc1c9..bdaf4606f5 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -647,8 +647,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_ hp2 = (*event)->headers; for (hp = todup->headers; hp; hp = hp->next) { - if ((header = ALLOC(sizeof(*header))) == 0) { - return SWITCH_STATUS_MEMERR; + void *pop; + + if (switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) { + header = (switch_event_header_t *) pop; + } else { + header = ALLOC(sizeof(*header)); + switch_assert(header); } memset(header, 0, sizeof(*header)); @@ -662,7 +667,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_ (*event)->headers = header; } - last = header; + (*event)->last_header = last = header; } if (todup->body) { diff --git a/src/switch_log.c b/src/switch_log.c index 47239a15de..1685f03330 100644 --- a/src/switch_log.c +++ b/src/switch_log.c @@ -253,7 +253,27 @@ SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, const char } else { if (level == SWITCH_LOG_CONSOLE || !LOG_QUEUE || !THREAD_RUNNING) { if (handle) { - fprintf(handle, "%s", data); + int aok = 1; +#ifndef WIN32 + + fd_set can_write; + int fd; + struct timeval to; + + fd = fileno(handle); + memset(&to, 0, sizeof(to)); + FD_SET(fd, &can_write); + to.tv_sec = 0; + to.tv_usec = 5000; + if (select(fd+1, NULL, &can_write, NULL, &to) > 0) { + aok = FD_ISSET(fd, &can_write); + } else { + aok = 0; + } +#endif + if (aok) { + fprintf(handle, "%s", data); + } } free(data); } else if (level <= MAX_LEVEL) {