terminator 0.4.3 → 0.4.4

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
@@ -2,10 +2,10 @@ NAME
2
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. but not very safe
7
- for misbehaving, downtrodden zombied out processes.
8
-
5
+ An external timeout mechanism based on processes and signals. Safe for
6
+ system calls. Safe for minors. but not very safe for misbehaving,
7
+ downtrodden zombied out processes.
8
+
9
9
  DESCRIPTION
10
10
  Terminator is a solution to the problem of 'how am I meant to kill a
11
11
  system call in Ruby!?'
@@ -43,6 +43,16 @@ HOW IT WORKS
43
43
 
44
44
  So really it is a race of who is going to win?
45
45
 
46
+ Word of warning though. Terminator is not subtle. Don't expect it to split
47
+ hairs. Trying to give a process that takes about 1 second to complete, a
48
+ 2 second terminator... well... odds are 50/50 on who is going to make it.
49
+
50
+ If you have a 1 second process, give it 3 seconds to complete. Arnie doesn't
51
+ much care for casualties of war.
52
+
53
+ Another word of warning, if using Terminator inside a loop, it is possible
54
+ to exceed your open file limit. I have safely tested looping 1000 times
55
+
46
56
  INSTALL
47
57
  gem install terminator
48
58
 
@@ -52,7 +62,13 @@ URIS
52
62
 
53
63
  HISTORY
54
64
  0.4.2
55
- initial version
65
+ * initial version (ara)
66
+ 0.4.3
67
+ * added some extra specs and test cases (mikel)
68
+ 0.4.4
69
+ * made terminator loop safe. 1000.times { Terminator.timeout(1) do true; end }
70
+ now works (mikel)
71
+ * added more test cases (mikel)
56
72
 
57
73
  AUTHORS
58
74
  ara.t.howard - ara.t.howard@gmail.com
@@ -128,3 +144,26 @@ SAMPLES
128
144
  signaled @ 1221026177
129
145
  woke up @ 1221026178
130
146
 
