Skip to content
Browse files

Merge branch 'bugfix_backport' into merge

  • Loading branch information...
2 parents 877a805 + ce004d5 commit 8a47963f3dab21750e29aab945e454cad2b640d0 @FooBarWidget committed
Showing with 88 additions and 18 deletions.
  1. +5 −0 ChangeLog
  2. +5 −12 eval.c
  3. +15 −6 ext/thread/thread.c
  4. +63 −0 test/thread/test_thread.rb
View
5 ChangeLog
@@ -1362,6 +1362,11 @@ Tue May 26 20:50:32 2009 Tanaka Akira <akr@fsij.org>
* eval.c (rb_thread_schedule): handle EBADF of select as well.
[ruby-core:21264]
+Fri May 15 17:33:51 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_join), ext/thread/thread.c (wake_one): adjusts
+ targets of rest waiting threads to join. [ruby-core:23457]
+
Wed Apr 8 18:59:52 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (subtruct): check tv_sec.
View
17 eval.c
@@ -11392,7 +11392,6 @@ rb_thread_schedule()
if (th->status != THREAD_STOPPED) continue;
if (th->wait_for & WAIT_JOIN) {
if (rb_thread_dead(th->join)) {
- th->wait_for = 0;
th->status = THREAD_RUNNABLE;
found = 1;
}
@@ -11901,19 +11900,13 @@ void
rb_thread_set_join(thread, join)
VALUE thread, join;
{
- rb_thread_t th = rb_thread_check(thread);
- rb_thread_t jth = rb_thread_check(join);
- if ((th->wait_for & WAIT_JOIN) == 0) {
- rb_bug( "Internal consistency failure! Expected thread to already be in waiting to join state %0x, was in %0x", WAIT_JOIN, th->wait_for);
- }
-
- if (th->join != curr_thread) {
- rb_bug( "Internal consistency failure! Should only invoke rb_thread_set_join from a mutex unlock. Thread join aiming at %0x which something other than current thread %0x", th->join, curr_thread);
- }
-
- th->join = jth;
+ rb_thread_t th = rb_thread_check(thread);
+ rb_thread_t jth = rb_thread_check(join);
+ th->wait_for = WAIT_JOIN;
+ th->join = jth;
}
+
/*
* call-seq:
* thr.join => thr
View
21 ext/thread/thread.c
@@ -211,7 +211,7 @@ adjust_join(const List *list, VALUE new)
extern void rb_thread_set_join _((VALUE, VALUE));
Entry *entry;
for (entry = list->entries; entry; entry = entry->next) {
- rb_thread_set_join(entry->value, new);
+ rb_thread_set_join(entry->value, new);
}
}
@@ -231,7 +231,7 @@ run_thread(VALUE thread)
}
static VALUE
-wake_one(List *list)
+wake_first(List *list)
{
VALUE waking;
@@ -244,10 +244,22 @@ wake_one(List *list)
}
static VALUE
+wake_one(List *list)
+{
+ VALUE waking = wake_first(list);
+
+ if (!NIL_P(waking)) {
+ adjust_join(list, waking);
+ }
+
+ return waking;
+}
+
+static VALUE
wake_all(List *list)
{
while (list->entries) {
- wake_one(list);
+ wake_first(list);
}
return Qnil;
}
@@ -481,9 +493,6 @@ unlock_mutex_inner(Mutex *mutex)
}
waking = wake_one(&mutex->waiting);
- if (!NIL_P(waking)) {
- adjust_join(&mutex->waiting, waking);
- }
mutex->owner = waking;
return waking;
View
63 test/thread/test_thread.rb
@@ -86,5 +86,68 @@ def test_queue_rescue
assert_nothing_raised("[ruby-dev:37545]") {assert_equal(1, queue.pop)}
assert(queue.empty?)
end
+
+ # This test checks that a thread in Mutex#lock which is raised is
+ # completely removed from the wait_list of the mutex
+ def test_mutex_exception_handling
+ m = Mutex.new
+ m.lock
+
+ sleeping = false
+ t = Thread.new do
+ begin
+ m.lock
+ rescue
+ end
+
+ sleeping = true
+ # Keep that thread alive: if the thread returns, the test method
+ # won't be able to check that +m+ has not been taken (dead mutex
+ # owners are ignored)
+ sleep
+ end
+
+ # Wait for t to wait for the mutex and raise it
+ while true
+ sleep 0.1
+ break if t.stop?
+ end
+ t.raise ArgumentError
+ assert(t.alive? || sleeping)
+
+ # Wait for +t+ to reach the sleep
+ while true
+ sleep 0.1
+ break if t.stop?
+ end
+
+ # Now unlock. The mutex should be free, so Mutex#unlock should return nil
+ assert(! m.unlock)
+ end
+
+ def test_mutex_join
+ m = Mutex.new
+ m.lock
+ wt2 = Thread.new do
+ m.lock
+ sleep 0.5
+ m.unlock
+ end
+
+ # Ensure wt2 is waiting on m
+ sleep 0.1
+
+ wt1 = Thread.new do
+ m.lock
+ m.unlock
+ end
+ # Ensure wt1 is waiting on m
+ sleep 0.1
+
+ # Give it to wt2
+ m.unlock
+
+ assert_nothing_raised {wt1.join}
+ end
end

0 comments on commit 8a47963

Please sign in to comment.
Something went wrong with that request. Please try again.