timeout-interrupt 0.2.0 → 0.2.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.
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: