diff options
author | Eric Wong <normalperson@yhbt.net> | 2010-09-26 02:46:51 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2010-09-26 02:53:04 +0000 |
commit | a226d237666728ea9242f6079b2c76528d53cdb2 (patch) | |
tree | 44a04f643cecf78dc6ffaae2979732569f63143a | |
parent | 3ca3a23d3e68f62af6d57cf22825b2751c226fff (diff) | |
download | sleepy_penguin-a226d237666728ea9242f6079b2c76528d53cdb2.tar.gz |
There can be ways (in the future) where supporting Epoll#dup/Epoll#clone can proveuseful, so continue to support them until proven otherwise.
-rw-r--r-- | ext/sleepy_penguin/epoll.c | 19 | ||||
-rw-r--r-- | test/test_epoll.rb | 4 |
2 files changed, 20 insertions, 3 deletions
diff --git a/ext/sleepy_penguin/epoll.c b/ext/sleepy_penguin/epoll.c index 83f1568..3540c51 100644 --- a/ext/sleepy_penguin/epoll.c +++ b/ext/sleepy_penguin/epoll.c @@ -112,6 +112,7 @@ static VALUE alloc(VALUE klass) ep->fd = -1; ep->io = Qnil; ep->capa = step; + ep->flags = EPOLL_CLOEXEC; ep->events = xmalloc(sizeof(struct epoll_event) * ep->capa); return self; @@ -448,6 +449,19 @@ static VALUE epclosed(VALUE self) return ep->fd == -1 ? Qtrue : Qfalse; } +static int cloexec_dup(struct rb_epoll *ep) +{ +#ifdef F_DUPFD_CLOEXEC + int flags = ep->flags & EPOLL_CLOEXEC ? F_DUPFD_CLOEXEC : F_DUPFD; + int fd = fcntl(ep->fd, flags, 0); +#else + int fd = dup(ep->fd); + if (fd >= 0) + (void)fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + return fd; +} + static VALUE init_copy(VALUE copy, VALUE orig) { struct rb_epoll *a = ep_get(orig); @@ -457,11 +471,12 @@ static VALUE init_copy(VALUE copy, VALUE orig) NIL_P(b->io) && "Ruby broken?"); ep_check(a); - b->fd = dup(a->fd); + b->flags = a->flags; + b->fd = cloexec_dup(a); if (b->fd == -1) { if (errno == ENFILE || errno == EMFILE) { rb_gc(); - b->fd = dup(a->fd); + b->fd = cloexec_dup(a); } if (b->fd == -1) rb_sys_fail("dup"); diff --git a/test/test_epoll.rb b/test/test_epoll.rb index 0acf08d..50daf3e 100644 --- a/test/test_epoll.rb +++ b/test/test_epoll.rb @@ -31,6 +31,8 @@ class TestEpoll < Test::Unit::TestCase fork { @ep.add(@rd, Epoll::IN); exit!(0) } fork { @ep.set(@rd, Epoll::IN); exit!(0) } fork { @ep.to_io; exit!(0) } + fork { @ep.dup; exit!(0) } + fork { @ep.clone; exit!(0) } fork { @ep.close; exit!(0) } fork { @ep.closed?; exit!(0) } fork { @@ -202,7 +204,7 @@ class TestEpoll < Test::Unit::TestCase def test_dup tmp = [] - clone = @ep.clone + clone = @ep.dup assert @ep.to_io.fileno != clone.to_io.fileno clone.add @wr, Epoll::OUT @ep.wait(nil, 0) { |flags, obj| tmp << [ flags, obj ] } |