terminator 0.4.2 → 0.4.3
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.
- data/README +43 -5
- data/gemspec.rb +0 -0
- data/gen_readme.rb +0 -0
- data/install.rb +0 -0
- data/lib/terminator.rb +6 -3
- data/spec/terminator_spec.rb +135 -0
- data/terminator-0.4.2.gem +0 -0
- metadata +5 -5
- data/spec/terminator.rb +0 -16
data/README
CHANGED
@@ -1,10 +1,48 @@
|
|
1
1
|
NAME
|
2
|
-
|
2
|
+
Terminator
|
3
3
|
|
4
4
|
SYNOPSIS
|
5
|
-
|
6
|
-
windows.
|
7
|
-
|
5
|
+
An external timeout mechanism based on processes and signals. Safe on
|
6
|
+
windows. Safe for system calls. Safe for minors. but not very safe
|
7
|
+
for misbehaving, downtrodden zombied out processes.
|
8
|
+
|
9
|
+
DESCRIPTION
|
10
|
+
Terminator is a solution to the problem of 'how am I meant to kill a
|
11
|
+
system call in Ruby!?'
|
12
|
+
|
13
|
+
Ruby (at least MRI) uses green threads to "multitask". This means that
|
14
|
+
there is really only ever one ruby process running which then splits up
|
15
|
+
it's processor time between all of it's threads internally.
|
16
|
+
|
17
|
+
The processor then only has to deal with one ruby process and the ruby
|
18
|
+
process deals with all it's threads. There are pros and cons to this
|
19
|
+
method, but that is not the point of this library.
|
20
|
+
|
21
|
+
The point is, that if you make a system call to an external resource from
|
22
|
+
ruby, then the kernel will go and make that call for ruby and NOT COME BACK
|
23
|
+
to ruby until that system call completes or fails. This can take a very
|
24
|
+
long time and is why your feeble attempts at using ruby's internal "Timeout"
|
25
|
+
command has failed miserably at timing out your external web service, database
|
26
|
+
or network connections.
|
27
|
+
|
28
|
+
You see, Ruby just doesn't get a chance to do anything as the kernel goes
|
29
|
+
"I'm not going to talk to you again until your system calls complete". Sort
|
30
|
+
of a no win situation for Ruby.
|
31
|
+
|
32
|
+
That's where Terminator comes in. Like Arnie, he will come back. No matter
|
33
|
+
what, and complete his mission, unless he gets aborted before his timeout,
|
34
|
+
you can trust Terminator to thoroughly and without remorse, nuke your
|
35
|
+
misbehaving and timing out ruby processes efficiently, and quickly.
|
36
|
+
|
37
|
+
HOW IT WORKS
|
38
|
+
Basically we create a new terminator ruby process, separate to the existing
|
39
|
+
running ruby process that has a simple command of sleep for x seconds, and then
|
40
|
+
do a process TERM on the PID of the original ruby process that created it.
|
41
|
+
|
42
|
+
If your process finishes before the timeout, it will kill the Terminator first.
|
43
|
+
|
44
|
+
So really it is a race of who is going to win?
|
45
|
+
|
8
46
|
INSTALL
|
9
47
|
gem install terminator
|
10
48
|
|
@@ -14,7 +52,7 @@ URIS
|
|
14
52
|
|
15
53
|
HISTORY
|
16
54
|
0.4.2
|
17
|
-
initial version
|
55
|
+
initial version
|
18
56
|
|
19
57
|
AUTHORS
|
20
58
|
ara.t.howard - ara.t.howard@gmail.com
|
data/gemspec.rb
CHANGED
File without changes
|
data/gen_readme.rb
CHANGED
File without changes
|
data/install.rb
CHANGED
File without changes
|
data/lib/terminator.rb
CHANGED
@@ -4,13 +4,16 @@ require 'tempfile'
|
|
4
4
|
require 'fattr'
|
5
5
|
|
6
6
|
module Terminator
|
7
|
-
Version = '0.4.
|
7
|
+
Version = '0.4.3'
|
8
8
|
|
9
9
|
def terminate options = {}, &block
|
10
|
-
options = { :seconds => Float(options).
|
10
|
+
options = { :seconds => Float(options).to_f } unless Hash === options
|
11
11
|
|
12
12
|
seconds = getopt :seconds, options
|
13
|
-
|
13
|
+
|
14
|
+
raise ::Terminator::Error, "Time to kill must be greater than 0" unless seconds > 0
|
15
|
+
|
16
|
+
trap = getopt :trap, options, lambda{ eval("raise(::Terminator::Error, 'Timeout out after #{ seconds }s')", block) }
|
14
17
|
|
15
18
|
handler = Signal.trap(signal, &trap)
|
16
19
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#! /usr/bin/env bacon
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bacon'
|
5
|
+
|
6
|
+
alias :doing :lambda
|
7
|
+
|
8
|
+
describe Terminator do
|
9
|
+
|
10
|
+
describe "being given a contract to terminate" do
|
11
|
+
it "should not complain about it" do
|
12
|
+
doing { Terminator.terminate(1) { "Hello" } }.should_not raise_error
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should not accept an expired contract" do
|
16
|
+
doing { Terminator.terminate(0) { "Hello" } }.should.raise(Terminator::Error)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should not accept a late contract" do
|
20
|
+
doing { Terminator.terminate(-0.1) { "Hello" } }.should.raise(Terminator::Error)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should handle fractions of seconts" do
|
24
|
+
failed = false
|
25
|
+
Terminator.terminate(0.3) do
|
26
|
+
failed = true
|
27
|
+
end
|
28
|
+
failed.should.be.false
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "handling contracts" do
|
34
|
+
it "should not kill it's mark if the mark completes" do
|
35
|
+
failed = false
|
36
|
+
Terminator.terminate(0.01) do
|
37
|
+
failed = true
|
38
|
+
end
|
39
|
+
failed.should.be.false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not terminate it's mark until the time is up" do
|
43
|
+
failed = false
|
44
|
+
Terminator.terminate(1) do
|
45
|
+
sleep 0.9
|
46
|
+
failed = true
|
47
|
+
end
|
48
|
+
failed.should.be.false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should handle multiple overlapping contracts gracefully" do
|
52
|
+
first_job = false
|
53
|
+
second_job = false
|
54
|
+
third_job = false
|
55
|
+
|
56
|
+
Terminator.terminate(0.3) do
|
57
|
+
first_job = true
|
58
|
+
end
|
59
|
+
|
60
|
+
Terminator.terminate(0.3) do
|
61
|
+
second_job = true
|
62
|
+
end
|
63
|
+
|
64
|
+
Terminator.terminate(0.3) do
|
65
|
+
third_job = true
|
66
|
+
end
|
67
|
+
|
68
|
+
first_job.should.be.true
|
69
|
+
second_job.should.be.true
|
70
|
+
third_job.should.be.true
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be a surgical weapon only selectively destroying it's marks" do
|
74
|
+
first_job = false
|
75
|
+
second_job = false
|
76
|
+
|
77
|
+
begin
|
78
|
+
Terminator.terminate(0.3) do
|
79
|
+
sleep 0.4
|
80
|
+
first_job = true
|
81
|
+
end
|
82
|
+
rescue
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
Terminator.terminate(0.3) do
|
87
|
+
second_job = true
|
88
|
+
end
|
89
|
+
|
90
|
+
first_job.should.be.false
|
91
|
+
second_job.should.be.true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should a surgical weapon only selectively destroying it's marks - backwards" do
|
95
|
+
first_job = false
|
96
|
+
second_job = false
|
97
|
+
|
98
|
+
Terminator.terminate(0.3) do
|
99
|
+
first_job = true
|
100
|
+
end
|
101
|
+
|
102
|
+
begin
|
103
|
+
Terminator.terminate(0.3) do
|
104
|
+
sleep 0.4
|
105
|
+
second_job = true
|
106
|
+
end
|
107
|
+
rescue
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
first_job.should.be.true
|
112
|
+
second_job.should.be.false
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should accept an optional trap handler" do
|
117
|
+
trap = lambda{ 'You failed me again!' }
|
118
|
+
|
119
|
+
doing {
|
120
|
+
Terminator.terminate(0.001, :trap => trap) do
|
121
|
+
sleep 0.2
|
122
|
+
job = true
|
123
|
+
end }.should.raise(Terminator::Error)
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
BEGIN {
|
132
|
+
rootdir = File.split(File.expand_path(File.dirname(File.dirname(__FILE__))))
|
133
|
+
libdir = File.join(rootdir, 'lib')
|
134
|
+
require File.join(libdir, 'terminator')
|
135
|
+
}
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: terminator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ara T. Howard
|
@@ -9,12 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-09-
|
12
|
+
date: 2008-09-11 00:00:00 +10:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: fattr
|
17
|
-
type: :runtime
|
18
17
|
version_requirement:
|
19
18
|
version_requirements: !ruby/object:Gem::Requirement
|
20
19
|
requirements:
|
@@ -43,7 +42,8 @@ files:
|
|
43
42
|
- samples/c.rb
|
44
43
|
- samples/d.rb
|
45
44
|
- spec
|
46
|
-
- spec/
|
45
|
+
- spec/terminator_spec.rb
|
46
|
+
- terminator-0.4.2.gem
|
47
47
|
has_rdoc: false
|
48
48
|
homepage: http://codeforpeople.com/lib/ruby/terminator/
|
49
49
|
post_install_message:
|
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements: []
|
67
67
|
|
68
68
|
rubyforge_project: codeforpeople
|
69
|
-
rubygems_version: 1.
|
69
|
+
rubygems_version: 1.0.1
|
70
70
|
signing_key:
|
71
71
|
specification_version: 2
|
72
72
|
summary: terminator
|
data/spec/terminator.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#! /usr/bin/env bacon
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bacon'
|
5
|
-
|
6
|
-
describe Terminator do
|
7
|
-
it 'should have some tests' do
|
8
|
-
0b101010.should == 42
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
BEGIN {
|
13
|
-
rootdir = File.split(File.expand_path(File.dirname(File.dirname(__FILE__))))
|
14
|
-
libdir = File.join(rootdir, 'lib')
|
15
|
-
require File.join(libdir, 'terminator')
|
16
|
-
}
|