Commit dc880427 authored by Daniel Salzman's avatar Daniel Salzman

Fix polling with many FDs

parents d8e63f44 75aa6af3
......@@ -447,7 +447,7 @@ AC_SEARCH_LIBS([capng_apply], [cap-ng])
# Checks for header files.
AC_HEADER_RESOLV
AC_CHECK_HEADERS_ONCE([cap-ng.h netinet/in_systm.h pthread_np.h signal.h sys/select.h sys/time.h sys/wait.h sys/uio.h])
AC_CHECK_HEADERS_ONCE([cap-ng.h netinet/in_systm.h pthread_np.h signal.h sys/time.h sys/wait.h sys/uio.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
......@@ -456,7 +456,7 @@ AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
# Checks for library functions.
AC_CHECK_FUNCS([clock_gettime gettimeofday fgetln getline madvise malloc_trim poll posix_memalign pthread_setaffinity_np regcomp select setgroups strlcat strlcpy initgroups accept4])
AC_CHECK_FUNCS([clock_gettime gettimeofday fgetln getline madvise malloc_trim poll posix_memalign pthread_setaffinity_np regcomp setgroups strlcat strlcpy initgroups accept4])
# Check for be64toh function
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <endian.h>]], [[return be64toh(0);]])],
......
......@@ -18,6 +18,7 @@
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <poll.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <sys/uio.h>
......@@ -302,21 +303,16 @@ int net_accept(int sock, struct sockaddr_storage *addr)
/* -- I/O interface handling partial -------------------------------------- */
/*!
* \brief Perform \a select() on one socket.
*
* \param read Wait for input readiness.
* \param write Wait for output readiness.
* \brief Perform \a poll() on one socket.
*/
static int select_one(int fd, bool read, bool write, struct timeval *timeout)
static int poll_one(int fd, int events, int timeout_ms)
{
fd_set set;
FD_ZERO(&set);
FD_SET(fd, &set);
fd_set *rfds = read ? &set : NULL;
fd_set *wfds = write ? &set : NULL;
struct pollfd pfd = {
.fd = fd,
.events = events
};
return select(fd + 1, rfds, wfds, NULL, timeout);
return poll(&pfd, 1, timeout_ms);
}
/*!
......@@ -346,7 +342,7 @@ static bool io_should_wait(int error)
*/
struct io {
ssize_t (*process)(int sockfd, struct msghdr *msg);
int (*wait)(int sockfd, struct timeval *timeout);
int (*wait)(int sockfd, int timeout_ms);
};
/*!
......@@ -393,7 +389,7 @@ static void msg_iov_shift(struct msghdr *msg, size_t done)
*
*/
static ssize_t io_exec(const struct io *io, int fd, struct msghdr *msg,
bool oneshot, struct timeval *timeout)
bool oneshot, int timeout_ms)
{
size_t done = 0;
size_t total = msg_iov_len(msg);
......@@ -415,7 +411,7 @@ static ssize_t io_exec(const struct io *io, int fd, struct msghdr *msg,
/* Wait for data readiness. */
if (ret > 0 || (ret == -1 && io_should_wait(errno))) {
do {
ret = io->wait(fd, timeout);
ret = io->wait(fd, timeout_ms);
} while (ret == -1 && errno == EINTR);
if (ret == 1) {
continue;
......@@ -436,19 +432,19 @@ static ssize_t recv_process(int fd, struct msghdr *msg)
return recvmsg(fd, msg, MSG_DONTWAIT | MSG_NOSIGNAL);
}
static int recv_wait(int fd, struct timeval *timeout)
static int recv_wait(int fd, int timeout_ms)
{
return select_one(fd, true, false, timeout);
return poll_one(fd, POLLIN, timeout_ms);
}
static ssize_t recv_data(int sock, struct msghdr *msg, bool oneshot, struct timeval *timeout)
static ssize_t recv_data(int sock, struct msghdr *msg, bool oneshot, int timeout_ms)
{
static const struct io RECV_IO = {
.process = recv_process,
.wait = recv_wait
};
return io_exec(&RECV_IO, sock, msg, oneshot, timeout);
return io_exec(&RECV_IO, sock, msg, oneshot, timeout_ms);
}
static ssize_t send_process(int fd, struct msghdr *msg)
......@@ -456,25 +452,25 @@ static ssize_t send_process(int fd, struct msghdr *msg)
return sendmsg(fd, msg, MSG_NOSIGNAL);
}
static int send_wait(int fd, struct timeval *timeout)
static int send_wait(int fd, int timeout_ms)
{
return select_one(fd, false, true, timeout);
return poll_one(fd, POLLOUT, timeout_ms);
}
static ssize_t send_data(int sock, struct msghdr *msg, struct timeval *timeout)
static ssize_t send_data(int sock, struct msghdr *msg, int timeout_ms)
{
static const struct io SEND_IO = {
.process = send_process,
.wait = send_wait
};
return io_exec(&SEND_IO, sock, msg, false, timeout);
return io_exec(&SEND_IO, sock, msg, false, timeout_ms);
}
/* -- generic stream and datagram I/O -------------------------------------- */
ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr, struct timeval *timeout)
const struct sockaddr_storage *addr, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -490,7 +486,7 @@ ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
int ret = send_data(sock, &msg, timeout);
int ret = send_data(sock, &msg, timeout_ms);
if (ret < 0) {
return ret;
} else if (ret != size) {
......@@ -501,7 +497,7 @@ ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
}
ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
struct sockaddr_storage *addr, struct timeval *timeout)
struct sockaddr_storage *addr, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -517,33 +513,33 @@ ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
return recv_data(sock, &msg, true, timeout);
return recv_data(sock, &msg, true, timeout_ms);
}
ssize_t net_dgram_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr)
{
return net_send(sock, buffer, size, addr, NULL);
return net_send(sock, buffer, size, addr, 0);
}
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
return net_recv(sock, buffer, size, NULL, timeout);
return net_recv(sock, buffer, size, NULL, timeout_ms);
}
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms)
{
return net_send(sock, buffer, size, NULL, timeout);
return net_send(sock, buffer, size, NULL, timeout_ms);
}
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
return net_recv(sock, buffer, size, NULL, timeout);
return net_recv(sock, buffer, size, NULL, timeout_ms);
}
/* -- DNS specific I/O ----------------------------------------------------- */
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms)
{
if (sock < 0 || buffer == NULL || size > UINT16_MAX) {
return KNOT_EINVAL;
......@@ -560,7 +556,7 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct ti
msg.msg_iov = iov;
msg.msg_iovlen = 2;
ssize_t ret = send_data(sock, &msg, timeout);
ssize_t ret = send_data(sock, &msg, timeout_ms);
if (ret < 0) {
return ret;
}
......@@ -568,7 +564,7 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct ti
return size; /* Do not count the size prefix. */
}
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -583,7 +579,7 @@ ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval
uint16_t pktsize = 0;
iov.iov_base = &pktsize;
iov.iov_len = sizeof(pktsize);
int ret = recv_data(sock, &msg, false, timeout);
int ret = recv_data(sock, &msg, false, timeout_ms);
if (ret != sizeof(pktsize)) {
return ret;
}
......@@ -600,5 +596,5 @@ ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval
msg.msg_iovlen = 1;
iov.iov_base = buffer;
iov.iov_len = pktsize;
return recv_data(sock, &msg, false, timeout);
return recv_data(sock, &msg, false, timeout_ms);
}
......@@ -19,7 +19,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/time.h>
/*!
* \brief Network interface flags.
......@@ -109,30 +108,31 @@ int net_accept(int sock, struct sockaddr_storage *addr);
*
* The implementation handles partial-writes automatically.
*
* \param[in] sock Socket.
* \param[in] buffer Message buffer.
* \param[in] size Size of the message.
* \param[in] addr Remote address (ignored for SOCK_STREAM).
* \param[in,out] timeout Write timeout (ignored for SOCK_DGRAM).
* \param[in] sock Socket.
* \param[in] buffer Message buffer.
* \param[in] size Size of the message.
* \param[in] addr Remote address (ignored for SOCK_STREAM).
* \param[in] timeout_ms Write timeout in miliseconds (-1 for infinity,
* not valid for SOCK_DGRAM).
*
* \return Number of bytes sent or negative error code.
*/
ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr, struct timeval *timeout);
const struct sockaddr_storage *addr, int timeout_ms);
/*!
* \brief Receive a message from a socket.
*
* \param[in] sock Socket.
* \param[out] buffer Receiving buffer.
* \param[in] size Capacity of the receiving buffer.
* \param[out] addr Remote address (can be NULL).
* \param[in,out] timeout Read timeout.
* \param[in] sock Socket.
* \param[out] buffer Receiving buffer.
* \param[in] size Capacity of the receiving buffer.
* \param[out] addr Remote address (can be NULL).
* \param[in] timeout_ms Read timeout in miliseconds (-1 for infinity).
*
* \return Number of bytes read or negative error code.
*/
ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
struct sockaddr_storage *addr, struct timeval *timeout);
struct sockaddr_storage *addr, int timeout_ms);
/*!
* \brief Send a message on a SOCK_DGRAM socket.
......@@ -147,24 +147,21 @@ ssize_t net_dgram_send(int sock, const uint8_t *buffer, size_t size,
*
* \see net_recv
*/
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Send a message on a SOCK_STREAM socket.
*
* \see net_send
*/
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Receive a message from a SOCK_STREAM socket.
*
* \see net_recv
*/
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Send a DNS message on a TCP socket.
......@@ -175,8 +172,7 @@ ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size,
*
* \see net_send
*/
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Receive a DNS message from a TCP socket.
......@@ -187,5 +183,4 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size,
*
* \see net_recv
*/
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
......@@ -113,20 +113,6 @@ void remote_unbind(int sock)
(void)close(sock);
}
int remote_poll(int sock, const sigset_t *sigmask)
{
/* Wait for events. */
fd_set rfds;
FD_ZERO(&rfds);
if (sock > -1) {
FD_SET(sock, &rfds);
} else {
sock = -1; /* Make sure n == r + 1 == 0 */
}
return pselect(sock + 1, &rfds, NULL, NULL, NULL, sigmask);
}
int remote_recv(int sock, uint8_t *buf, size_t *buflen)
{
int c = tcp_accept(sock);
......@@ -135,7 +121,7 @@ int remote_recv(int sock, uint8_t *buf, size_t *buflen)
}
/* Receive data. */
int n = net_dns_tcp_recv(c, buf, *buflen, NULL);
int n = net_dns_tcp_recv(c, buf, *buflen, -1);
*buflen = n;
if (n <= 0) {
close(c);
......@@ -186,10 +172,10 @@ static int remote_send_chunk(int c, knot_pkt_t *query, const char *d, uint16_t l
rcu_read_lock();
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval timeout = { conf_int(val), 0 };
int timeout = conf_int(val) * 1000;
rcu_read_unlock();
ret = net_dns_tcp_send(c, resp->wire, resp->size, &timeout);
ret = net_dns_tcp_send(c, resp->wire, resp->size, timeout);
failed:
......
......@@ -48,16 +48,6 @@ int remote_bind(const char *path);
*/
void remote_unbind(int sock);
/*!
* \brief Poll new events on RC socket.
*
* \param sock RC interface socket.
* \param sigmask Signal mask to use during blocking waiting.
*
* \return number of polled events or -1 on error.
*/
int remote_poll(int sock, const sigset_t *sigmask);
/*!
* \brief Start a RC connection with remote.
*
......
......@@ -95,8 +95,8 @@ static int dnsproxy_fwd(int state, knot_pkt_t *pkt, struct query_data *qdata, vo
ret = knot_requestor_enqueue(&re, req);
if (ret == KNOT_EOK) {
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval tv = { conf_int(val), 0 };
ret = knot_requestor_exec(&re, &tv);
int timeout = conf_int(val) * 1000;
ret = knot_requestor_exec(&re, timeout);
} else {
knot_request_free(req, re.mm);
}
......
......@@ -267,8 +267,8 @@ static int remote_forward(struct knot_request *request, conf_remote_t *remote)
ret = knot_requestor_enqueue(&re, req);
if (ret == KNOT_EOK) {
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval tv = { conf_int(val), 0 };
ret = knot_requestor_exec(&re, &tv);
int timeout = conf_int(val) * 1000;
ret = knot_requestor_exec(&re, timeout);
} else {
knot_request_free(req, re.mm);
}
......@@ -369,9 +369,9 @@ static void send_update_response(const zone_t *zone, struct knot_request *req)
if (net_is_stream(req->fd)) {
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval timeout = { conf_int(val), 0 };
int timeout = conf_int(val) * 1000;
net_dns_tcp_send(req->fd, req->resp->wire, req->resp->size,
&timeout);
timeout);
} else {
net_dgram_send(req->fd, req->resp->wire, req->resp->size,
&req->remote);
......
......@@ -123,7 +123,7 @@ static void *thread_ep(void *data)
return 0;
}
// Unblock SIGALRM
// Unblock SIGALRM for synchronization
sigset_t mask;
(void)sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
......@@ -458,10 +458,14 @@ static int dt_start_id(dthread_t *thread)
}
// Start thread
sigset_t mask_all, mask_old;
sigfillset(&mask_all);
pthread_sigmask(SIG_SETMASK, &mask_all, &mask_old);
int res = pthread_create(&thread->_thr, /* pthread_t */
&thread->_attr, /* pthread_attr_t */
thread_ep, /* routine: thread_ep */
thread); /* passed object: dthread_t */
pthread_sigmask(SIG_SETMASK, &mask_old, NULL);
// Unlock thread
unlock_thread_rw(thread);
......
......@@ -609,9 +609,8 @@ static int reconfigure_rate_limits(conf_t *conf, server_t *server)
return KNOT_EOK;
}
int server_reconfigure(conf_t *conf, void *data)
int server_reconfigure(conf_t *conf, server_t *server)
{
server_t *server = (server_t *)data;
if (server == NULL) {
return KNOT_EINVAL;
}
......
......@@ -178,7 +178,7 @@ void server_stop(server_t *server);
* \retval KNOT_EINVAL on invalid parameters.
* \retval KNOT_ERROR unspecified error.
*/
int server_reconfigure(conf_t *conf, void *data);
int server_reconfigure(conf_t *conf, server_t *data);
/*!
* \brief Reconfigure zone database.
......
......@@ -115,12 +115,11 @@ static int tcp_handle(tcp_context_t *tcp, int fd,
/* Timeout. */
rcu_read_lock();
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval tmout = { conf_int(val), 0 };
int timeout = conf_int(val) * 1000;
rcu_read_unlock();
/* Receive data. */
struct timeval recv_tmout = tmout;
int ret = net_dns_tcp_recv(fd, rx->iov_base, rx->iov_len, &recv_tmout);
int ret = net_dns_tcp_recv(fd, rx->iov_base, rx->iov_len, timeout);
if (ret <= 0) {
if (ret == KNOT_EAGAIN) {
char addr_str[SOCKADDR_STRLEN] = {0};
......@@ -160,8 +159,7 @@ static int tcp_handle(tcp_context_t *tcp, int fd,
/* Send, if response generation passed and wasn't ignored. */
if (ans->size > 0 && !(state & (KNOT_STATE_FAIL|KNOT_STATE_NOOP))) {
struct timeval send_tmout = tmout;
if (net_dns_tcp_send(fd, ans->wire, ans->size, &send_tmout) != ans->size) {
if (net_dns_tcp_send(fd, ans->wire, ans->size, timeout) != ans->size) {
ret = KNOT_ECONNREFUSED;
break;
}
......
......@@ -157,8 +157,8 @@ static int zone_query_request(knot_pkt_t *query, const conf_remote_t *remote,
ret = knot_requestor_enqueue(&re, req);
if (ret == KNOT_EOK) {
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
struct timeval tv = { conf_int(val), 0 };
ret = knot_requestor_exec(&re, &tv);
int timeout = conf_int(val) * 1000;
ret = knot_requestor_exec(&re, timeout);
} else {
knot_request_free(req, re.mm);
}
......
......@@ -59,12 +59,8 @@ static int request_ensure_connected(struct knot_request *request)
return KNOT_EOK;
}
static int request_send(struct knot_request *request,
const struct timeval *timeout)
static int request_send(struct knot_request *request, int timeout_ms)
{
/* Each request has unique timeout. */
struct timeval tv = *timeout;
/* Initiate non-blocking connect if not connected. */
int ret = request_ensure_connected(request);
if (ret != KNOT_EOK) {
......@@ -78,7 +74,7 @@ static int request_send(struct knot_request *request,
/* Send query. */
if (use_tcp(request)) {
ret = net_dns_tcp_send(request->fd, wire, wire_len, &tv);
ret = net_dns_tcp_send(request->fd, wire, wire_len, timeout_ms);
} else {
ret = net_dgram_send(request->fd, wire, wire_len, NULL);
}
......@@ -89,8 +85,7 @@ static int request_send(struct knot_request *request,
return KNOT_EOK;
}
static int request_recv(struct knot_request *request,
const struct timeval *timeout)
static int request_recv(struct knot_request *request, int timeout_ms)
{
knot_pkt_t *resp = request->resp;
knot_pkt_clear(resp);
......@@ -101,14 +96,11 @@ static int request_recv(struct knot_request *request,
return ret;
}
/* Each request has unique timeout. */
struct timeval tv = *timeout;
/* Receive it */
if (use_tcp(request)) {
ret = net_dns_tcp_recv(request->fd, resp->wire, resp->max_size, &tv);
ret = net_dns_tcp_recv(request->fd, resp->wire, resp->max_size, timeout_ms);
} else {
ret = net_dgram_recv(request->fd, resp->wire, resp->max_size, &tv);
ret = net_dgram_recv(request->fd, resp->wire, resp->max_size, timeout_ms);
}
if (ret <= 0) {
resp->size = 0;
......@@ -271,7 +263,7 @@ int knot_requestor_dequeue(struct knot_requestor *requestor)
}
static int request_io(struct knot_requestor *req, struct knot_request *last,
struct timeval *timeout)
int timeout_ms)
{
int ret = KNOT_EOK;
knot_pkt_t *query = last->query;
......@@ -284,7 +276,7 @@ static int request_io(struct knot_requestor *req, struct knot_request *last,
knot_overlay_produce(&req->overlay, query);
if (req->overlay.state == KNOT_STATE_CONSUME) {
ret = request_send(last, timeout);
ret = request_send(last, timeout_ms);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -294,7 +286,7 @@ static int request_io(struct knot_requestor *req, struct knot_request *last,
/* Data to be read. */
if (req->overlay.state == KNOT_STATE_CONSUME) {
/* Read answer and process it. */
ret = request_recv(last, timeout);
ret = request_recv(last, timeout_ms);
if (ret < 0) {
return ret;
}
......@@ -307,13 +299,13 @@ static int request_io(struct knot_requestor *req, struct knot_request *last,
}
static int exec_request(struct knot_requestor *req, struct knot_request *last,
struct timeval *timeout)
int timeout_ms)
{
int ret = KNOT_EOK;
/* Do I/O until the processing is satisifed or fails. */
while (req->overlay.state & (KNOT_STATE_PRODUCE|KNOT_STATE_CONSUME)) {
ret = request_io(req, last, timeout);
ret = request_io(req, last, timeout_ms);
if (ret != KNOT_EOK) {
knot_overlay_reset(&req->overlay);
return ret;
......@@ -332,8 +324,7 @@ static int exec_request(struct knot_requestor *req, struct knot_request *last,
}
_public_
int knot_requestor_exec(struct knot_requestor *requestor,
struct timeval *timeout)
int knot_requestor_exec(struct knot_requestor *requestor, int timeout_ms)
{
if (knot_requestor_finished(requestor)) {
return KNOT_ENOENT;
......@@ -342,7 +333,7 @@ int knot_requestor_exec(struct knot_requestor *requestor,
/* Execute next request. */
ptrnode_t *node = HEAD(*PENDING(requestor));
struct knot_request *last = node->d;
int ret = exec_request(requestor, last, timeout);
int ret = exec_request(requestor, last, timeout_ms);
/* Remove it from processing. */
knot_requestor_dequeue(requestor);
......
......@@ -135,10 +135,9 @@ int knot_requestor_dequeue(struct knot_requestor *requestor);
/*!
* \brief Execute next pending query (FIFO).
*
* \param requestor Requestor instance.
* \param timeout Processing timeout.
* \param requestor Requestor instance.
* \param timeout_ms Timeout of each operation in miliseconds (-1 for infinity).
*
* \return KNOT_EOK or error
*/
int knot_requestor_exec(struct knot_requestor *requestor,
struct timeval *timeout);
int knot_requestor_exec(struct knot_requestor *requestor, int timeout_ms);
......@@ -44,7 +44,7 @@ static int cmd_remote_print_reply(const knot_rrset_t *rr)
return KNOT_EOK;
}
static int cmd_remote_reply(int c, struct timeval *timeout)
static int cmd_remote_reply(int c, int timeout_ms)
{
knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
if (!pkt) {
......@@ -52,7 +52,7 @@ static int cmd_remote_reply(int c, struct timeval *timeout)
}
/* Read response packet. */
int n = net_dns_tcp_recv(c, pkt->wire, pkt->max_size, timeout);
int n = net_dns_tcp_recv(c, pkt->wire, pkt->max_size, timeout_ms);
if (n <= 0) {
knot_pkt_free(&pkt);
return KNOT_ECONN;
......@@ -132,7 +132,7 @@ int cmd_remote(const char *socket, const char *cmd, uint16_t rrt,
/* Default timeout. */
conf_val_t *val = &conf()->cache.srv_tcp_reply_timeout;
const struct timeval tv_reply = { conf_int(val), 0 };
int timeout = conf_int(val) * 1000;
/* Prepare socket address. */
struct sockaddr_storage addr;
......@@ -154,8 +154,7 @@ int cmd_remote(const char *socket, const char *cmd, uint16_t rrt,
}
/* Send and free packet. */
struct timeval tv = tv_reply;
ret = net_dns_tcp_send(s, pkt->wire, pkt->size, &tv);
ret = net_dns_tcp_send(s, pkt->wire, pkt->size, timeout);
knot_pkt_free(&pkt);
/* Evaluate and wait for reply. */
......@@ -169,8 +168,7 @@ int cmd_remote(const char *socket, const char *cmd, uint16_t rrt,
/* Wait for reply. */
ret = KNOT_EOK;
while (ret == KNOT_EOK) {
tv = tv_reply;
ret = cmd_remote_reply(s, &tv);
ret = cmd_remote_reply(s, timeout);
if (ret != KNOT_EOK) {
if (ret != KNOT_ECONN) {
log_error("remote command reply: %s",
......
......@@ -15,6 +15,7 @@
*/
#include <dirent.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -108,8 +109,23 @@ static int make_daemon(int nochdir, int noclose)
return 0;
}
/*! \brief SIGINT signal handler. */
static void interrupt_handle(int signum)
struct signal {
int signum;
bool handle;
};
/*! \brief Signals used by the server. */
static const struct signal SIGNALS[] = {
{ SIGHUP, true }, /* Reload server. */
{ SIGINT, true }, /* Terminate server .*/
{ SIGTERM, true },
{ SIGALRM, false }, /* Internal thread synchronization. */
{ SIGPIPE, false }, /* Ignored. Some I/O errors. */
{ 0 }
};
/*! \brief Server signal handler. */
static void handle_signal(int signum)
{
switch (signum) {
case SIGHUP:
......@@ -117,6 +133,9 @@ static void interrupt_handle(int signum)
break;
case SIGINT:
case SIGTERM:
if (sig_req_stop) {
abort();
}
sig_req_stop = true;
break;
default:
......@@ -128,23 +147,31 @@ static void interrupt_handle(int signum)
/*! \brief Setup signal handlers and blocking mask. */
static void setup_signals(void)
{
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = interrupt_handle;
static sigset_t block_mask;
(void)sigemptyset(&block_mask);
/* Block all signals. */
static sigset_t all;
sigfillset(&all);
pthread_sigmask(SIG_SETMASK, &all, NULL);