Class: WEBrick::Utils::TimeoutHandler

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/webrick/utils.rb

Overview

Class used to manage timeout handlers across multiple threads.

Timeout handlers should be managed by using the class methods which are synchronized.

id = TimeoutHandler.register(10, Timeout::Error)
begin
  sleep 20
  puts 'foo'
ensure
  TimeoutHandler.cancel(id)
end

will raise Timeout::Error

id = TimeoutHandler.register(10, Timeout::Error)
begin
  sleep 5
  puts 'foo'
ensure
  TimeoutHandler.cancel(id)
end

will print ‘foo’

Constant Summary collapse

TimeoutMutex =

Mutex used to synchronize access across threads

Thread::Mutex.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTimeoutHandler

Creates a new TimeoutHandler. You should use ::register and ::cancel instead of creating the timeout handler directly.



148
149
150
151
152
153
154
# File 'lib/webrick/utils.rb', line 148

def initialize
  TimeoutMutex.synchronize{
    @timeout_info = Hash.new
  }
  @queue = Thread::Queue.new
  @watcher = nil
end

Class Method Details

.cancel(id) ⇒ Object

Cancels the timeout handler id



137
138
139
# File 'lib/webrick/utils.rb', line 137

def TimeoutHandler.cancel(id)
  instance.cancel(Thread.current, id)
end

.register(seconds, exception) ⇒ Object

Registers a new timeout handler

time

Timeout in seconds

exception

Exception to raise when timeout elapsed



130
131
132
133
# File 'lib/webrick/utils.rb', line 130

def TimeoutHandler.register(seconds, exception)
  at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds
  instance.register(Thread.current, at, exception)
end

.terminateObject



141
142
143
# File 'lib/webrick/utils.rb', line 141

def self.terminate
  instance.terminate
end

Instance Method Details

#cancel(thread, id) ⇒ Object

Cancels the timeout handler id



226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/webrick/utils.rb', line 226

def cancel(thread, id)
  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 false
  }
end

#interrupt(thread, id, exception) ⇒ Object

Interrupts the timeout handler id and raises exception



203
204
205
206
207
# File 'lib/webrick/utils.rb', line 203

def interrupt(thread, id, exception)
  if cancel(thread, id) && thread.alive?
    thread.raise(exception, "execution timeout")
  end
end

#register(thread, time, exception) ⇒ Object

Registers a new timeout handler

time

Timeout in seconds

exception

Exception to raise when timeout elapsed



214
215
216
217
218
219
220
221
222
# File 'lib/webrick/utils.rb', line 214

def register(thread, time, exception)
  info = nil
  TimeoutMutex.synchronize{
    (@timeout_info[thread] ||= []) << (info = [time, exception])
  }
  @queue.push nil
  watcher
  return info.object_id
end

#terminateObject



240
241
242
243
244
245
# File 'lib/webrick/utils.rb', line 240

def terminate
  TimeoutMutex.synchronize{
    @timeout_info.clear
    @watcher&.kill&.join
  }
end