]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add resistance on blocking writes to stdout
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 25 Jan 2008 23:09:33 +0000 (23:09 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 25 Jan 2008 23:09:33 +0000 (23:09 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7363 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/event_handlers/mod_event_socket/mod_event_socket.c
src/mod/loggers/mod_console/mod_console.c
src/switch_event.c
src/switch_log.c

index b0500f5671d392ab470f5afa64ee414cc5ef3575..89f63f868db8b26efdbb2abd839531aee697dddf 100644 (file)
@@ -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");
                        }
index c3c59464af5c01fb84e01fbf4bd835e7e033ca02..25039f29d0253e5b56638b8fcf14b60ac0cb3a84 100644 (file)
@@ -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;
                }
index b1170fc1c94dbf9547a212017ba8a8f868675c75..bdaf4606f5625bb234138d98e3fad7c6bf7dc071 100644 (file)
@@ -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) {
index 47239a15de481a86cd4413d83aca07804d0a74cd..1685f033308674c36b824feb84f2f646e43b3b4f 100644 (file)
@@ -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) {