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 CHANGED
@@ -1,10 +1,48 @@
1
1
  NAME
2
- terminator
2
+ Terminator
3
3
 
4
4
  SYNOPSIS
5
- an external timeout mechanism based on processes and signals. safe on
6
- windows. safe for system calls. safe for minors.
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 with
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
File without changes
data/install.rb CHANGED
File without changes
@@ -4,13 +4,16 @@ require 'tempfile'
4
4
  require 'fattr'
5
5
 
6
6
  module Terminator
7
- Version = '0.4.2'
7
+ Version = '0.4.3'
8
8
 
9
9
  def terminate options = {}, &block
10
- options = { :seconds => Float(options).to_i } unless Hash === options
10
+ options = { :seconds => Float(options).to_f } unless Hash === options
11
11
 
12
12
  seconds = getopt :seconds, options
13
- trap = getopt :trap, options, lambda{ eval("raise(::Terminator::Error, '#{ seconds }s')", block) }
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.2
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-10 00:00:00 -06:00
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/terminator.rb
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.2.0
69
+ rubygems_version: 1.0.1
70
70
  signing_key:
71
71
  specification_version: 2
72
72
  summary: terminator
@@ -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
- }