diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-08-26 17:03:41 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-08-26 17:03:41 +0000 |
commit | 4d9c58752a1d83be10811d4929c809a60eefeff8 (patch) | |
tree | 2895d1ecadad7b9b8c01e0062e015fb457bf3506 | |
parent | 416249b3fdf1a0de60d1ca25aacbaba5a5a148f8 (diff) |
merge revision(s) f91879a7b548284c93743168acfd11e3d2aeefac,9557069299ac3b96691040a541afa65761a724ad: [Backport #15992]
handle_interrupt to defend monitor state [Bug #15992]
If an exception is raised from another thread for example Timeout
and this thread is just after `mon_exit`'s `@mon_owner = nil`,
the exception breaks the state of MonitorMixin. To prevent that situation,
it need to block interruption in mon_enter and mon_exit.
Avoid creating Hash objects per each mon_synchronize call (#2393)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@67774 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | lib/monitor.rb | 27 | ||||
-rw-r--r-- | version.h | 2 |
2 files changed, 19 insertions, 10 deletions
diff --git a/lib/monitor.rb b/lib/monitor.rb index 288ed755ea..e99cbd4baa 100644 --- a/lib/monitor.rb +++ b/lib/monitor.rb @@ -87,6 +87,9 @@ # MonitorMixin module. # module MonitorMixin + EXCEPTION_NEVER = {Exception => :never}.freeze + EXCEPTION_IMMEDIATE = {Exception => :immediate}.freeze + # # FIXME: This isn't documented in Nutshell. # @@ -103,13 +106,17 @@ module MonitorMixin # even if no other thread doesn't signal. # def wait(timeout = nil) - @monitor.__send__(:mon_check_owner) - count = @monitor.__send__(:mon_exit_for_cond) - begin - @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout) - return true - ensure - @monitor.__send__(:mon_enter_for_cond, count) + Thread.handle_interrupt(EXCEPTION_NEVER) do + @monitor.__send__(:mon_check_owner) + count = @monitor.__send__(:mon_exit_for_cond) + begin + Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do + @cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout) + end + return true + ensure + @monitor.__send__(:mon_enter_for_cond, count) + end end end @@ -221,11 +228,13 @@ module MonitorMixin # +MonitorMixin+. # def mon_synchronize - mon_enter + # Prevent interrupt on handling interrupts; for example timeout errors + # it may break locking state. + Thread.handle_interrupt(Exception => :never){ mon_enter } begin yield ensure - mon_exit + Thread.handle_interrupt(EXCEPTION_NEVER){ mon_exit } end end alias synchronize mon_synchronize @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.5.6" #define RUBY_RELEASE_DATE "2019-08-27" -#define RUBY_PATCHLEVEL 192 +#define RUBY_PATCHLEVEL 193 #define RUBY_RELEASE_YEAR 2019 #define RUBY_RELEASE_MONTH 8 |