@@ -933,6 +933,7 @@ rspamd_main_heartbeat_start (struct rspamd_worker *wrk, struct ev_loop *event_lo | |||
ev_timer_start (event_loop, &wrk->hb.heartbeat_ev); | |||
} | |||
/** | |||
* Handles worker after fork returned zero | |||
* @param wrk |
@@ -1042,10 +1042,11 @@ rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type, | |||
int | |||
rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
gboolean async) | |||
enum rspamd_inet_address_listen_opts opts, | |||
gint listen_queue) | |||
{ | |||
gint fd, r; | |||
gint on = 1; | |||
gint on = 1, serrno; | |||
const struct sockaddr *sa; | |||
const char *path; | |||
@@ -1053,7 +1054,8 @@ rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
return -1; | |||
} | |||
fd = rspamd_socket_create (addr->af, type, 0, async); | |||
fd = rspamd_socket_create (addr->af, type, 0, | |||
(opts & RSPAMD_INET_ADDRESS_LISTEN_ASYNC)); | |||
if (fd == -1) { | |||
return -1; | |||
} | |||
@@ -1070,7 +1072,23 @@ rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
sa = &addr->u.in.addr.sa; | |||
} | |||
(void)setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint)); | |||
#if defined(SO_REUSEADDR) | |||
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint)) == -1) { | |||
msg_err ("cannot set SO_REUSEADDR on %d: %d", fd, strerror (errno)); | |||
goto err; | |||
} | |||
#endif | |||
#if defined(SO_REUSEPORT) | |||
if (opts & RSPAMD_INET_ADDRESS_LISTEN_REUSEPORT) { | |||
on = 1; | |||
if (setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (const void *)&on, sizeof (gint)) == -1) { | |||
msg_err ("cannot set SO_REUSEPORT on %d: %d", fd, strerror (errno)); | |||
goto err; | |||
} | |||
} | |||
#endif | |||
#ifdef HAVE_IPV6_V6ONLY | |||
if (addr->af == AF_INET6) { | |||
@@ -1086,13 +1104,13 @@ rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
r = bind (fd, sa, addr->slen); | |||
if (r == -1) { | |||
if (!async || errno != EINPROGRESS) { | |||
close (fd); | |||
if (!(opts & RSPAMD_INET_ADDRESS_LISTEN_ASYNC) || errno != EINPROGRESS) { | |||
msg_warn ("bind %s failed: %d, '%s'", | |||
rspamd_inet_address_to_string_pretty (addr), | |||
errno, | |||
strerror (errno)); | |||
return -1; | |||
goto err; | |||
} | |||
} | |||
@@ -1115,18 +1133,31 @@ rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
path, addr->u.un->mode, strerror (errno)); | |||
} | |||
} | |||
r = listen (fd, -1); | |||
r = listen (fd, listen_queue); | |||
if (r == -1) { | |||
msg_warn ("listen %s failed: %d, '%s'", | |||
rspamd_inet_address_to_string_pretty (addr), | |||
errno, strerror (errno)); | |||
close (fd); | |||
return -1; | |||
goto err; | |||
} | |||
} | |||
return fd; | |||
err: | |||
/* Error path */ | |||
serrno = errno; | |||
if (fd != -1) { | |||
close (fd); | |||
} | |||
errno = serrno; | |||
return -1; | |||
} | |||
gssize |
@@ -228,15 +228,21 @@ void rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port); | |||
int rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type, | |||
gboolean async); | |||
enum rspamd_inet_address_listen_opts { | |||
RSPAMD_INET_ADDRESS_LISTEN_DEFAULT = 0, | |||
RSPAMD_INET_ADDRESS_LISTEN_ASYNC = (1u << 0u), | |||
RSPAMD_INET_ADDRESS_LISTEN_REUSEPORT = (1u << 1u), | |||
}; | |||
/** | |||
* Listen on a specified inet address | |||
* @param addr | |||
* @param type | |||
* @param async | |||
* @param opts | |||
* @return | |||
*/ | |||
int rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type, | |||
gboolean async); | |||
enum rspamd_inet_address_listen_opts opts, | |||
gint listen_queue); | |||
/** | |||
* Check whether specified ip is valid (not INADDR_ANY or INADDR_NONE) for ipv4 or ipv6 |
@@ -946,7 +946,9 @@ rspamadm_lua (gint argc, gchar **argv, const struct rspamadm_command *cmd) | |||
for (i = 0; i < addrs->len; i ++) { | |||
rspamd_inet_addr_t *addr = g_ptr_array_index (addrs, i); | |||
fd = rspamd_inet_address_listen (addr, SOCK_STREAM, TRUE); | |||
fd = rspamd_inet_address_listen (addr, SOCK_STREAM, | |||
RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1); | |||
if (fd != -1) { | |||
static ev_io ev; | |||
@@ -412,7 +412,7 @@ create_listen_socket (GPtrArray *addrs, guint cnt, | |||
*/ | |||
if (listen_type & RSPAMD_WORKER_SOCKET_TCP) { | |||
fd = rspamd_inet_address_listen (g_ptr_array_index (addrs, i), | |||
SOCK_STREAM, TRUE); | |||
SOCK_STREAM, RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1); | |||
if (fd != -1) { | |||
ls = g_malloc0 (sizeof (*ls)); | |||
ls->addr = rspamd_inet_address_copy (g_ptr_array_index (addrs, i)); | |||
@@ -423,7 +423,7 @@ create_listen_socket (GPtrArray *addrs, guint cnt, | |||
} | |||
if (listen_type & RSPAMD_WORKER_SOCKET_UDP) { | |||
fd = rspamd_inet_address_listen (g_ptr_array_index (addrs, i), | |||
SOCK_DGRAM, TRUE); | |||
SOCK_DGRAM, RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1); | |||
if (fd != -1) { | |||
ls = g_malloc0 (sizeof (*ls)); | |||
ls->addr = rspamd_inet_address_copy (g_ptr_array_index (addrs, i)); | |||
@@ -1438,7 +1438,7 @@ main (gint argc, gchar **argv, gchar **env) | |||
} | |||
else { | |||
control_fd = rspamd_inet_address_listen (control_addr, SOCK_STREAM, | |||
TRUE); | |||
RSPAMD_INET_ADDRESS_LISTEN_ASYNC, -1); | |||
if (control_fd == -1) { | |||
msg_err_main ("cannot open control socket at path: %s", | |||
rspamd_main->cfg->control_socket_path); |