1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Monitor#exit: check monitor ownership.

Monitor#exit should be called by only onwer Thread. However, there
is not check for it.
This commit is contained in:
Koichi Sasada 2019-11-12 10:02:47 +09:00
parent fef4370b40
commit fd6445b7e8
2 changed files with 39 additions and 11 deletions

View file

@ -86,10 +86,25 @@ monitor_enter(VALUE monitor)
}
static VALUE
monitor_exit(VALUE monitor)
monitor_check_owner(VALUE monitor)
{
struct rb_monitor *mc = monitor_ptr(monitor);
if (!mc_owner_p(mc)) {
rb_raise(rb_eThreadError, "current thread not owner");
}
return Qnil;
}
static VALUE
monitor_exit(VALUE monitor)
{
monitor_check_owner(monitor);
struct rb_monitor *mc = monitor_ptr(monitor);
if (mc->count <= 0) rb_bug("monitor_exit: count:%d\n", (int)mc->count);
mc->count--;
if (mc->count == 0) {
RB_OBJ_WRITE(monitor, &mc->owner, Qnil);
rb_mutex_unlock(mc->mutex);
@ -111,16 +126,6 @@ monitor_owned_p(VALUE monitor)
return (rb_mutex_locked_p(mc->mutex) && mc_owner_p(mc)) ? Qtrue : Qfalse;
}
static VALUE
monitor_check_owner(VALUE monitor)
{
struct rb_monitor *mc = monitor_ptr(monitor);
if (!mc_owner_p(mc)) {
rb_raise(rb_eThreadError, "current thread not owner");
}
return Qnil;
}
static VALUE
monitor_exit_for_cond(VALUE monitor)
{

View file

@ -35,6 +35,29 @@ class TestMonitor < Test::Unit::TestCase
assert_equal((1..10).to_a, ary)
end
def test_exit
m = Monitor.new
m.enter
assert_equal true, m.mon_owned?
m.exit
assert_equal false, m.mon_owned?
assert_raise ThreadError do
m.exit
end
assert_equal false, m.mon_owned?
m.enter
Thread.new{
assert_raise(ThreadError) do
m.exit
end
}.join
assert_equal true, m.mon_owned?
m.exit
end
def test_enter_second_after_killed_thread
th = Thread.start {
@monitor.enter