ruby-changes:32561
From: akr <ko1@a...>
Date: Sat, 18 Jan 2014 22:28:39 +0900 (JST)
Subject: [ruby-changes:32561] akr:r44640 (trunk): * io.c: Test O_CLOEXEC only once.
akr 2014-01-18 22:28:35 +0900 (Sat, 18 Jan 2014) New Revision: 44640 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44640 Log: * io.c: Test O_CLOEXEC only once. Patch by Eric Wong. [ruby-core:59419] [Feature #9328] Modified files: trunk/ChangeLog trunk/io.c Index: ChangeLog =================================================================== --- ChangeLog (revision 44639) +++ ChangeLog (revision 44640) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Jan 18 22:25:53 2014 Tanaka Akira <akr@f...> + + * io.c: Test O_CLOEXEC only once. + Patch by Eric Wong. [ruby-core:59419] [Feature #9328] + Sat Jan 18 21:24:49 2014 Tanaka Akira <akr@f...> * ext/socket/option.c: IP_MULTICAST_LOOP and IP_MULTICAST_TTL socket Index: io.c =================================================================== --- io.c (revision 44639) +++ io.c (revision 44640) @@ -228,10 +228,29 @@ rb_fd_fix_cloexec(int fd) https://github.com/ruby/ruby/blob/trunk/io.c#L228 rb_update_max_fd(fd); } +/* this is only called once */ +static int +rb_fix_detect_o_cloexec(int fd) +{ +#ifdef O_CLOEXEC + int flags = fcntl(fd, F_GETFD); + + if (flags == -1) + rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno)); + + if (flags & FD_CLOEXEC) + return 1; +#endif /* fall through if O_CLOEXEC does not work: */ + rb_maygvl_fd_fix_cloexec(fd); + return 0; +} + int rb_cloexec_open(const char *pathname, int flags, mode_t mode) { int ret; + static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ + #ifdef O_CLOEXEC /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */ flags |= O_CLOEXEC; @@ -240,7 +259,13 @@ rb_cloexec_open(const char *pathname, in https://github.com/ruby/ruby/blob/trunk/io.c#L259 #endif ret = open(pathname, flags, mode); if (ret == -1) return -1; - rb_maygvl_fd_fix_cloexec(ret); + if (ret <= 2 || o_cloexec_state == 0) { + rb_maygvl_fd_fix_cloexec(ret); + } else if (o_cloexec_state > 0) { + return ret; + } else { + o_cloexec_state = rb_fix_detect_o_cloexec(ret); + } return ret; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/