safe_regexp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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