diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-05-08 14:07:32 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-05-08 14:07:32 +0000 |
commit | 6f3830427d22f85373a1069148201a9c69d52a5c (patch) | |
tree | abead1448983aa0f6917c9db543ef1bf840fc090 | |
parent | f491696f4b1320f7e26801ec189f4f874400bc52 (diff) | |
download | ruby-6f3830427d22f85373a1069148201a9c69d52a5c.tar.gz |
* ext/io/console/console.c (ttymode): save dupped file descriptors
and restore tty modes using them, so that original modes can be
restored even if orignal fds are closed. [ruby-dev:41225]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27676 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | ext/io/console/console.c | 33 | ||||
-rw-r--r-- | ext/io/console/extconf.rb | 1 |
3 files changed, 37 insertions, 3 deletions
@@ -1,3 +1,9 @@ +Sat May 8 23:07:28 2010 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * ext/io/console/console.c (ttymode): save dupped file descriptors + and restore tty modes using them, so that original modes can be + restored even if orignal fds are closed. [ruby-dev:41225] + Sat May 8 13:48:31 2010 Marc-Andre Lafortune <ruby-core@marc-andre.ca> * array.c (rb_ary_fetch, rb_ary_splice, rb_ary_store): Improve diff --git a/ext/io/console/console.c b/ext/io/console/console.c index a521312e47..764f632027 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -173,6 +173,23 @@ get_write_fd(const rb_io_t *fptr) #define FD_PER_IO 2 +#if defined HAVE_DUP3 +#define dup_private(fd) dup3((fd), -1, O_CLOEXEC) +#elif defined F_DUPFD_CLOEXEC +#define dup_private(fd) fcntl((fd), F_DUPFD_CLOEXEC) +#elif defined O_CLOEXEC +static inline int +dup_private(int fd) +{ + fd = dup(fd); + if (fd != -1) fcntl(fd, F_SETFD, O_CLOEXEC); + return fd; +} +#define dup_private(fd) dup_private(fd) +#else +#define dup_private(fd) dup(fd) +#endif + static VALUE ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) { @@ -180,6 +197,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) int status = -1; int error = 0; int fd[FD_PER_IO]; + int tmpfd, dupped = 0; conmode t[FD_PER_IO]; VALUE result = Qnil; @@ -187,6 +205,10 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) fd[0] = GetReadFD(fptr); if (fd[0] != -1) { if (set_ttymode(fd[0], t+0, setter)) { + if ((tmpfd = dup_private(fd[0])) != -1) { + fd[0] = tmpfd; + dupped |= 1 << 0; + } status = 0; } else { @@ -197,6 +219,10 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) fd[1] = GetWriteFD(fptr); if (fd[1] != -1 && fd[1] != fd[0]) { if (set_ttymode(fd[1], t+1, setter)) { + if ((tmpfd = dup_private(fd[1])) != -1) { + fd[1] = tmpfd; + dupped |= 1 << 1; + } status = 0; } else { @@ -207,18 +233,19 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) if (status == 0) { result = rb_protect(func, io, &status); } - GetOpenFile(io, fptr); - if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) { + if (fd[0] != -1) { if (!setattr(fd[0], t+0)) { error = errno; status = -1; } + if (dupped & (1 << 0)) close(fd[0]); } - if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(fptr)) { + if (fd[1] != -1 && fd[1] != fd[0]) { if (!setattr(fd[1], t+1)) { error = errno; status = -1; } + if (dupped & (1 << 1)) close(fd[1]); } if (status) { if (status == -1) { diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb index ac861848fa..57cd7ad87f 100644 --- a/ext/io/console/extconf.rb +++ b/ext/io/console/extconf.rb @@ -14,6 +14,7 @@ else end have_header("sys/ioctl.h") have_func("rb_io_get_write_io", "ruby/io.h") +have_func("dup3", "unistd.h") if ok create_makefile("io/console") end |