diff --git a/src/unix/linux/syscalls.c b/src/unix/linux/syscalls.c index 5eb826b7..cbf2bbbd 100644 --- a/src/unix/linux/syscalls.c +++ b/src/unix/linux/syscalls.c @@ -152,13 +152,25 @@ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { #if __i386__ - unsigned long args[] = { - (unsigned long) fd, - (unsigned long) addr, - (unsigned long) addrlen, - (unsigned long) flags - }; - return syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); + unsigned long args[4]; + int r; + + args[0] = (unsigned long) fd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) addrlen; + args[3] = (unsigned long) flags; + + r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); + + /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does + * a bad flags argument. Try to distinguish between the two cases. + */ + if (r == -1) + if (errno == EINVAL) + if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0) + errno = ENOSYS; + + return r; #elif __NR_accept4 return syscall(__NR_accept4, fd, addr, addrlen, flags); #else