[core] fdevent_accept_listenfd() nonblock cloexec

fdevent_accept_listenfd() now always returns fd O_NONBLOCK O_CLOEXEC
for consistency, rather than setting elsewhere in connection_accepted()

Handle older Linux 2.6 kernels which might have accept4() in glibc,
but return ENOSYS, as accept4() was not added until Linux kernel 2.6.28.
personal/stbuehler/fix-fdevent
Glenn Strauss 2018-03-25 00:57:38 -04:00
parent 26fb8d3ee6
commit d400f8aac5
2 changed files with 20 additions and 9 deletions

View File

@ -1116,11 +1116,6 @@ connection *connection_accepted(server *srv, server_socket *srv_socket, sock_add
con->conditional_is_valid[COMP_SERVER_SOCKET] = 1;
con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1;
if (-1 == fdevent_fcntl_set_nb_cloexec_sock(srv->ev, con->fd)) {
log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
connection_close(srv, con);
return NULL;
}
buffer_copy_string_len(con->proto, CONST_STR_LEN("http"));
if (HANDLER_GO_ON != plugins_call_handle_connection_accept(srv, con)) {
connection_close(srv, con);

View File

@ -563,17 +563,33 @@ int fdevent_accept_listenfd(int listenfd, struct sockaddr *addr, size_t *addrlen
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
#if defined(__NetBSD__)
const int sock_cloexec = 1;
fd = paccept(listenfd, addr, &len, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);
#else
fd = (use_sock_cloexec)
? accept4(listenfd, addr, &len, SOCK_CLOEXEC | SOCK_NONBLOCK)
: accept(listenfd, addr, &len);
int sock_cloexec = use_sock_cloexec;
if (sock_cloexec) {
fd = accept4(listenfd, addr, &len, SOCK_CLOEXEC | SOCK_NONBLOCK);
if (fd < 0 && (errno == ENOSYS || errno == ENOTSUP)) {
fd = accept(listenfd, addr, &len);
sock_cloexec = 0;
}
}
else {
fd = accept(listenfd, addr, &len);
}
#endif
#else
const int sock_cloexec = 0;
fd = accept(listenfd, addr, &len);
#endif
if (fd >= 0) *addrlen = (size_t)len;
if (fd >= 0) {
*addrlen = (size_t)len;
if (!sock_cloexec && 0 != fdevent_fcntl_set_nb_cloexec(NULL, fd)) {
close(fd);
fd = -1;
}
}
return fd;
}