diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | lib/webrick/utils.rb | 43 |
2 files changed, 28 insertions, 21 deletions
@@ -1,3 +1,9 @@ +Wed Dec 16 00:53:45 2015 Naohisa Goto <ngotogenome@gmail.com> + + * lib/webrick/utils.rb (WEBrick::Utils::TimeoutHandler): Acquire + TimeoutMutex only when accessing @timeout_info for avoiding + potential deadlock. [Bug #11742] [ruby-dev:49387] + Wed Dec 16 00:39:27 2015 Jake Worth <jakeworth82@gmail.com> * doc/extension.rdoc: [DOC] fix double-word typo. [Fix GH-1153] diff --git a/lib/webrick/utils.rb b/lib/webrick/utils.rb index dc7ce508ea..654d9dea95 100644 --- a/lib/webrick/utils.rb +++ b/lib/webrick/utils.rb @@ -135,24 +135,22 @@ module WEBrick # +time+:: Timeout in seconds # +exception+:: Exception to raise when timeout elapsed def TimeoutHandler.register(seconds, exception) - TimeoutMutex.synchronize{ - instance.register(Thread.current, Time.now + seconds, exception) - } + instance.register(Thread.current, Time.now + seconds, exception) end ## # Cancels the timeout handler +id+ def TimeoutHandler.cancel(id) - TimeoutMutex.synchronize{ - instance.cancel(Thread.current, id) - } + instance.cancel(Thread.current, id) end ## # Creates a new TimeoutHandler. You should use ::register and ::cancel # instead of creating the timeout handler directly. def initialize - @timeout_info = Hash.new + TimeoutMutex.synchronize{ + @timeout_info = Hash.new + } @watcher = Thread.start{ to_interrupt = [] while true @@ -185,11 +183,9 @@ module WEBrick ## # Interrupts the timeout handler +id+ and raises +exception+ def interrupt(thread, id, exception) - TimeoutMutex.synchronize{ - if cancel(thread, id) && thread.alive? - thread.raise(exception, "execution timeout") - end - } + if cancel(thread, id) && thread.alive? + thread.raise(exception, "execution timeout") + end end ## @@ -198,8 +194,11 @@ module WEBrick # +time+:: Timeout in seconds # +exception+:: Exception to raise when timeout elapsed def register(thread, time, exception) - @timeout_info[thread] ||= Array.new - @timeout_info[thread] << (info = [time, exception]) + info = nil + TimeoutMutex.synchronize{ + @timeout_info[thread] ||= Array.new + @timeout_info[thread] << (info = [time, exception]) + } begin @watcher.wakeup rescue ThreadError @@ -210,14 +209,16 @@ module WEBrick ## # Cancels the timeout handler +id+ def cancel(thread, id) - if ary = @timeout_info[thread] - ary.delete_if{|info| info.object_id == id } - if ary.empty? - @timeout_info.delete(thread) + TimeoutMutex.synchronize{ + if ary = @timeout_info[thread] + ary.delete_if{|info| info.object_id == id } + if ary.empty? + @timeout_info.delete(thread) + end + return true end - return true - end - return false + return false + } end end |