diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-10-31 21:01:18 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-10-31 21:01:18 +0000 |
commit | ee5ae134dd1c0037a36b2e0c78cd4e326d002c3a (patch) | |
tree | 1664585f391e2e97f0f58faf082b576028c00e6f /ext/socket/socket.c | |
parent | 17f068b6a676892082b0e8defefbbb8c8297902c (diff) |
* ext/socket/socket.c (rsock_socketpair): use SOCK_CLOEXEC if
available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33593 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket/socket.c')
-rw-r--r-- | ext/socket/socket.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 31346a0295..aa1749bb4a 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -78,14 +78,35 @@ pair_yield(VALUE pair) #if defined HAVE_SOCKETPAIR static int -rsock_socketpair(int domain, int type, int protocol, int sv[2]) +rsock_socketpair(int domain, int type0, int protocol, int sv[2]) { - int ret; + int ret, type; + +#ifdef SOCK_CLOEXEC + static int try_sock_cloexec = 1; + if (try_sock_cloexec) + type = type0|SOCK_CLOEXEC; + else + type = type0; + retry_without_sock_cloexec:; +#else + type = type0; +#endif ret = socketpair(domain, type, protocol, sv); - if (ret < 0 && (errno == EMFILE || errno == ENFILE)) { - rb_gc(); - ret = socketpair(domain, type, protocol, sv); + if (ret < 0) { +#ifdef SOCK_CLOEXEC + /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ + if (try_sock_cloexec && errno == EINVAL) { + try_sock_cloexec = 0; + type = type0; + goto retry_without_sock_cloexec; + } +#endif + if (errno == EMFILE || errno == ENFILE) { + rb_gc(); + ret = socketpair(domain, type, protocol, sv); + } } return ret; |