ruby-changes:58731
From: Koichi <ko1@a...>
Date: Tue, 12 Nov 2019 10:08:01 +0900 (JST)
Subject: [ruby-changes:58731] fd6445b7e8 (master): Monitor#exit: check monitor ownership.
https://git.ruby-lang.org/ruby.git/commit/?id=fd6445b7e8 From fd6445b7e8bab9d340be6f76688a8b96f1b52029 Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Tue, 12 Nov 2019 10:02:47 +0900 Subject: Monitor#exit: check monitor ownership. Monitor#exit should be called by only onwer Thread. However, there is not check for it. diff --git a/ext/monitor/monitor.c b/ext/monitor/monitor.c index 2d39976..256fc4d 100644 --- a/ext/monitor/monitor.c +++ b/ext/monitor/monitor.c @@ -86,10 +86,25 @@ monitor_enter(VALUE monitor) https://github.com/ruby/ruby/blob/trunk/ext/monitor/monitor.c#L86 } 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(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); @@ -112,16 +127,6 @@ monitor_owned_p(VALUE monitor) https://github.com/ruby/ruby/blob/trunk/ext/monitor/monitor.c#L127 } 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) { struct rb_monitor *mc = monitor_ptr(monitor); diff --git a/test/monitor/test_monitor.rb b/test/monitor/test_monitor.rb index 49c34e0..950db91 100644 --- a/test/monitor/test_monitor.rb +++ b/test/monitor/test_monitor.rb @@ -35,6 +35,29 @@ class TestMonitor < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/monitor/test_monitor.rb#L35 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 -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/