Skip to content

Commit ed89a1b

Browse files
committed
More pthread_rwlock error handling
1 parent 1f599a6 commit ed89a1b

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

test/-ext-/gvl/test_instrumentation_api.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# frozen_string_literal: false
22
class TestGVLInstrumentation < Test::Unit::TestCase
3+
def setup
4+
skip("No windows support yet") if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
5+
end
6+
37
def test_gvl_instrumentation
48
require '-test-/gvl/instrumentation'
59
Bug::GVLInstrumentation.reset_counters
@@ -16,6 +20,28 @@ def test_gvl_instrumentation
1620
end
1721
end
1822

23+
def test_gvl_instrumentation_fork_safe
24+
skip "No fork()" unless Process.respond_to?(:fork)
25+
26+
require '-test-/gvl/instrumentation'
27+
Bug::GVLInstrumentation::register_callback
28+
29+
begin
30+
pid = fork do
31+
Bug::GVLInstrumentation.reset_counters
32+
threads = 5.times.map { Thread.new { sleep 0.05; 1 + 1; sleep 0.02 } }
33+
threads.each(&:join)
34+
Bug::GVLInstrumentation.counters.each do |c|
35+
assert_predicate c,:nonzero?
36+
end
37+
end
38+
_, status = Process.wait2(pid)
39+
assert_predicate status, :success?
40+
ensure
41+
Bug::GVLInstrumentation::unregister_callback
42+
end
43+
end
44+
1945
def test_gvl_instrumentation_unregister
2046
require '-test-/gvl/instrumentation'
2147
assert Bug::GVLInstrumentation::register_and_unregister_callbacks

thread_pthread.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,21 +110,25 @@ rb_gvl_event_new(void *callback, rb_event_flag_t event) {
110110
hook->callback = callback;
111111
hook->event = event;
112112

113-
if (pthread_rwlock_wrlock(&rb_gvl_hooks_rw_lock)) {
114-
rb_bug("GVL hooks deadlock");
113+
int r;
114+
if ((r = pthread_rwlock_wrlock(&rb_gvl_hooks_rw_lock))) {
115+
rb_bug_errno("pthread_rwlock_wrlock", r);
115116
}
116117

117118
hook->next = rb_gvl_hooks;
118119
ATOMIC_PTR_EXCHANGE(rb_gvl_hooks, hook);
119120

120-
pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock);
121+
if ((r = pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock))) {
122+
rb_bug_errno("pthread_rwlock_unlock", r);
123+
}
121124
return hook;
122125
}
123126

124127
bool
125128
rb_gvl_event_delete(gvl_hook_t * hook) {
126-
if (pthread_rwlock_wrlock(&rb_gvl_hooks_rw_lock)) {
127-
rb_bug("GVL hooks deadlock");
129+
int r;
130+
if ((r = pthread_rwlock_wrlock(&rb_gvl_hooks_rw_lock))) {
131+
rb_bug_errno("pthread_rwlock_wrlock", r);
128132
}
129133

130134
bool success = FALSE;
@@ -143,7 +147,9 @@ rb_gvl_event_delete(gvl_hook_t * hook) {
143147
} while ((h = h->next));
144148
}
145149

146-
pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock);
150+
if ((r = pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock))) {
151+
rb_bug_errno("pthread_rwlock_unlock", r);
152+
}
147153

148154
if (success) {
149155
ruby_xfree(hook);
@@ -153,8 +159,9 @@ rb_gvl_event_delete(gvl_hook_t * hook) {
153159

154160
static void
155161
rb_gvl_execute_hooks(rb_event_flag_t event, rb_atomic_t waiting) {
156-
if (pthread_rwlock_rdlock(&rb_gvl_hooks_rw_lock)) {
157-
rb_bug("GVL hooks deadlock");
162+
int r;
163+
if ((r = pthread_rwlock_rdlock(&rb_gvl_hooks_rw_lock))) {
164+
rb_bug_errno("pthread_rwlock_rdlock", r);
158165
}
159166

160167
if (rb_gvl_hooks) {
@@ -166,7 +173,9 @@ rb_gvl_execute_hooks(rb_event_flag_t event, rb_atomic_t waiting) {
166173
}
167174
} while((h = h->next));
168175
}
169-
pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock);
176+
if ((r = pthread_rwlock_unlock(&rb_gvl_hooks_rw_lock))) {
177+
rb_bug_errno("pthread_rwlock_unlock", r);
178+
}
170179
}
171180

172181
enum rtimer_state {
@@ -727,11 +736,14 @@ static void native_thread_init(rb_thread_t *th);
727736
void
728737
Init_native_thread(rb_thread_t *th)
729738
{
730-
pthread_rwlock_init(&rb_gvl_hooks_rw_lock, NULL);
739+
int r;
740+
if ((r = pthread_rwlock_init(&rb_gvl_hooks_rw_lock, NULL))) {
741+
rb_bug_errno("pthread_rwlock_init", r);
742+
}
731743

732744
#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
733745
if (condattr_monotonic) {
734-
int r = pthread_condattr_init(condattr_monotonic);
746+
r = pthread_condattr_init(condattr_monotonic);
735747
if (r == 0) {
736748
r = pthread_condattr_setclock(condattr_monotonic, CLOCK_MONOTONIC);
737749
}

0 commit comments

Comments
 (0)