mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Revert r64441
* This reverts commit 647fc1227a
:
"thread_sync.c (rb_mutex_synchronize): only unlock if we own the mutex"
* Let's try to preserve the semantics of always being locked inside
Mutex#synchronize, even if an exception interrupts ConditionVariable#wait.
* As discussed on [Bug #14999].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64448 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b5b5b28c65
commit
c742050ea5
2 changed files with 44 additions and 56 deletions
|
@ -23,15 +23,21 @@ describe "ConditionVariable#wait" do
|
|||
th.join
|
||||
end
|
||||
|
||||
it "the lock remains usable even if the thread is killed" do
|
||||
it "reacquires the lock even if the thread is killed" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
owned = nil
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
begin
|
||||
cv.wait(m)
|
||||
ensure
|
||||
owned = m.owned?
|
||||
$stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -43,19 +49,24 @@ describe "ConditionVariable#wait" do
|
|||
th.kill
|
||||
th.join
|
||||
|
||||
m.try_lock.should == true
|
||||
m.unlock
|
||||
owned.should == true
|
||||
end
|
||||
|
||||
it "lock remains usable even if the thread is killed after being signaled" do
|
||||
it "reacquires the lock even if the thread is killed after being signaled" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
owned = nil
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
begin
|
||||
cv.wait(m)
|
||||
ensure
|
||||
owned = m.owned?
|
||||
$stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,8 +84,7 @@ describe "ConditionVariable#wait" do
|
|||
}
|
||||
|
||||
th.join
|
||||
m.try_lock.should == true
|
||||
m.unlock
|
||||
owned.should == true
|
||||
end
|
||||
|
||||
it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do
|
||||
|
|
|
@ -321,14 +321,21 @@ rb_mutex_owned_p(VALUE self)
|
|||
return owned;
|
||||
}
|
||||
|
||||
static void
|
||||
mutex_do_unlock(rb_mutex_t *mutex, rb_thread_t *th)
|
||||
static const char *
|
||||
rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th)
|
||||
{
|
||||
const char *err = NULL;
|
||||
|
||||
if (mutex->th == 0) {
|
||||
err = "Attempt to unlock a mutex which is not locked";
|
||||
}
|
||||
else if (mutex->th != th) {
|
||||
err = "Attempt to unlock a mutex which is locked by another thread";
|
||||
}
|
||||
else {
|
||||
struct sync_waiter *cur = 0, *next = 0;
|
||||
rb_mutex_t **th_mutex = &th->keeping_mutexes;
|
||||
|
||||
VM_ASSERT(mutex->th == th);
|
||||
|
||||
mutex->th = 0;
|
||||
list_for_each_safe(&mutex->waitq, cur, next, node) {
|
||||
list_del_init(&cur->node);
|
||||
|
@ -351,21 +358,6 @@ mutex_do_unlock(rb_mutex_t *mutex, rb_thread_t *th)
|
|||
}
|
||||
*th_mutex = mutex->next_mutex;
|
||||
mutex->next_mutex = NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th)
|
||||
{
|
||||
const char *err = NULL;
|
||||
|
||||
if (mutex->th == 0) {
|
||||
err = "Attempt to unlock a mutex which is not locked";
|
||||
}
|
||||
else if (mutex->th != th) {
|
||||
err = "Attempt to unlock a mutex which is locked by another thread";
|
||||
}
|
||||
else {
|
||||
mutex_do_unlock(mutex, th);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -505,20 +497,6 @@ mutex_sleep(int argc, VALUE *argv, VALUE self)
|
|||
return rb_mutex_sleep(self, timeout);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
mutex_unlock_if_owned(VALUE self)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_mutex_t *mutex;
|
||||
GetMutexPtr(self, mutex);
|
||||
|
||||
/* we may not own the mutex if an exception occured */
|
||||
if (mutex->th == th) {
|
||||
mutex_do_unlock(mutex, th);
|
||||
}
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mutex.synchronize { ... } -> result of the block
|
||||
|
@ -531,7 +509,7 @@ VALUE
|
|||
rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
|
||||
{
|
||||
rb_mutex_lock(mutex);
|
||||
return rb_ensure(func, arg, mutex_unlock_if_owned, mutex);
|
||||
return rb_ensure(func, arg, rb_mutex_unlock, mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue