diff --git a/ChangeLog b/ChangeLog index b6828bbc84..80fae2c9ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Nov 1 05:59:41 2011 Tanaka Akira + + * ext/socket/socket.c (rsock_socketpair): use SOCK_CLOEXEC if + available. + Tue Nov 1 02:56:17 2011 NAKAMURA Usaku * ruby.c (load_file_internal): convert the encoding of load path if 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;