runaway 1.0.0 → 1.0.1
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 +4 -4
- data/lib/runaway.rb +10 -2
- data/runaway.gemspec +3 -3
- data/spec/runaway_spec.rb +21 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee88a2e47d1bf2847893a4b258d236efcfff3fae
|
4
|
+
data.tar.gz: f3edef5cc5fae9363f1d56978c0465b56faa0a24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0489708f0657aeb6e7b91c7f23e2007974d22577afe01b9c04b2dca6d12a9fcdbdf68cdbb965b75970351333eab45ec6a1599f3d34a3727abda9f8daa47ab248
|
7
|
+
data.tar.gz: 34eeca38ad28dfb7b205a40b9517f3b3123683a9fdd466031b848bd1780f9b67e1b477c3a1d10104b412b36ee80df21c33e1ab2dfcf5af799e0b0f86963d3ede
|
data/lib/runaway.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
|
3
3
|
module Runaway
|
4
|
-
VERSION = '1.0.
|
4
|
+
VERSION = '1.0.1'
|
5
5
|
|
6
6
|
UncleanExit = Class.new(StandardError)
|
7
7
|
Child = Class.new(StandardError)
|
@@ -49,9 +49,12 @@ module Runaway
|
|
49
49
|
(Process.kill(sig, child_pid) rescue Errno::ESRCH) if !has_quit
|
50
50
|
}
|
51
51
|
|
52
|
+
last_heartbeat_sent = started_at
|
52
53
|
begin
|
53
54
|
loop do
|
54
|
-
sleep
|
55
|
+
sleep 0.5
|
56
|
+
|
57
|
+
break if has_quit
|
55
58
|
|
56
59
|
# First check if it has exceeded it's wall clock time allowance
|
57
60
|
running_for = Time.now - started_at
|
@@ -60,6 +63,11 @@ module Runaway
|
|
60
63
|
child_pid, running_for, must_quit_within])
|
61
64
|
end
|
62
65
|
|
66
|
+
# Then check if it is time to poke it with a heartbeat
|
67
|
+
at = Time.now
|
68
|
+
next if (at - last_heartbeat_sent) < heartbeat_interval
|
69
|
+
last_heartbeat_sent = at
|
70
|
+
|
63
71
|
# Then send it the USR2 as a "ping", and expect a "pong" in
|
64
72
|
# the form of a pipe write. If the pipe is still not readable
|
65
73
|
# after a certain time, we assume the process has hung.
|
data/runaway.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: runaway 1.0.
|
5
|
+
# stub: runaway 1.0.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "runaway"
|
9
|
-
s.version = "1.0.
|
9
|
+
s.version = "1.0.1"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Julik Tarkhanov"]
|
14
|
-
s.date = "2016-
|
14
|
+
s.date = "2016-03-01"
|
15
15
|
s.description = "Spin off blocks in child processes and make sure they terminate on time"
|
16
16
|
s.email = "me@julik.nl"
|
17
17
|
s.extra_rdoc_files = [
|
data/spec/runaway_spec.rb
CHANGED
@@ -17,15 +17,17 @@ describe "Runaway" do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
context 'with a process that
|
20
|
+
context 'with a process that exceeds the maximum runtime' do
|
21
21
|
it 'terminates the process' do
|
22
|
+
start_at = Time.now
|
22
23
|
expect {
|
23
24
|
Runaway.spin(must_quit_within: 3) do
|
24
|
-
sleep
|
25
|
+
sleep 30
|
25
26
|
end
|
26
27
|
}.to raise_error {|err|
|
27
28
|
expect(err).to be_kind_of(Runaway::RuntimeExceeded)
|
28
|
-
expect(err.message).to match(/\d+ did not terminate after
|
29
|
+
expect(err.message).to match(/\d+ did not terminate after \d+ secs \(limited to 3 secs\)/)
|
30
|
+
expect(Time.now - start_at).to be < 5 # Ensure it was killed quickly
|
29
31
|
}
|
30
32
|
end
|
31
33
|
end
|
@@ -41,13 +43,26 @@ describe "Runaway" do
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
46
|
+
context 'when a process terminates before the first heartbeat has to be dispatched' do
|
47
|
+
it 'just returns :done' do
|
48
|
+
t = Time.now
|
49
|
+
return_token = Runaway.spin(heartbeat_interval: 5) { sleep 0.1 }
|
50
|
+
expect(return_token).to eq(:done)
|
51
|
+
delta = Time.now - t
|
52
|
+
expect(delta).to be < 2
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
44
56
|
context 'when a process stops responding to heartbeats' do
|
45
|
-
it 'raises an error' do
|
57
|
+
it 'kills it quickly and raises an error' do
|
58
|
+
t = Time.now
|
46
59
|
expect {
|
47
|
-
|
60
|
+
# Delete, then override the USR2 trap so that heartbeats do not get handled at all
|
61
|
+
Runaway.spin(heartbeat_interval: 0.8) { trap('USR2', 'DEFAULT'); trap('USR2') {}; sleep 45 }
|
48
62
|
}.to raise_error {|err|
|
49
63
|
expect(err).to be_kind_of(Runaway::HeartbeatTimeout)
|
50
|
-
expect(err.message).to match(/\d+ did not reply to heartbeat after
|
64
|
+
expect(err.message).to match(/\d+ did not reply to heartbeat after \d+ secs/)
|
65
|
+
expect(Time.now - t).to be < 5 # should really ahve killed it fast
|
51
66
|
}
|
52
67
|
end
|
53
68
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: runaway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|