]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
* Add time out for sync IO as it can cause unpredictable errors
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 21 Sep 2009 14:46:48 +0000 (18:46 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 21 Sep 2009 14:46:48 +0000 (18:46 +0400)
CMakeLists.txt
config.h.in
src/buffer.c
src/map.c
src/plugins/regexp.c
src/util.c

index 7428c13b40d9cb1b52d14d1b69546f93f3a6e283..390b1bbfc146f8acd2d1a9d9e47a87cb66413530 100644 (file)
@@ -229,6 +229,7 @@ CHECK_INCLUDE_FILES(libgen.h HAVE_LIBGEN_H)
 CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H)
 CHECK_INCLUDE_FILES(grp.h HAVE_GRP_H)
 CHECK_INCLUDE_FILES(glob.h HAVE_GLOB_H)
+CHECK_INCLUDE_FILES(poll.h HAVE_POLL_H)
 
 IF(HAVE_SYS_WAIT_H)
        LIST(APPEND CMAKE_REQUIRED_INCLUDES sys/wait.h)
index 5a7439788067b4adc4d972981e1f20011bf1ce48..2c03d5486c6c76ebb8f5042ade472a99c920d471 100644 (file)
@@ -36,6 +36,8 @@
 
 #cmakedefine HAVE_NETDB_H        1
 
+#cmakedefine HAVE_POLL_H         1
+
 #cmakedefine HAVE_SYSLOG_H       1
 
 #cmakedefine HAVE_LIBUTIL_H      1
 #include <fcntl.h>
 #endif
 
+/* poll */
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
 /* sys/stat */
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
index d212fc22096f7be6fa9c36ada577d9620fd618c6..7c52da10de4ecc100504aa6717833effa098f989 100644 (file)
@@ -344,6 +344,9 @@ rspamd_remove_dispatcher (rspamd_io_dispatcher_t *dispatcher)
        if (dispatcher != NULL) {
                event_del (dispatcher->ev);
                memory_pool_delete (dispatcher->pool);
+               if (dispatcher->out_buffers) {
+                       g_list_free (dispatcher->out_buffers);
+               }
                g_free (dispatcher);
        }
 }
index cbe8e502685bcaf2dc86cefaf3fd0944777b9fcc..147b06515e9b89ebe7f0b114d7887dacc1ac8bda 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -418,7 +418,7 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
        if (map_pool == NULL) {
                map_pool = memory_pool_new (memory_pool_get_size ());
        }
-       new_map = memory_pool_alloc (map_pool, sizeof (struct rspamd_map));
+       new_map = memory_pool_alloc0 (map_pool, sizeof (struct rspamd_map));
        new_map->read_callback = read_callback;
        new_map->fin_callback = fin_callback;
        new_map->user_data = user_data;
@@ -430,13 +430,13 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
                        msg_warn ("add_map: cannot open file '%s': %s", def, strerror (errno));
                        return FALSE;
                }
-               fdata = memory_pool_alloc (map_pool, sizeof (struct file_map_data));
+               fdata = memory_pool_alloc0 (map_pool, sizeof (struct file_map_data));
                fdata->filename = memory_pool_strdup (map_pool, def);
                fstat (fd, &fdata->st);
                new_map->map_data = fdata;
        }
        else if (proto == PROTO_HTTP) {
-               hdata = memory_pool_alloc (map_pool, sizeof (struct http_map_data));
+               hdata = memory_pool_alloc0 (map_pool, sizeof (struct http_map_data));
                /* Try to search port */
                if ((p = strchr (def, ':')) != NULL) {
                        hostend = p;
index dcbdce7b6e887258fad6aac903f53de47c277cbf..d8d9f3ea8c34ed1aea73d477c8f4d13f85cc14fe 100644 (file)
@@ -312,10 +312,10 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task)
                                return 0;
                        }
                        else {
+                               memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, headerlist);
                                if (re->regexp == NULL) {
                                        msg_debug ("process_regexp: regexp contains only header and it is found %s", re->header);
                                        task_cache_add (task, re, 1);
-                                       g_list_free (headerlist);
                                        return 1;
                                }
                                cur = headerlist;
@@ -327,7 +327,6 @@ process_regexp (struct rspamd_regexp *re, struct worker_task *task)
                                        }
                                        cur = g_list_next (cur);
                                }
-                               g_list_free (headerlist);
                                task_cache_add (task, re, 0);
                                return 0;
                        }
index ba06c570ea61cdba53244f9031b235214a8e9324..2e18c441afd46bccdf15ac63bd60a1035c0092f0 100644 (file)
@@ -32,6 +32,8 @@
 #define CHECK_TIME 60
 /* More than 2 log messages per second */
 #define BUF_INTENSITY 2
+/* Default connect timeout for sync sockets */
+#define CONNECT_TIMEOUT 3
 
 #ifdef RSPAMD_MAIN
 sig_atomic_t do_reopen_log = 0;
@@ -54,13 +56,49 @@ static gboolean log_buffered = FALSE;
 int
 make_socket_nonblocking (int fd)
 {
-       if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+       int ofl;
+
+       ofl = fcntl (fd, F_GETFL, 0);
+
+       if (fcntl (fd, F_SETFL, ofl | O_NONBLOCK) == -1) {
+               msg_warn ("make_socket_nonblocking: fcntl failed: %d, '%s'", errno, strerror (errno));
+               return -1;
+       }
+       return 0;
+}
+
+int
+make_socket_blocking (int fd)
+{      
+       int ofl;
+
+       ofl = fcntl (fd, F_GETFL, 0);
+
+       if (fcntl (fd, F_SETFL, ofl & (~O_NONBLOCK)) == -1) {
                msg_warn ("make_socket_nonblocking: fcntl failed: %d, '%s'", errno, strerror (errno));
                return -1;
        }
        return 0;
 }
 
+static int 
+poll_sync_socket (int fd, int timeout, short events)
+{
+       int r;
+       struct pollfd fds[1];
+
+       fds->fd = fd;
+       fds->events = events;
+       fds->revents = 0;
+       while ((r = poll (fds, 1, timeout)) < 0) {
+               if (errno != EINTR) {
+                       break;
+               }
+       }
+
+       return r;
+}
+
 static int
 make_inet_socket (int family, struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
 {
@@ -75,7 +113,7 @@ make_inet_socket (int family, struct in_addr *addr, u_short port, gboolean is_se
                return -1;
        }
 
-       if (async && make_socket_nonblocking(fd) < 0) {
+       if (make_socket_nonblocking (fd) < 0) {
                goto out;
        }
        
@@ -99,10 +137,24 @@ make_inet_socket (int family, struct in_addr *addr, u_short port, gboolean is_se
        }
 
        if (r == -1) {
-               if (!async || errno != EINPROGRESS) {
+               if (errno != EINPROGRESS) {
                        msg_warn ("make_tcp_socket: bind/connect failed: %d, '%s'", errno, strerror (errno));
                        goto out;
                }
+               if (!async) {
+                       /* Try to poll */
+                       if (poll_sync_socket (fd, CONNECT_TIMEOUT * 1000, POLLOUT) <= 0) {
+                               errno = ETIMEDOUT;
+                               msg_warn ("make_tcp_socket: bind/connect failed: timeout");
+                               goto out;
+                       }
+                       else {
+                               /* Make synced again */
+                               if (make_socket_blocking (fd) < 0) {
+                                       goto out;
+                               }
+                       }
+               }
        }
        else {
                /* Still need to check SO_ERROR on socket */