From bfb99704ad5c0476f401be57ee2403652a0a8af4 Mon Sep 17 00:00:00 2001 From: Alberto Leiva Popper Date: Mon, 5 Jul 2021 10:15:45 -0500 Subject: [PATCH] RTR Server: Clear O_NONBLOCK on client sockets It seems that client sockets inherit the O_NONBLOCK flag from the server socket on some implementations of `accept()`. We definitely don't want O_NONBLOCK on client sockets, so clear it explicitely every time. --- src/rtr/rtr.c | 57 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/rtr/rtr.c b/src/rtr/rtr.c index 6855c50e..4161f963 100644 --- a/src/rtr/rtr.c +++ b/src/rtr/rtr.c @@ -95,6 +95,34 @@ init_addrinfo(char const *hostname, char const *service, return 0; } +static int +set_nonblock(int fd, bool value) +{ + int flags; + int error; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) { + error = errno; + pr_op_errno(error, "fcntl() to get flags failed"); + return error; + } + + /* Non-block to allow listening on all server sockets */ + if (value) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if (fcntl(fd, F_SETFL, flags) == -1) { + error = errno; + pr_op_errno(error, "fcntl() to set flags failed"); + return error; + } + + return 0; +} + /* * Creates the socket that will stay put and wait for new connections started * from the clients. @@ -105,7 +133,6 @@ create_server_socket(char const *hostname, char const *service, int *result) struct addrinfo *addrs; struct addrinfo *addr; unsigned long port; - int flags; int reuse; int fd; int error; @@ -130,18 +157,8 @@ create_server_socket(char const *hostname, char const *service, int *result) continue; } - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - pr_op_errno(errno, "fcntl() to get flags failed"); - close(fd); - continue; - } - /* Non-block to allow listening on all server sockets */ - flags |= O_NONBLOCK; - - if (fcntl(fd, F_SETFL, flags) == -1) { - pr_op_errno(errno, "fcntl() to set flags failed"); + if (set_nonblock(fd, true) != 0) { close(fd); continue; } @@ -501,9 +518,9 @@ handle_client_connections(void *arg) pr_op_debug("Waiting for client connections at server..."); do { - /* Look for connections every .2 seconds*/ - select_time.tv_sec = 0; - select_time.tv_usec = 200000; + /* Query server_stop every second. */ + select_time.tv_sec = 1; + select_time.tv_usec = 0; /* Am I still alive? */ if (server_stop) @@ -554,6 +571,16 @@ handle_client_connections(void *arg) * So don't interrupt the thread when this happens. */ + /* + * On some systems, O_NONBLOCK is inherited. + * We very much don't want O_NONBLOCK on the client + * socket. + */ + if (set_nonblock(client_fd, false) != 0) { + close(client_fd); + continue; + } + param = malloc(sizeof(struct thread_param)); if (param == NULL) { /* No error PDU on memory allocation. */ -- 2.47.2