From f11a1c737f7e1d524d8b8bc056a531ab0f669d8e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 21 Sep 2009 18:46:48 +0400 Subject: [PATCH] * Add time out for sync IO as it can cause unpredictable errors --- CMakeLists.txt | 1 + config.h.in | 7 ++++++ src/buffer.c | 3 +++ src/map.c | 6 ++--- src/plugins/regexp.c | 3 +-- src/util.c | 58 +++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 70 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7428c13b4..390b1bbfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/config.h.in b/config.h.in index 5a7439788..2c03d5486 100644 --- a/config.h.in +++ b/config.h.in @@ -36,6 +36,8 @@ #cmakedefine HAVE_NETDB_H 1 +#cmakedefine HAVE_POLL_H 1 + #cmakedefine HAVE_SYSLOG_H 1 #cmakedefine HAVE_LIBUTIL_H 1 @@ -222,6 +224,11 @@ #include #endif +/* poll */ +#ifdef HAVE_POLL_H +#include +#endif + /* sys/stat */ #ifdef HAVE_SYS_STAT_H #include diff --git a/src/buffer.c b/src/buffer.c index d212fc220..7c52da10d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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); } } diff --git a/src/map.c b/src/map.c index cbe8e5026..147b06515 100644 --- 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; diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c index dcbdce7b6..d8d9f3ea8 100644 --- a/src/plugins/regexp.c +++ b/src/plugins/regexp.c @@ -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; } diff --git a/src/util.c b/src/util.c index ba06c570e..2e18c441a 100644 --- a/src/util.c +++ b/src/util.c @@ -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 */ -- 2.39.5