From f242e17f9b011e1e78cf64eabf1d39d67a7ca274 Mon Sep 17 00:00:00 2001 From: ngoto Date: Thu, 16 Jul 2015 13:06:13 +0000 Subject: [PATCH] * process.c (redirect_dup2): when the new FD of dup2() coflicts with one of the timer thread FDs, the internal FD is diverted. [Bug #11336] [ruby-core:69886] [Bug #11350] [ruby-core:69961] * process.c (dup2_with_divert): new function for the above purpose. * thread_pthread.c (rb_divert_reserved_fd): new function for diverting reserved FD. If the given FD is the same as one of the reserved FDs, the reserved FD number is internally changed. It returns -1 when error. Otherwise, returns 0. It also returns 0 if there is no need to change reserved FD number. * thread_win32.c (rb_divert_reserved_fd): always returns 0 because of no reserved FDs. * internal.h (rb_divert_reserved_fd): prototype declaration. It is Ruby internal use only. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51268 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 20 ++++++++++++++++++++ internal.h | 1 + process.c | 14 ++++++++++++-- thread_pthread.c | 23 +++++++++++++++++++++++ thread_win32.c | 6 ++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2f3835346..27a06bd220 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Thu Jul 16 21:47:47 2015 Naohisa Goto + + * process.c (redirect_dup2): when the new FD of dup2() coflicts + with one of the timer thread FDs, the internal FD is diverted. + [Bug #11336] [ruby-core:69886] [Bug #11350] [ruby-core:69961] + + * process.c (dup2_with_divert): new function for the above purpose. + + * thread_pthread.c (rb_divert_reserved_fd): new function for + diverting reserved FD. If the given FD is the same as one of the + reserved FDs, the reserved FD number is internally changed. + It returns -1 when error. Otherwise, returns 0. It also returns + 0 if there is no need to change reserved FD number. + + * thread_win32.c (rb_divert_reserved_fd): always returns 0 because + of no reserved FDs. + + * internal.h (rb_divert_reserved_fd): prototype declaration. + It is Ruby internal use only. + Thu Jul 16 21:47:46 2015 Koichi Sasada * iseq.c (rb_iseq_disasm): rename rb_iseq_t *iseqdat to iseq diff --git a/internal.h b/internal.h index b51b49ee77..c91d8caba0 100644 --- a/internal.h +++ b/internal.h @@ -1150,6 +1150,7 @@ void ruby_kill(rb_pid_t pid, int sig); /* thread_pthread.c, thread_win32.c */ void Init_native_thread(void); +int rb_divert_reserved_fd(int fd); /* transcode.c */ extern VALUE rb_cEncodingConverter; diff --git a/process.c b/process.c index 7d3b1f580a..daf2eabf1e 100644 --- a/process.c +++ b/process.c @@ -305,6 +305,16 @@ close_unless_reserved(int fd) return close(fd); /* async-signal-safe */ } +static inline int +dup2_with_divert(int oldfd, int newfd) +{ + if (rb_divert_reserved_fd(newfd) == -1) { /* async-signal-safe if no error occurred */ + return -1; + } else { + return dup2(oldfd, newfd); /* async-signal-safe */ + } +} + /*#define DEBUG_REDIRECT*/ #if defined(DEBUG_REDIRECT) @@ -344,7 +354,7 @@ static int redirect_dup2(int oldfd, int newfd) { int ret; - ret = dup2(oldfd, newfd); + ret = dup2_with_divert(oldfd, newfd); ttyprintf("dup2(%d, %d) => %d\n", oldfd, newfd, ret); return ret; } @@ -378,7 +388,7 @@ parent_redirect_close(int fd) #else #define redirect_dup(oldfd) dup(oldfd) -#define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd)) +#define redirect_dup2(oldfd, newfd) dup2_with_divert((oldfd), (newfd)) #define redirect_close(fd) close_unless_reserved(fd) #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm)) #define parent_redirect_close(fd) close_unless_reserved(fd) diff --git a/thread_pthread.c b/thread_pthread.c index 71edee18b0..26fe9ffddf 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1707,6 +1707,29 @@ rb_reserved_fd_p(int fd) #endif } +int +rb_divert_reserved_fd(int fd) +{ +#if USE_SLEEPY_TIMER_THREAD + int *ptr; + int newfd; + + if ((fd == *(ptr = &(timer_thread_pipe.normal[0])) || + fd == *(ptr = &(timer_thread_pipe.normal[1])) || + fd == *(ptr = &(timer_thread_pipe.low[0])) || + fd == *(ptr = &(timer_thread_pipe.low[1]))) && + timer_thread_pipe.owner_process == getpid()) { /* async-signal-safe */ + newfd = rb_cloexec_dup(fd); /* async-signal-safe if no error */ + if (newfd == -1) return -1; + rb_update_max_fd(newfd); /* async-signal-safe if no error */ + /* set_nonblock(newfd); */ /* async-signal-safe if no error */ + *ptr = newfd; + rb_thread_wakeup_timer_thread_low(); /* async-signal-safe? */ + } +#endif + return 0; +} + rb_nativethread_id_t rb_nativethread_self(void) { diff --git a/thread_win32.c b/thread_win32.c index c4ea6c8efd..2dd377d348 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -788,6 +788,12 @@ rb_reserved_fd_p(int fd) return 0; } +int +rb_divert_reserved_fd(int fd) +{ + return 0; +} + rb_nativethread_id_t rb_nativethread_self(void) {