147
+
148
+ <========< samples/e.rb >========>
149
+
150
+ ~ > cat samples/e.rb
151
+
152
+ require 'terminator'
153
+
154
+ puts "Looping 1000 times on the terminator..."
155
+ success = false
156
+ 1.upto(1000) do |i|
157
+ success = false
158
+ Terminator.terminate(1) do
159
+ success = true
160
+ end
161
+ print "\b\b\b#{i}"
162
+ end
163
+ puts "\nI was successful" if success
164
+
165
+ ~ > ruby samples/e.rb
166
+
167
+ Looping 1000 times on the terminator...
168
+ 1000
169
+ I was successful
@@ -0,0 +1,307 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Module: Terminator</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="classHeader">
50
+ <table class="header-table">
51
+ <tr class="top-aligned-row">
52
+ <td><strong>Module</strong></td>
53
+ <td class="class-name-in-header">Terminator</td>
54
+ </tr>
55
+ <tr class="top-aligned-row">
56
+ <td><strong>In:</strong></td>
57
+ <td>
58
+ <a href="../files/lib/terminator_rb.html">
59
+ lib/terminator.rb
60
+ </a>
61
+ <br />
62
+ </td>
63
+ </tr>
64
+
65
+ </table>
66
+ </div>
67
+ <!-- banner header -->
68
+
69
+ <div id="bodyContent">
70
+
71
+
72
+
73
+ <div id="contextContent">
74
+
75
+ <div id="description">
76
+ <h1><a href="Terminator.html">Terminator</a></h1>
77
+ <h2>Synopsis</h2>
78
+ <p>
79
+ An external timeout mechanism based on processes and signals. Safe for
80
+ system calls. Safe for minors. but not very safe for misbehaving,
81
+ downtrodden zombied out processes.
82
+ </p>
83
+ <h2>Description</h2>
84
+ <p>
85
+ <a href="Terminator.html">Terminator</a> is a solution to the problem of
86
+ &#8216;how am I meant to kill a system call in Ruby!?&#8217;
87
+ </p>
88
+ <p>
89
+ Ruby (at least MRI) uses green threads to &quot;multitask&quot;. This means
90
+ that there is really only ever one ruby process running which then splits
91
+ up it&#8216;s processor time between all of it&#8216;s threads internally.
92
+ </p>
93
+ <p>
94
+ The processor then only has to deal with one ruby process and the ruby
95
+ process deals with all it&#8216;s threads. There are pros and cons to this
96
+ method, but that is not the point of this library.
97
+ </p>
98
+ <p>
99
+ The point is, that if you make a system call to an external resource from
100
+ ruby, then the kernel will go and make that call for ruby and NOT COME BACK
101
+ to ruby until that system call completes or fails. This can take a very
102
+ long time and is why your feeble attempts at using ruby&#8216;s internal
103
+ &quot;Timeout&quot; command has failed miserably at timing out your
104
+ external web service, database or network connections.
105
+ </p>
106
+ <p>
107
+ You see, Ruby just doesn&#8216;t get a chance to do anything as the kernel
108
+ goes &quot;I&#8216;m not going to talk to you again until your system calls
109
+ complete&quot;. Sort of a no win situation for Ruby.
110
+ </p>
111
+ <p>
112
+ That&#8216;s where <a href="Terminator.html">Terminator</a> comes in. Like
113
+ Arnie, he will come back. No matter what, and complete his mission, unless
114
+ he gets aborted before his timeout, you can trust <a
115
+ href="Terminator.html">Terminator</a> to thoroughly and without remorse,
116
+ nuke your misbehaving and timing out ruby processes efficiently, and
117
+ quickly.
118
+ </p>
119
+ <h2>How it Works</h2>
120
+ <p>
121
+ Basically we create a new terminator ruby process, separate to the existing
122
+ running ruby process that has a simple command of sleep for x seconds, and
123
+ then do a process TERM on the PID of the original ruby process that created
124
+ it.
125
+ </p>
126
+ <p>
127
+ If your process finishes before the timeout, it will kill the <a
128
+ href="Terminator.html">Terminator</a> first.
129
+ </p>
130
+ <p>
131
+ So really it is a race of who is going to win?
132
+ </p>
133
+ <p>
134
+ Word of warning though. <a href="Terminator.html">Terminator</a> is not
135
+ subtle. Don&#8216;t expect it to split hairs. Trying to give a process that
136
+ takes about 1 second to complete, a 2 second terminator&#8230; well&#8230;
137
+ odds are 50/50 on who is going to make it.
138
+ </p>
139
+ <p>
140
+ If you have a 1 second process, give it 3 seconds to complete. Arnie
141
+ doesn&#8216;t much care for casualties of war.
142
+ </p>
143
+ <p>
144
+ Another word of warning, if using <a href="Terminator.html">Terminator</a>
145
+ inside a loop, it is possible to exceed your open file limit. I have safely
146
+ tested looping 1000 times
147
+ </p>
148
+ <h2>URIS</h2>
149
+ <ul>
150
+ <li><a href="http://codeforpeople.com/lib/ruby">codeforpeople.com/lib/ruby</a>
151
+
152
+ </li>
153
+ <li><a
154
+ href="http://rubyforge.org/projects/codeforpeople">rubyforge.org/projects/codeforpeople</a>
155
+
156
+ </li>
157
+ </ul>
158
+ <h2>Usage</h2>
159
+ <p>
160
+ The terminator library is simple to use.
161
+ </p>
162
+ <pre>
163
+ require 'terminator'
164
+ Terminator.terminate(1) do
165
+ sleep 4
166
+ puts(&quot;I will never print&quot;)
167
+ end
168
+ #=&gt; Terminator::Error: Timeout out after 1s
169
+ </pre>
170
+ <p>
171
+ The above code snippet will raise a <a
172
+ href="Terminator/Error.html">Terminator::Error</a> as the
173
+ terminator&#8216;s timeout is 2 seconds and the block will take at least 4
174
+ to complete.
175
+ </p>
176
+ <p>
177
+ You can put error handling in with a simple begin / rescue block:
178
+ </p>
179
+ <pre>
180
+ require 'terminator'
181
+ begin
182
+ Terminator.terminate(1) do
183
+ sleep 4
184
+ puts(&quot;I will never print&quot;)
185
+ end
186
+ rescue
187
+ puts(&quot;I got terminated, but rescued myself.&quot;)
188
+ end
189
+ #=&gt; I got terminated, but rescued myself.
190
+ </pre>
191
+ <p>
192
+ The standard action on termination is to raise a <a
193
+ href="Terminator/Error.html">Terminator::Error</a>, however, this is just
194
+ an anonymous object that is called, so you can pass your own trap handling
195
+ by giving the terminator a lambda as an argument.
196
+ </p>
197
+ <pre>
198
+ require 'terminator'
199
+ custom_trap = lambda { eval(&quot;raise(RuntimeError, 'Oops... I failed...')&quot;) }
200
+ Terminator.terminate(:seconds =&gt; 1, :trap =&gt; custom_trap) do
201
+ sleep 10
202
+ end
203
+ #=&gt; RuntimeError: (eval):1:in `irb_binding': Oops... I failed...
204
+ </pre>
205
+
206
+ </div>
207
+
208
+
209
+ </div>
210
+
211
+ <div id="method-list">
212
+ <h3 class="section-bar">Methods</h3>
213
+
214
+ <div class="name-list">
215
+ <a href="#M000001">terminate</a>&nbsp;&nbsp;
216
+ </div>
217
+ </div>
218
+
219
+ </div>
220
+
221
+
222
+ <!-- if includes -->
223
+
224
+ <div id="section">
225
+
226
+ <div id="class-list">
227
+ <h3 class="section-bar">Classes and Modules</h3>
228
+
229
+ Class <a href="Terminator/Error.html" class="link">Terminator::Error</a><br />
230
+
231
+ </div>
232
+
233
+ <div id="constants-list">
234
+ <h3 class="section-bar">Constants</h3>
235
+
236
+ <div class="name-list">
237
+ <table summary="Constants">
238
+ <tr class="top-aligned-row context-row">
239
+ <td class="context-item-name">Version</td>
240
+ <td>=</td>
241
+ <td class="context-item-value">'0.4.4'</td>
242
+ </tr>
243
+ </table>
244
+ </div>
245
+ </div>
246
+
247
+
248
+
249
+
250
+
251
+
252
+ <!-- if method_list -->
253
+ <div id="methods">
254
+ <h3 class="section-bar">Public Instance methods</h3>
255
+
256
+ <div id="method-M000001" class="method-detail">
257
+ <a name="M000001"></a>
258
+
259
+ <div class="method-heading">
260
+ <a href="Terminator.src/M000001.html" target="Code" class="method-signature"
261
+ onclick="popupCode('Terminator.src/M000001.html');return false;">
262
+ <span class="method-name">terminate</span><span class="method-args">(options = {})</span>
263
+ </a>
264
+ </div>
265
+
266
+ <div class="method-description">
267
+ <p>
268
+ <a href="Terminator.html#M000001">Terminator.terminate</a> has two ways you
269
+ can call it. You can either just specify:
270
+ </p>
271
+ <pre>
272
+ Terminator.terminate(seconds) { code_to_execute }
273
+ </pre>
274
+ <p>
275
+ where seconds is an integer number greater than or equal to 1. If you pass
276
+ a float in on seconds, <a href="Terminator.html">Terminator</a> will call
277
+ to_i on it and convert it to an integer. This is because <a
278
+ href="Terminator.html">Terminator</a> is not a precise tool, due to it
279
+ calling a new ruby instance, and spawning a new process, relying on split
280
+ second accuracy is a folly.
281
+ </p>
282
+ <p>
283
+ If you want to pass in the block, please use:
284
+ </p>
285
+ <pre>
286
+ Terminator.terminate(:seconds =&gt; seconds, :trap =&gt; block) { code_to_execute }
287
+ </pre>
288
+ <p>
289
+ Where block is an anonymous method that gets called when the timeout
290
+ occurs.
291
+ </p>
292
+ </div>
293
+ </div>
294
+
295
+
296
+ </div>
297
+
298
+
299
+ </div>
300
+
301
+
302
+ <div id="validator-badges">
303
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
304
+ </div>
305
+
306
+ </body>
307
+ </html>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html>
7
+ <head>
8
+ <title>terminate (Terminator)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
11
+ </head>
12
+ <body class="standalone-code">
13
+ <pre><span class="ruby-comment cmt"># File lib/terminator.rb, line 120</span>
14
+ <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">terminate</span> <span class="ruby-identifier">options</span> = {}, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>
15
+ <span class="ruby-identifier">options</span> = { <span class="ruby-identifier">:seconds</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-constant">Float</span>(<span class="ruby-identifier">options</span>).<span class="ruby-identifier">to_i</span> } <span class="ruby-keyword kw">unless</span> <span class="ruby-constant">Hash</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">options</span>
16
+
17
+ <span class="ruby-identifier">seconds</span> = <span class="ruby-identifier">getopt</span> <span class="ruby-identifier">:seconds</span>, <span class="ruby-identifier">options</span>
18
+
19
+ <span class="ruby-identifier">raise</span> <span class="ruby-operator">::</span><span class="ruby-constant">Terminator</span><span class="ruby-operator">::</span><span class="ruby-constant">Error</span>, <span class="ruby-value str">&quot;Time to kill must be at least 1 second&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">seconds</span> <span class="ruby-operator">&gt;=</span> <span class="ruby-value">1</span>
20
+
21
+ <span class="ruby-identifier">trap</span> = <span class="ruby-identifier">getopt</span> <span class="ruby-identifier">:trap</span>, <span class="ruby-identifier">options</span>, <span class="ruby-identifier">lambda</span>{ <span class="ruby-identifier">eval</span>(<span class="ruby-node">&quot;raise(::Terminator::Error, 'Timeout out after #{ seconds }s')&quot;</span>, <span class="ruby-identifier">block</span>) }
22
+
23
+ <span class="ruby-identifier">handler</span> = <span class="ruby-constant">Signal</span>.<span class="ruby-identifier">trap</span>(<span class="ruby-identifier">signal</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">trap</span>)
24
+
25
+ <span class="ruby-identifier">terminator_pid</span> = <span class="ruby-identifier">plot_to_kill</span> <span class="ruby-identifier">pid</span>, <span class="ruby-identifier">:in</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">seconds</span>, <span class="ruby-identifier">:with</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">signal</span>
26
+
27
+ <span class="ruby-keyword kw">begin</span>
28
+ <span class="ruby-identifier">block</span>.<span class="ruby-identifier">call</span>
29
+ <span class="ruby-identifier">nuke_terminator</span>(<span class="ruby-identifier">terminator_pid</span>)
30
+ <span class="ruby-keyword kw">ensure</span>
31
+ <span class="ruby-constant">Signal</span>.<span class="ruby-identifier">trap</span>(<span class="ruby-identifier">signal</span>, <span class="ruby-identifier">handler</span>)
32
+ <span class="ruby-keyword kw">end</span>
33
+ <span class="ruby-keyword kw">end</span></pre>
34
+ </body>
35
+ </html>
@@ -0,0 +1,111 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Class: Terminator::Error</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="classHeader">
50
+ <table class="header-table">
51
+ <tr class="top-aligned-row">
52
+ <td><strong>Class</strong></td>
53
+ <td class="class-name-in-header">Terminator::Error</td>
54
+ </tr>
55
+ <tr class="top-aligned-row">
56
+ <td><strong>In:</strong></td>
57
+ <td>
58
+ <a href="../../files/lib/terminator_rb.html">
59
+ lib/terminator.rb
60
+ </a>
61
+ <br />
62
+ </td>
63
+ </tr>
64
+
65
+ <tr class="top-aligned-row">
66
+ <td><strong>Parent:</strong></td>
67
+ <td>
68
+ ::StandardError
69
+ </td>
70
+ </tr>
71
+ </table>
72
+ </div>
73
+ <!-- banner header -->
74
+
75
+ <div id="bodyContent">
76
+
77
+
78
+
79
+ <div id="contextContent">
80
+
81
+
82
+
83
+ </div>
84
+
85
+
86
+ </div>
87
+
88
+
89
+ <!-- if includes -->
90
+
91
+ <div id="section">
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ <!-- if method_list -->
101
+
102
+
103
+ </div>
104
+
105
+
106
+ <div id="validator-badges">
107
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
108
+ </div>
109
+
110
+ </body>
111
+ </html>