aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--internal.h1
-rw-r--r--process.c14
-rw-r--r--thread_pthread.c23
-rw-r--r--thread_win32.c6
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 <ngotogenome@gmail.com>
+
+ * 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 <ko1@atdot.net>
* 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)
{