summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2020-10-28 15:27:00 -0700
committerGitHub <noreply@github.com>2020-10-28 15:27:00 -0700
commitdfb3605bbee9c3cfbc1c354594c367472f29cb35 (patch)
treec45c7551fad0baeb053771468bd534b396bfd4bf /thread.c
parenta99f52d5113a601b6d18bd671dfee24266689ffe (diff)
Add Thread.ignore_deadlock accessor
Setting this to true disables the deadlock detector. It should only be used in cases where the deadlock could be broken via some external means, such as via a signal. Now that $SAFE is no longer used, replace the safe_level_ VM flag with ignore_deadlock for storing the setting. Fixes [Bug #13768]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3710 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/thread.c b/thread.c
index 64d9ac03dd..007a5cbc7b 100644
--- a/thread.c
+++ b/thread.c
@@ -3065,7 +3065,7 @@ rb_thread_abort_exc_set(VALUE thread, VALUE val)
*
* There is also an instance level method to set this for a specific thread,
* see #report_on_exception=.
- *
+ *
*/
static VALUE
@@ -3115,6 +3115,52 @@ rb_thread_s_report_exc_set(VALUE self, VALUE val)
/*
* call-seq:
+ * Thread.ignore_deadlock -> true or false
+ *
+ * Returns the status of the global ``ignore deadlock'' condition.
+ * The default is +false+, so that deadlock conditions are not ignored.
+ *
+ * See also ::ignore_deadlock=.
+ *
+ */
+
+static VALUE
+rb_thread_s_ignore_deadlock(VALUE _)
+{
+ return GET_THREAD()->vm->thread_ignore_deadlock ? Qtrue : Qfalse;
+}
+
+
+/*
+ * call-seq:
+ * Thread.ignore_deadlock = boolean -> true or false
+ *
+ * Returns the new state.
+ * When set to +true+, the VM will not check for deadlock conditions.
+ * It is only useful to set this if your application can break a
+ * deadlock condition via some other means, such as a signal.
+ *
+ * Thread.ignore_deadlock = true
+ * queue = Queue.new
+ *
+ * trap(:SIGUSR1){queue.push "Received signal"}
+ *
+ * # raises fatal error unless ignoring deadlock
+ * puts queue.pop
+ *
+ * See also ::ignore_deadlock.
+ */
+
+static VALUE
+rb_thread_s_ignore_deadlock_set(VALUE self, VALUE val)
+{
+ GET_THREAD()->vm->thread_ignore_deadlock = RTEST(val);
+ return val;
+}
+
+
+/*
+ * call-seq:
* thr.report_on_exception -> true or false
*
* Returns the status of the thread-local ``report on exception'' condition for
@@ -5480,6 +5526,8 @@ Init_Thread(void)
rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
rb_define_singleton_method(rb_cThread, "report_on_exception", rb_thread_s_report_exc, 0);
rb_define_singleton_method(rb_cThread, "report_on_exception=", rb_thread_s_report_exc_set, 1);
+ rb_define_singleton_method(rb_cThread, "ignore_deadlock", rb_thread_s_ignore_deadlock, 0);
+ rb_define_singleton_method(rb_cThread, "ignore_deadlock=", rb_thread_s_ignore_deadlock_set, 1);
#if THREAD_DEBUG < 0
rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0);
rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1);
@@ -5611,6 +5659,8 @@ debug_deadlock_check(rb_ractor_t *r, VALUE msg)
static void
rb_check_deadlock(rb_ractor_t *r)
{
+ if (GET_THREAD()->vm->thread_ignore_deadlock) return;
+
int found = 0;
rb_thread_t *th = NULL;
int sleeper_num = rb_ractor_sleeper_thread_num(r);