aboutsummaryrefslogtreecommitdiffstats
path: root/thread_pthread.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-06-27 03:14:30 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-06-27 03:14:30 +0000
commit7610686fff7f8435fca4c6b63210df99840f6a67 (patch)
tree550ff5e80d4735d7a5c3f05605a180cfcba526b2 /thread_pthread.c
parentfed97e841d398d7d23d714cfc418a55a4eff44c2 (diff)
downloadruby-7610686fff7f8435fca4c6b63210df99840f6a67.tar.gz
hijack SIGCHLD handler for internal use
Use a global SIGCHLD handler to guard all callers of rb_waitpid. To work safely with multi-threaded programs, we introduce a VM-wide waitpid_lock to be acquired BEFORE fork/vfork spawns the process. This is to be combined with the new ruby_waitpid_locked function used by mjit.c in a non-Ruby thread. Ruby-level SIGCHLD handlers registered with Signal.trap(:CHLD) continues to work as before and there should be no regressions in any existing use cases. Splitting the wait queues for PID > 0 and groups (PID <= 0) ensures we favor PID > 0 callers. The disabling of SIGCHLD in rb_f_system is longer necessary, as we use deferred signal handling and no longer make ANY blocking waitpid syscalls in other threads which could "beat" the waitpid call made by rb_f_system. We prevent SIGCHLD from firing in normal Ruby Threads and only enable it in the timer-thread, to prevent spurious wakeups from in test/-ext-/gvl/test_last_thread.rb with MJIT enabled. I've tried to guard as much of the code for RUBY_SIGCHLD==0 using C "if" statements rather than CPP "#if" so to reduce the likelyhood of portability problems as the compiler will see more code. We also work to suppress false-positives from Process.wait(-1, Process::WNOHANG) to quiets warnings from spec/ruby/core/process/wait2_spec.rb with MJIT enabled. Lastly, we must implement rb_grantpt for ext/pty. We need a MJIT-compatible way of supporting grantpt(3) which may spawn the `pt_chown' binary and call waitpid(2) on it. [ruby-core:87605] [Ruby trunk Bug#14867] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread_pthread.c')
-rw-r--r--thread_pthread.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/thread_pthread.c b/thread_pthread.c
index 1a1a6fc0c6..6ac7728ad9 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1479,6 +1479,13 @@ static void *
thread_timer(void *p)
{
rb_global_vm_lock_t *gvl = (rb_global_vm_lock_t *)p;
+#ifdef HAVE_PTHREAD_SIGMASK /* mainly to enable SIGCHLD */
+ {
+ sigset_t mask;
+ sigemptyset(&mask);
+ pthread_sigmask(SIG_SETMASK, &mask, NULL);
+ }
+#endif
if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n");
@@ -1764,4 +1771,22 @@ rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void)
return ret;
}
+#define USE_NATIVE_SLEEP_COND (1)
+
+#if USE_NATIVE_SLEEP_COND
+rb_nativethread_cond_t *
+rb_sleep_cond_get(const rb_execution_context_t *ec)
+{
+ rb_thread_t *th = rb_ec_thread_ptr(ec);
+
+ return &th->native_thread_data.sleep_cond;
+}
+
+void
+rb_sleep_cond_put(rb_nativethread_cond_t *cond)
+{
+ /* no-op */
+}
+#endif /* USE_NATIVE_SLEEP_COND */
+
#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */