timeout-interrupt 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem 'ffi-libc'
7
7
  group :development do
8
8
  gem "shoulda"
9
9
  gem "yard"
10
+ gem "redcarpet"
10
11
  gem "rdoc"
11
12
  gem "bundler"
12
13
  gem "jeweler"
data/Gemfile.lock CHANGED
@@ -24,6 +24,7 @@ GEM
24
24
  rake (10.0.3)
25
25
  rdoc (4.0.0)
26
26
  json (~> 1.4)
27
+ redcarpet (2.2.2)
27
28
  shoulda (3.3.2)
28
29
  shoulda-context (~> 1.0.1)
29
30
  shoulda-matchers (~> 1.4.1)
@@ -45,6 +46,7 @@ DEPENDENCIES
45
46
  ffi-libc
46
47
  jeweler
47
48
  rdoc
49
+ redcarpet
48
50
  shoulda
49
51
  simplecov
50
52
  yard
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -1,40 +1,107 @@
1
1
  require 'ffi/libc'
2
2
  require 'timeout'
3
3
 
4
+ # Provided by ffi-libc-lib and extended by this library, if needed.
5
+ # Older version of ffi-libc does not provide {FFI::LibC.alarm}
4
6
  module FFI
5
7
  module LibC
8
+ # @!method alarm(seconds)
9
+ # Sets an alarm. After `seconds` it will send an ALRM-signal to this process.
10
+ #
11
+ # Predefined alarm will be reset and will forget.
12
+ # @note Older implementations of ffi-libc does not provide {alarm}, but we need it.
13
+ # So we detect, if it is not provided and attach it.
14
+ # @param seconds [0] Clears alarm.
15
+ # @param seconds [Integer] How many seconds should be waited, before ALRM-signal should be send?
16
+ # @return (nil)
6
17
  attach_function :alarm, [:uint], :uint unless FFI::LibC.respond_to? :alarm
7
18
  end
8
19
  end
9
20
 
21
+ # Helper module for `TimeoutInterrupt`
22
+ # @see TimeoutInterrupt
10
23
  module TimeoutInterruptSingleton
11
24
  class <<self
25
+ # Stores all timeouts.
26
+ #
27
+ # @param thread [nil] must be nil! Do not use it yet!
28
+ # @return [Hash< key(Integer): [at(Time), backtrace(Array<String>), exception(Exception)] >]
12
29
  def timeouts thread = nil
13
- @timeouts ||= Hash.new {|h,k| h[k] = [] }
14
- thread = Thread.current if thread.kind_of? Thread
30
+ @timeouts ||= Hash.new {|h,k| h[k] = {} }
31
+ thread = Thread.current unless thread.kind_of? Thread
15
32
  thread ? @timeouts[thread] : @timeouts
16
33
  end
17
34
 
35
+ # If there's a timed out timeout, it will raise its exception.
36
+ # Can be used for handling ALRM-signal.
37
+ # It will prepare the next timeout, too.
38
+ #
39
+ # The timeout will not removed from timeouts, because it is timed out, yet.
40
+ # First, if timeout-scope will be exit, it will be removed.
41
+ #
42
+ # @return [nil]
18
43
  def alarm_trap sig
44
+ raise_if_sb_timed_out
45
+ setup
46
+ end
47
+
48
+ # There is a timed out timeout? It will raise it!
49
+ # You need not to check it yourself, it will do it for you.
50
+ #
51
+ # @return [nil]
52
+ def raise_if_sb_timed_out
53
+ return if self.timeouts.empty?
19
54
  key, (at, bt, exception) = self.timeouts.min_by {|key,(at,bt,ex)| at }
20
55
  return if Time.now < at
21
56
  raise exception, 'execution expired', bt
22
57
  end
23
58
 
59
+ # Prepares the next timeout. Sets the trap and the shortest timeout as alarm.
60
+ #
61
+ # @return [nil]
24
62
  def setup
