[core] check if SOCK_NONBLOCK is ignored (fixes #2883)
x-ref: "fdevent_init should check if SOCK_NONBLOCK works" https://redmine.lighttpd.net/issues/2883personal/stbuehler/fix-fdevent
parent
3efaff973f
commit
78024584bb
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue