summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
Diffstat (limited to 'ext/socket')
-rw-r--r--ext/socket/ancdata.c6
-rw-r--r--ext/socket/init.c148
-rw-r--r--ext/socket/rubysocket.h7
-rw-r--r--ext/socket/socket.c98
-rw-r--r--ext/socket/unixsocket.c6
5 files changed, 66 insertions, 199 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 84463af061..e0fc247f8c 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -2,7 +2,6 @@
#include <time.h>
-int rsock_cmsg_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
static VALUE sym_wait_readable, sym_wait_writable;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
@@ -1429,10 +1428,7 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
if (fstat(fd, &stbuf) == -1)
rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS");
rb_update_max_fd(fd);
- if (rsock_cmsg_cloexec_state < 0)
- rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd);
- if (rsock_cmsg_cloexec_state == 0 || fd <= 2)
- rb_maygvl_fd_fix_cloexec(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
if (S_ISSOCK(stbuf.st_mode))
io = rsock_init_sock(rb_obj_alloc(rb_cSocket), fd);
else
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 6d17ecfb4e..0604e8b72f 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -408,84 +408,30 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
}
#endif /* MSG_DONTWAIT_RELIABLE */
-/* returns true if SOCK_CLOEXEC is supported */
-int rsock_detect_cloexec(int fd)
+static int
+rsock_socket0(int domain, int type, int proto)
{
#ifdef SOCK_CLOEXEC
- int flags = fcntl(fd, F_GETFD);
-
- if (flags == -1)
- rb_bug("rsock_detect_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
+ type |= SOCK_CLOEXEC;
+#endif
- if (flags & FD_CLOEXEC)
- return 1;
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
#endif
- return 0;
-}
-#ifdef SOCK_CLOEXEC
-static int
-rsock_socket0(int domain, int type, int proto)
-{
- int ret;
- static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
-
- if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */
- ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
- if (ret >= 0) {
- if (ret <= 2)
- goto fix_cloexec;
- goto update_max_fd;
- }
- }
- else if (cloexec_state < 0) { /* usually runs once only for detection */
- ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
- if (ret >= 0) {
- cloexec_state = rsock_detect_cloexec(ret);
- if (cloexec_state == 0 || ret <= 2)
- goto fix_cloexec;
- goto update_max_fd;
- }
- else if (ret == -1 && errno == EINVAL) {
- /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
- ret = socket(domain, type, proto);
- if (ret != -1) {
- cloexec_state = 0;
- /* fall through to fix_cloexec */
- }
- }
- }
- else { /* cloexec_state == 0 */
- ret = socket(domain, type, proto);
- }
- if (ret == -1)
+ int result = socket(domain, type, proto);
+
+ if (result == -1)
return -1;
-fix_cloexec:
- rb_maygvl_fd_fix_cloexec(ret);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(ret);
- }
-update_max_fd:
- rb_update_max_fd(ret);
- return ret;
-}
-#else /* !SOCK_CLOEXEC */
-static int
-rsock_socket0(int domain, int type, int proto)
-{
- int ret = socket(domain, type, proto);
+ rb_fd_fix_cloexec(result);
- if (ret == -1)
- return -1;
- rb_fd_fix_cloexec(ret);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(ret);
- }
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(result);
+#endif
- return ret;
+ return result;
}
-#endif /* !SOCK_CLOEXEC */
int
rsock_socket(int domain, int type, int proto)
@@ -637,6 +583,10 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
void
rsock_make_fd_nonblock(int fd)
{
+#ifdef _WIN32
+ return;
+#endif
+
int flags;
#ifdef F_GETFL
flags = fcntl(fd, F_GETFL);
@@ -653,56 +603,34 @@ rsock_make_fd_nonblock(int fd)
}
static int
-cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len,
- int nonblock)
+cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{
- int ret;
socklen_t len0 = 0;
-#ifdef HAVE_ACCEPT4
- static int try_accept4 = 1;
-#endif
- if (RSOCK_NONBLOCK_DEFAULT) {
- nonblock = 1;
- }
if (address_len) len0 = *address_len;
+
#ifdef HAVE_ACCEPT4
- if (try_accept4) {
- int flags = 0;
-#ifdef SOCK_CLOEXEC
- flags |= SOCK_CLOEXEC;
-#endif
+ int flags = SOCK_CLOEXEC;
+
#ifdef SOCK_NONBLOCK
- if (nonblock) {
- flags |= SOCK_NONBLOCK;
- }
+ flags |= SOCK_NONBLOCK;
#endif
- ret = accept4(socket, address, address_len, flags);
- /* accept4 is available since Linux 2.6.28, glibc 2.10. */
- if (ret != -1) {
- if (ret <= 2)
- rb_maygvl_fd_fix_cloexec(ret);
+
+ int result = accept4(socket, address, address_len, flags);
+ if (result == -1) return -1;
+
#ifndef SOCK_NONBLOCK
- if (nonblock) {
- rsock_make_fd_nonblock(ret);
- }
+ rsock_make_fd_nonblock(result);
#endif
- if (address_len && len0 < *address_len) *address_len = len0;
- return ret;
- }
- if (errno != ENOSYS) {
- return -1;
- }
- try_accept4 = 0;
- }
+#else
+ int result = accept(socket, address, address_len);
+ if (result == -1) return -1;
+
+ rb_maygvl_fd_fix_cloexec(result);
+ rsock_make_fd_nonblock(result);
#endif
- ret = accept(socket, address, address_len);
- if (ret == -1) return -1;
+
if (address_len && len0 < *address_len) *address_len = len0;
- rb_maygvl_fd_fix_cloexec(ret);
- if (nonblock) {
- rsock_make_fd_nonblock(ret);
- }
- return ret;
+ return result;
}
VALUE
@@ -712,7 +640,7 @@ rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
int fd2;
rb_io_set_nonblock(fptr);
- fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1);
+ fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len);
if (fd2 < 0) {
int e = errno;
switch (e) {
@@ -744,7 +672,7 @@ static VALUE
accept_blocking(void *data)
{
struct accept_arg *arg = data;
- return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len, 0);
+ return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len);
}
VALUE
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index 867e215273..fcea2a5a05 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -36,13 +36,7 @@
# if defined(_MSC_VER)
# undef HAVE_TYPE_STRUCT_SOCKADDR_DL
# endif
-/*
- * FIXME: failures if we make nonblocking the default
- * [ruby-core:89973] [ruby-core:89976] [ruby-core:89977] [Bug #14968]
- */
-# define RSOCK_NONBLOCK_DEFAULT (0)
#else
-# define RSOCK_NONBLOCK_DEFAULT (0)
# include <sys/socket.h>
# include <netinet/in.h>
# ifdef HAVE_NETINET_IN_SYSTM_H
@@ -260,7 +254,6 @@ typedef union {
#define INET_SOCKS 2
extern int rsock_do_not_reverse_lookup;
-extern int rsock_cmsg_cloexec_state;
#define FMODE_NOREVLOOKUP 0x100
/* common socket families only */
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index bfeb30340c..e4504620fb 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -168,93 +168,47 @@ pair_yield(VALUE pair)
#endif
#if defined HAVE_SOCKETPAIR
-
-#ifdef SOCK_CLOEXEC
static int
-rsock_socketpair0(int domain, int type, int protocol, int sv[2])
+rsock_socketpair0(int domain, int type, int protocol, int descriptors[2])
{
- int ret;
- static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
- static const int default_flags = SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
- if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */
- ret = socketpair(domain, type|default_flags, protocol, sv);
- if (ret == 0 && (sv[0] <= 2 || sv[1] <= 2)) {
- goto fix_cloexec; /* highly unlikely */
- }
- goto update_max_fd;
- }
- else if (cloexec_state < 0) { /* usually runs once only for detection */
- ret = socketpair(domain, type|default_flags, protocol, sv);
- if (ret == 0) {
- cloexec_state = rsock_detect_cloexec(sv[0]);
- if ((cloexec_state == 0) || (sv[0] <= 2 || sv[1] <= 2))
- goto fix_cloexec;
- goto update_max_fd;
- }
- else if (ret == -1 && errno == EINVAL) {
- /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
- ret = socketpair(domain, type, protocol, sv);
- if (ret != -1) {
- /* The reason of EINVAL may be other than SOCK_CLOEXEC.
- * So disable SOCK_CLOEXEC only if socketpair() succeeds without SOCK_CLOEXEC.
- * Ex. Socket.pair(:UNIX, 0xff) fails with EINVAL.
- */
- cloexec_state = 0;
- }
- }
- }
- else { /* cloexec_state == 0 */
- ret = socketpair(domain, type, protocol, sv);
- }
- if (ret == -1) {
- return -1;
- }
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
+#endif
-fix_cloexec:
- rb_maygvl_fd_fix_cloexec(sv[0]);
- rb_maygvl_fd_fix_cloexec(sv[1]);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(sv[0]);
- rsock_make_fd_nonblock(sv[1]);
- }
+ int result = socketpair(domain, type, protocol, descriptors);
-update_max_fd:
- rb_update_max_fd(sv[0]);
- rb_update_max_fd(sv[1]);
+ if (result == -1)
+ return -1;
- return ret;
-}
-#else /* !SOCK_CLOEXEC */
-static int
-rsock_socketpair0(int domain, int type, int protocol, int sv[2])
-{
- int ret = socketpair(domain, type, protocol, sv);
+#ifndef SOCK_CLOEXEC
+ rb_fd_fix_cloexec(descriptors[0]);
+ rb_fd_fix_cloexec(descriptors[1]);
+#endif
- if (ret == -1)
- return -1;
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(descriptors[0]);
+ rsock_make_fd_nonblock(descriptors[1]);
+#endif
- rb_fd_fix_cloexec(sv[0]);
- rb_fd_fix_cloexec(sv[1]);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(sv[0]);
- rsock_make_fd_nonblock(sv[1]);
- }
- return ret;
+ return result;
}
-#endif /* !SOCK_CLOEXEC */
static int
-rsock_socketpair(int domain, int type, int protocol, int sv[2])
+rsock_socketpair(int domain, int type, int protocol, int descriptors[2])
{
- int ret;
+ int result;
+
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
- ret = rsock_socketpair0(domain, type, protocol, sv);
- if (ret < 0 && rb_gc_for_fd(errno)) {
- ret = rsock_socketpair0(domain, type, protocol, sv);
+ if (result < 0 && rb_gc_for_fd(errno)) {
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
}
- return ret;
+ return result;
}
/*
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
index 0c3a01d21e..53a50958ed 100644
--- a/ext/socket/unixsocket.c
+++ b/ext/socket/unixsocket.c
@@ -455,11 +455,7 @@ retry:
#endif
rb_update_max_fd(fd);
-
- if (rsock_cmsg_cloexec_state < 0)
- rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd);
- if (rsock_cmsg_cloexec_state == 0 || fd <= 2)
- rb_maygvl_fd_fix_cloexec(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
if (klass == Qnil)
return INT2FIX(fd);