summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--config.h.in7
-rw-r--r--src/buffer.c3
-rw-r--r--src/map.c6
-rw-r--r--src/plugins/regexp.c3
-rw-r--r--src/util.c58
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 <fcntl.h>
#endif
+/* poll */
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
/* sys/stat */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
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 */