25
63
  if timeouts.empty?
26
64
  Signal.trap( 'ALRM') {}
27
65
  FFI::LibC.alarm 0
28
66
  else
29
- key, (at, bt) = timeouts.min_by {|key,(at,bt)| at }
30
- secs = (at - Time.now)
31
- alarm_trap 14 if 0 > secs
67
+ raise_if_sb_timed_out
32
68
  Signal.trap 'ALRM', &method( :alarm_trap)
33
- FFI::LibC.alarm secs.to_i+1
69
+ key, (at, bt) = timeouts.min_by {|key,(at,bt)| at }
70
+ FFI::LibC.alarm (at - Time.now).to_i + 1
34
71
  end
72
+ nil
35
73
  end
36
74
 
37
- def timeout seconds = nil, exception = nil
75
+ # Creates a timeout and calls your block, which has to finish before timeout occurs.
76
+ #
77
+ # @param seconds [Integer] In `seconds` Seconds, it should raise a timeout, if not finished.
78
+ # @param seconds [nil] Everything will be ignored and
79
+ # it will call {setup} for checking and preparing next known timeout.
80
+ # @param exception [Exception] which will be raised if timed out.
81
+ # @param exception [nil] `TimeoutInterrupt::Error` will be used to raise.
82
+ # @param block [Proc] Will be called and should finish its work before it timed out.
83
+ # @param block [nil] Nothing will happen, instead it will return a Proc,
84
+ # which can be called with a block to use the timeout.
85
+ # @return If block given, the returned value of your block.
86
+ # Or if not, it will return a Proc, which will expect a Proc if called.
87
+ # This Proc has no arguments and will prepare a timeout, like if you had given a block.
88
+ #
89
+ # You can rescue `Timeout::Error`, instead `TimeoutInterrupt::Error`, it will work too.
90
+ #
91
+ # It will call your given block, which has `seconds` seconds to end.
92
+ # If you want to prepare a timeout, which should be used many times,
93
+ # without giving `seconds` and `exception`, you can omit the block,
94
+ # so, `TimeoutInterruptSingleton#timeout` will return a `Proc`, which want to have the block.
95
+ #
96
+ # There is a problem with scoped timeouts. If you rescue a timeout in an other timeout,
97
+ # it's possible, that the other timeout will never timeout, because both are timed out at once.
98
+ # Than you need to call `TimeoutInterruptSingleton#timeout` without arguments.
99
+ # It will prepare the next timeout or it will raise it directy, if timed out.
100
+ #
101
+ # @see TimeoutInterrupt.timeout
102
+ # @see TimeoutInterrupt#timeout
103
+ # @raise exception
104
+ def timeout seconds = nil, exception = nil, &block
38
105
  return setup if seconds.nil?
39
106
  seconds = seconds.to_i
40
107
  exception ||= TimeoutInterrupt::Error
@@ -59,15 +126,82 @@ module TimeoutInterruptSingleton
59
126
  end
60
127
  end
61
128
 
129
+ # Can be included, or used directly.
130
+ # In both cases, it provides {#timeout}.
131
+ #
132
+ # @see TimeoutInterruptSingleton
62
133
  module TimeoutInterrupt
134
+ # The {TimeoutInterrupt::Error} is the default exception, which will be raised,
135
+ # if something will time out.
136
+ # Its base-class is {Timeout::Error}, so you can replace {Timeout} by {TimeoutInterrupt} without
137
+ # replacing your `rescue Timeout::Error`, but you can.
63
138
  class Error < Timeout::Error
64
139
  end
65
140
 
