safe_regexp 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1ef6c0df7c6e214380ee04d7cb031024464a50d49ad12e0cdf825a1a9304531
4
- data.tar.gz: afa6f06caa7c0378cdaba0d69e0eb5a210c4afce6631f352d4c7e917c406e9c0
3
+ metadata.gz: fc901f108ce8414bcee7e00f16a4a7ad630e90c8106dbbf4d2cdb31b96f8bc0b
4
+ data.tar.gz: '0690404a49a7fe5bdbc14c5500cf0144b9d88e322f6a863a29a1c17f97cef443'
5
5
  SHA512:
6
- metadata.gz: 928559f2fb198ceb875de832efa8389faaec72f56e30c69889e37c2631c366304358a54a79d5bfe24efae56c271ee48330e6417b7d6d840a6b9a93367149469e
7
- data.tar.gz: 4dd3585d1f00f8a9cf6188310cd432702ae37615a4ee937780919e5ae7d8b4cc51a86edcb3c7f7a77ebd78a918829d109c289be75275745033ffb3cc04d07ac8
6
+ metadata.gz: 600aee1cdd8b2a2bd7e222f52251a7fee8842243d0b4b92ebd7a508ec3088f8481e259dc5a7f16ae22bd7435a9f5912eff6627114e97b46d22f57e86c9167727
7
+ data.tar.gz: 4e98a42ccad498915ffbf6d7b18706f6dfa85a0a5a956a3fe93a65c36aec09edbd2dffde67834acbda890e0235bfb7e9883fad18a314f0c801ab713e15b1b294
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module SafeRegexp
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
data/lib/safe_regexp.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require "timeout"
3
2
 
4
3
  module SafeRegexp
5
- class SubprocessTimeout < Timeout::Error
6
- end
4
+ RESCUED_EXCEPTION = StandardError
7
5
 
8
6
  class RegexpTimeout < Timeout::Error
9
7
  end
@@ -13,20 +11,21 @@ module SafeRegexp
13
11
  retried = false
14
12
  begin
15
13
  read, write, pid = executor
16
- write.puts Marshal.dump([regex, method, string, keepalive])
17
- rescue Errno::EPIPE # keepalive killed the process
14
+ Marshal.dump([regex, method, string, keepalive], write)
15
+ rescue Errno::EPIPE # keepalive already killed the process
18
16
  raise if retried
19
17
  retried = true
20
- discard_executor
21
- retry
18
+ discard_executor # avoiding kill overhead since it's already dead
19
+ retry # new executor will be created by `executor` call
22
20
  end
23
21
 
24
- begin
25
- Timeout.timeout(timeout, SubprocessTimeout) { Marshal.load(read.gets) }
26
- rescue SubprocessTimeout
22
+ unless IO.select([read], nil, nil, timeout)
27
23
  kill_executor pid
28
24
  raise RegexpTimeout
29
25
  end
26
+
27
+ result = Marshal.load(read)
28
+ result.is_a?(RESCUED_EXCEPTION) ? raise(result) : result
30
29
  end
31
30
 
32
31
  def shutdown
@@ -39,13 +38,14 @@ module SafeRegexp
39
38
  def kill_executor(pid)
40
39
  begin
41
40
  Process.kill :KILL, pid # kill -9
41
+ rescue Errno::ESRCH
42
+ nil # already dead
43
+ else
42
44
  begin
43
45
  Process.wait pid # reap child
44
46
  rescue Errno::ECHILD
45
47
  nil # already reaped
46
48
  end
47
- rescue Errno::ESRCH
48
- nil # already dead
49
49
  end
50
50
  discard_executor
51
51
  end
@@ -57,7 +57,7 @@ module SafeRegexp
57
57
 
58
58
  # - keepalive gets extended by whatever time the matching takes, but that should not be too bad
59
59
  # we could fix it, but that means extra overhead that I'd rather avoid
60
- # - using select to avoid having extra threads
60
+ # - using select to avoid having extra threads / Timeout
61
61
  def executor
62
62
  Thread.current[:safe_regexp_executor] ||= begin
63
63
  in_read, in_write = IO.pipe
@@ -65,13 +65,17 @@ module SafeRegexp
65
65
  pid = fork do
66
66
  in_write.close
67
67
  out_read.close
68
- keepalive = 1
68
+ keepalive = 1 # initial payload should come in shortly after boot
69
69
  loop do
70
70
  break unless IO.select([in_read], nil, nil, keepalive)
71
- break unless (instructions = in_read.gets)
72
- regexp, method, string, keepalive = Marshal.load(instructions)
73
- result = regexp.public_send(method, string)
74
- out_write.puts Marshal.dump(result)
71
+ regexp, method, string, keepalive = Marshal.load(in_read)
72
+ begin
73
+ result = regexp.public_send(method, string)
74
+ result = result.to_a if result.is_a?(MatchData) # cannot be dumped
75
+ rescue RESCUED_EXCEPTION
76
+ result = $!
77
+ end
78
+ Marshal.dump(result, out_write)
75
79
  end
76
80
  exit! # to not run any kind of at_exit hook the parent might have configured
77
81
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_regexp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-28 00:00:00.000000000 Z
11
+ date: 2019-03-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: michael@grosser.it