diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-01-18 13:28:35 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-01-18 13:28:35 +0000 |
commit | f962eba5f430200d42def2756ac4af2512acdfce (patch) | |
tree | 31cd5fa07ba6e31693ceb46f7d2121997cab20c4 /io.c | |
parent | 7efaa4f5d07ebc100a1bbfb34bfd9ea23a4ac2f2 (diff) | |
download | ruby-f962eba5f430200d42def2756ac4af2512acdfce.tar.gz |
* io.c: Test O_CLOEXEC only once.
Patch by Eric Wong. [ruby-core:59419] [Feature #9328]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 27 |
1 files changed, 26 insertions, 1 deletions
@@ -228,10 +228,29 @@ rb_fd_fix_cloexec(int fd) 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, int flags, mode_t mode) #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; } |