From: Miroslav Lichvar Date: Tue, 23 Jul 2019 15:26:29 +0000 (+0200) Subject: socket: add support for socket() flags X-Git-Tag: 4.0-pre1~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27fd7519150f36a12f6c91e59b4b3615377f0532;p=thirdparty%2Fchrony.git socket: add support for socket() flags On start, check if the SOCK_CLOEXEC and SOCK_NONBLOCK flags are supported in the socket() call and use them instead of fcntl() in order to reduce the number of system calls required to send a client request. --- diff --git a/socket.c b/socket.c index 7d28d7a1..0c0409d9 100644 --- a/socket.c +++ b/socket.c @@ -82,6 +82,9 @@ struct MessageHeader { static int initialised; +/* Flags supported by socket() */ +static int socket_flags; + /* Arrays of Message and MessageHeader */ static ARR_Instance recv_messages; static ARR_Instance recv_headers; @@ -140,12 +143,35 @@ domain_to_string(int domain) /* ================================================== */ +static int +check_socket_flag(int sock_flag, int fd_flag, int fs_flag) +{ + int sock_fd, fd_flags, fs_flags; + + sock_fd = socket(AF_INET, SOCK_DGRAM | sock_flag, 0); + if (sock_fd < 0) + return 0; + + fd_flags = fcntl(sock_fd, F_GETFD); + fs_flags = fcntl(sock_fd, F_GETFL); + + close(sock_fd); + + if (fd_flags == -1 || (fd_flags & fd_flag) != fd_flag || + fs_flags == -1 || (fs_flags & fs_flag) != fs_flag) + return 0; + + return 1; +} + +/* ================================================== */ + static int open_socket(int domain, int type, int flags) { int sock_fd; - sock_fd = socket(domain, type, 0); + sock_fd = socket(domain, type | socket_flags, 0); if (sock_fd < 0) { DEBUG_LOG("Could not open %s socket : %s", @@ -154,14 +180,22 @@ open_socket(int domain, int type, int flags) } /* Close the socket automatically on exec */ - if (!UTI_FdSetCloexec(sock_fd)) { + if ( +#ifdef SOCK_CLOEXEC + (socket_flags & SOCK_CLOEXEC) == 0 && +#endif + !UTI_FdSetCloexec(sock_fd)) { DEBUG_LOG("Could not set O_CLOEXEC : %s", strerror(errno)); close(sock_fd); return INVALID_SOCK_FD; } /* Enable non-blocking mode */ - if (fcntl(sock_fd, F_SETFL, O_NONBLOCK)) { + if ( +#ifdef SOCK_NONBLOCK + (socket_flags & SOCK_NONBLOCK) == 0 && +#endif + fcntl(sock_fd, F_SETFL, O_NONBLOCK)) { DEBUG_LOG("Could not set O_NONBLOCK : %s", strerror(errno)); close(sock_fd); return INVALID_SOCK_FD; @@ -943,6 +977,16 @@ SCK_Initialise(void) priv_bind_function = NULL; + socket_flags = 0; +#ifdef SOCK_CLOEXEC + if (check_socket_flag(SOCK_CLOEXEC, FD_CLOEXEC, 0)) + socket_flags |= SOCK_CLOEXEC; +#endif +#ifdef SOCK_NONBLOCK + if (check_socket_flag(SOCK_NONBLOCK, 0, O_NONBLOCK)) + socket_flags |= SOCK_NONBLOCK; +#endif + initialised = 1; }