66
- def self.timeout seconds = nil, exception = nil, &e
67
- TimeoutInterruptSingleton.timeout seconds, exception, &e
141
+ # Creates a timeout and calls your block, which has to finish before timeout occurs.
142
+ #
143
+ # @param seconds [Integer] In `seconds` Seconds, it should raise a timeout, if not finished.
144
+ # @param seconds [nil] Everything will be ignored and
145
+ # it will call {TimeoutInterruptSingleton.setup} for checking and preparing next known timeout.
146
+ # @param exception [Exception] which will be raised if timed out.
147
+ # @param exception [nil] `TimeoutInterrupt::Error` will be used to raise.
148
+ # @param block [Proc] Will be called and should finish its work before it timed out.
149
+ # @param block [nil] Nothing will happen, instead it will return a Proc,
150
+ # which can be called with a block to use the timeout.
151
+ # @return If block given, the returned value of your block.
152
+ # Or if not, it will return a Proc, which will expect a Proc if called.
153
+ # This Proc has no arguments and will prepare a timeout, like if you had given a block.
154
+ #
155
+ # You can rescue `Timeout::Error`, instead `TimeoutInterrupt::Error`, it will work too.
156
+ #
157
+ # It will call your given block, which has `seconds` seconds to end.
158
+ # If you want to prepare a timeout, which should be used many times,
159
+ # without giving `seconds` and `exception`, you can omit the block,
160
+ # so, `TimeoutInterruptSingleton#timeout` will return a `Proc`, which want to have the block.
161
+ #
162
+ # There is a problem with scoped timeouts. If you rescue a timeout in an other timeout,
163
+ # it's possible, that the other timeout will never timeout, because both are timed out at once.
164
+ # Than you need to call `TimeoutInterruptSingleton#timeout` without arguments.
165
+ # It will prepare the next timeout or it will raise it directy, if timed out.
166
+ #
167
+ # @see TimeoutInterrupt#timeout
168
+ # @see TimeoutInterruptSingleton.timeout
169
+ # @raise exception
170
+ def self.timeout seconds = nil, exception = nil, &block
171
+ TimeoutInterruptSingleton.timeout seconds, exception, &block
68
172
  end
69
173
 
70
- def timeout seconds = nil, exception = nil, &e
71
- TimeoutInterruptSingleton.timeout seconds, exception, &e
174
+ # Creates a timeout and calls your block, which has to finish before timeout occurs.
175
+ #
176
+ # @param seconds [Integer] In `seconds` Seconds, it should raise a timeout, if not finished.
177
+ # @param seconds [nil] Everything will be ignored and
178
+ # it will call {TimeoutInterruptSingleton.setup} for checking and preparing next known timeout.
179
+ # @param exception [Exception] which will be raised if timed out.
180
+ # @param exception [nil] `TimeoutInterrupt::Error` will be used to raise.
181
+ # @param block [Proc] Will be called and should finish its work before it timed out.
182
+ # @param block [nil] Nothing will happen, instead it will return a Proc,
183
+ # which can be called with a block to use the timeout.
184
+ # @return If block given, the returned value of your block.
185
+ # Or if not, it will return a Proc, which will expect a Proc if called.
186
+ # This Proc has no arguments and will prepare a timeout, like if you had given a block.
187
+ #
188
+ # You can rescue `Timeout::Error`, instead `TimeoutInterrupt::Error`, it will work too.
189
+ #
190
+ # It will call your given block, which has `seconds` seconds to end.
191
+ # If you want to prepare a timeout, which should be used many times,
192
+ # without giving `seconds` and `exception`, you can omit the block,
193
+ # so, `TimeoutInterruptSingleton#timeout` will return a `Proc`, which want to have the block.
194
+ #
195
+ # There is a problem with scoped timeouts. If you rescue a timeout in an other timeout,
196
+ # it's possible, that the other timeout will never timeout, because both are timed out at once.
197
+ # Than you need to call `TimeoutInterruptSingleton#timeout` without arguments.
198
+ # It will prepare the next timeout or it will raise it directy, if timed out.
199
+ #
200
+ # @note This method is useful, if you `include TimeoutInterrupt`. You can call it directly.
201
+ # @see TimeoutInterrupt.timeout
202
+ # @see TimeoutInterruptSingleton.timeout
203
+ # @raise exception
204
+ def timeout seconds = nil, exception = nil, &block
205
+ TimeoutInterruptSingleton.timeout seconds, exception, &block
72
206
  end
