Module: SafeRegexp

Defined in:
lib/safe_regexp.rb,
lib/safe_regexp/version.rb

Defined Under Namespace

Classes: RegexpTimeout

Constant Summary collapse

RESCUED_EXCEPTION =
StandardError
VERSION =
"0.2.2"

Class Method Summary collapse

Class Method Details

.execute(regex, method, string, timeout: 1, keepalive: 10) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/safe_regexp.rb', line 10

def execute(regex, method, string, timeout: 1, keepalive: 10)
  retried = false

  begin
    loading_result = false

    begin
      read, write, pid = executor
      Marshal.dump([regex, method, string, keepalive], write)
    rescue Errno::EPIPE
      # keepalive already killed the process, but we don't check before sending
      # since that would be a race condition and cause overhead for the 99.9% case
      raise if retried
      retried = true
      discard_executor # avoiding kill overhead since it's already dead
      retry # new executor will be created by `executor` call
    end

    unless IO.select([read], nil, nil, timeout)
      kill_executor pid
      raise RegexpTimeout
    end

    loading_result = true
    result = Marshal.load(read)
  rescue EOFError # process was dead from keepalive when we sent to it or got killed from outside
    raise if retried || !loading_result
    retried = true
    discard_executor # avoiding kill overhead since it's already dead
    retry
  end

  result.is_a?(RESCUED_EXCEPTION) ? raise(result) : result
end

.shutdownObject



45
46
47
48
# File 'lib/safe_regexp.rb', line 45

def shutdown
  return unless (pid = Thread.current[:safe_regexp_executor]&.last)
  kill_executor pid
end