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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2394ae85e1bcf9ff2046d3892f33ece782e2e22
4
- data.tar.gz: 4838053519c1500f34bef114eb374a2b05af9833
3
+ metadata.gz: ee88a2e47d1bf2847893a4b258d236efcfff3fae
4
+ data.tar.gz: f3edef5cc5fae9363f1d56978c0465b56faa0a24
5
5
  SHA512:
6
- metadata.gz: 50c6402a8d00358139c9e93e37a02a4d34819e63ea6c7f00b27e6b544107af71d1a60b14671c2115c6d04565fe0d3a4f0310c2c79a3f100c453436f61b2e0a24
7
- data.tar.gz: 8555a4a081a964299e1866ee00bb0728984a87303add7f89b708a26429006f28721064d21bbe7e95dfd5f0a4106590de288a491e68e0796eb5170f87bad65f9a
6
+ metadata.gz: 0489708f0657aeb6e7b91c7f23e2007974d22577afe01b9c04b2dca6d12a9fcdbdf68cdbb965b75970351333eab45ec6a1599f3d34a3727abda9f8daa47ab248
7
+ data.tar.gz: 34eeca38ad28dfb7b205a40b9517f3b3123683a9fdd466031b848bd1780f9b67e1b477c3a1d10104b412b36ee80df21c33e1ab2dfcf5af799e0b0f86963d3ede
@@ -1,7 +1,7 @@
1
1
  require 'securerandom'
2
2
 
3
3
  module Runaway
4
- VERSION = '1.0.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 heartbeat_interval
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.
@@ -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.0 ruby lib
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.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-02-26"
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 = [
@@ -17,15 +17,17 @@ describe "Runaway" do
17
17
  end
18
18
  end
19
19
 
20
- context 'with a process that sleeps for too long' do
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 4
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 4 secs \(limited to 3 secs\)/)
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
- Runaway.spin { trap('USR2', 'DEFAULT'); trap('USR2') {}; sleep 7 }
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 4 secs/)
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.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-02-26 00:00:00.000000000 Z
11
+ date: 2016-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec