|
|
|
@ -20,6 +20,9 @@
|
|
|
|
|
#ifdef SOCK_CLOEXEC |
|
|
|
|
static int use_sock_cloexec; |
|
|
|
|
#endif |
|
|
|
|
#ifdef SOCK_NONBLOCK |
|
|
|
|
static int use_sock_nonblock; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
int fdevent_config(server *srv) { |
|
|
|
|
static const struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = |
|
|
|
@ -157,9 +160,15 @@ fdevents *fdevent_init(server *srv) {
|
|
|
|
|
/* Test if SOCK_CLOEXEC is supported by kernel.
|
|
|
|
|
* Linux kernels < 2.6.27 might return EINVAL if SOCK_CLOEXEC used |
|
|
|
|
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=529929
|
|
|
|
|
* http://www.linksysinfo.org/index.php?threads/lighttpd-no-longer-starts-toastman-1-28-0510-7.73132/ */
|
|
|
|
|
int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); |
|
|
|
|
* http://www.linksysinfo.org/index.php?threads/lighttpd-no-longer-starts-toastman-1-28-0510-7.73132/
|
|
|
|
|
* Test if SOCK_NONBLOCK is ignored by kernel on sockets. |
|
|
|
|
* (reported on Android running a custom ROM) |
|
|
|
|
* https://redmine.lighttpd.net/issues/2883
|
|
|
|
|
*/ |
|
|
|
|
int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); |
|
|
|
|
if (fd >= 0) { |
|
|
|
|
int flags = fcntl(fd, F_GETFL, 0); |
|
|
|
|
use_sock_nonblock = (-1 != flags && (flags & O_NONBLOCK)); |
|
|
|
|
use_sock_cloexec = 1; |
|
|
|
|
close(fd); |
|
|
|
|
} |
|
|
|
@ -477,7 +486,7 @@ int fdevent_fcntl_set_nb_cloexec(fdevents *ev, int fd) {
|
|
|
|
|
|
|
|
|
|
int fdevent_fcntl_set_nb_cloexec_sock(fdevents *ev, int fd) { |
|
|
|
|
#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) |
|
|
|
|
if (use_sock_cloexec) |
|
|
|
|
if (use_sock_cloexec && use_sock_nonblock) |
|
|
|
|
return 0; |
|
|
|
|
#endif |
|
|
|
|
return fdevent_fcntl_set_nb_cloexec(ev, fd); |
|
|
|
@ -500,7 +509,7 @@ int fdevent_socket_cloexec(int domain, int type, int protocol) {
|
|
|
|
|
int fdevent_socket_nb_cloexec(int domain, int type, int protocol) { |
|
|
|
|
int fd; |
|
|
|
|
#ifdef SOCK_CLOEXEC |
|
|
|
|
if (use_sock_cloexec) |
|
|
|
|
if (use_sock_cloexec && use_sock_nonblock) |
|
|
|
|
return socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol); |
|
|
|
|
#endif |
|
|
|
|
if (-1 != (fd = socket(domain, type, protocol))) { |
|
|
|
@ -569,7 +578,14 @@ int fdevent_accept_listenfd(int listenfd, struct sockaddr *addr, size_t *addrlen
|
|
|
|
|
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)) { |
|
|
|
|
if (fd >= 0) { |
|
|
|
|
if (!use_sock_nonblock) { |
|
|
|
|
if (0 != fdevent_fcntl_set_nb(NULL, fd)) { |
|
|
|
|
close(fd); |
|
|
|
|
fd = -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (errno == ENOSYS || errno == ENOTSUP) { |
|
|
|
|
fd = accept(listenfd, addr, &len); |
|
|
|
|
sock_cloexec = 0; |
|
|
|
|
} |
|
|
|
|