73
207
  end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "timeout-interrupt"
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Denis Knauf"]
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_runtime_dependency(%q<ffi-libc>, [">= 0"])
43
43
  s.add_development_dependency(%q<shoulda>, [">= 0"])
44
44
  s.add_development_dependency(%q<yard>, [">= 0"])
45
+ s.add_development_dependency(%q<redcarpet>, [">= 0"])
45
46
  s.add_development_dependency(%q<rdoc>, [">= 0"])
46
47
  s.add_development_dependency(%q<bundler>, [">= 0"])
47
48
  s.add_development_dependency(%q<jeweler>, [">= 0"])
@@ -50,6 +51,7 @@ Gem::Specification.new do |s|
50
51
  s.add_dependency(%q<ffi-libc>, [">= 0"])
51
52
  s.add_dependency(%q<shoulda>, [">= 0"])
52
53
  s.add_dependency(%q<yard>, [">= 0"])
54
+ s.add_dependency(%q<redcarpet>, [">= 0"])
53
55
  s.add_dependency(%q<rdoc>, [">= 0"])
54
56
  s.add_dependency(%q<bundler>, [">= 0"])
55
57
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -59,6 +61,7 @@ Gem::Specification.new do |s|
59
61
  s.add_dependency(%q<ffi-libc>, [">= 0"])
60
62
  s.add_dependency(%q<shoulda>, [">= 0"])
61
63
  s.add_dependency(%q<yard>, [">= 0"])
64
+ s.add_dependency(%q<redcarpet>, [">= 0"])
62
65
  s.add_dependency(%q<rdoc>, [">= 0"])
63
66
  s.add_dependency(%q<bundler>, [">= 0"])
64
67
  s.add_dependency(%q<jeweler>, [">= 0"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeout-interrupt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2013-03-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi-libc
16
- requirement: &79897400 !ruby/object:Gem::Requirement
16
+ requirement: &78508080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *79897400
24
+ version_requirements: *78508080
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: shoulda
27
- requirement: &79918180 !ruby/object:Gem::Requirement
27
+ requirement: &78507820 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *79918180
35
+ version_requirements: *78507820
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: yard
38
- requirement: &79914220 !ruby/object:Gem::Requirement
38
+ requirement: &78507570 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *79914220
46
+ version_requirements: *78507570
47
+ - !ruby/object:Gem::Dependency
48
+ name: redcarpet
49
+ requirement: &78507280 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *78507280
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: rdoc
49
- requirement: &79910520 !ruby/object:Gem::Requirement
60
+ requirement: &78506950 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *79910520
68
+ version_requirements: *78506950
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: bundler
60
- requirement: &79907200 !ruby/object:Gem::Requirement
71
+ requirement: &78505780 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *79907200
79
+ version_requirements: *78505780
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: jeweler
71
- requirement: &79905270 !ruby/object:Gem::Requirement
82
+ requirement: &78505320 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: '0'
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *79905270
90
+ version_requirements: *78505320
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: simplecov
82
- requirement: &79904230 !ruby/object:Gem::Requirement
93
+ requirement: &78505050 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,7 +98,7 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *79904230
101
+ version_requirements: *78505050
91
102
  description: Timeout-lib, which interrupts everything, also systemcalls. It uses libc-alarm.
92
103
  email: Denis.Knauf@gmail.com
93
104
  executables: []
@@ -122,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
133
  version: '0'
123
134
  segments:
124
135
  - 0
125
- hash: -567688307
136
+ hash: -241597663
126
137
  required_rubygems_version: !ruby/object:Gem::Requirement
127
138
  none: false
128
139
  requirements: