terminator 0.4.4 → 1.0.0

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTlkMmUwNjVjYTk5MDUzNzZiYWQ4MTNiMjdiZTUyNWUxNTY5OWFkYQ==
5
+ data.tar.gz: !binary |-
6
+ ZjZiYjdmZTg4YmIwYmZjNTZlMzQ3OWUxZWJkMjFkMzk1ZmMzNzQ5Zg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ Mzc3NWNjNWNiNGZkNjhkZGVjYmQxNjBiM2I1ODg4NmNlNmIxOGI0MTM3NDNm
10
+ MzhlODIyNTc4ZGM1NDNjZWE3ZmM3NWM2ZWQzYTg1MzFjZjQxMTMzYzM3M2Mx
11
+ MDU1OGM1OTllNTljMDNiN2U5MzY0NzcxYWZkN2Q0NWY5N2UyNDE=
12
+ data.tar.gz: !binary |-
13
+ MjcwZjYyMTg0ZTA5ZWNjNWNhZTllOWNhMmI4ZGE2OGZiYmM5NjdmODk3Mjhj
14
+ NDM2ZGMwOTdhMzdmZTRlMjA3OWU5NjQ3OTkxMjg4ODhiZjY4ZWJiNGNiYjlj
15
+ YWJiODFkZTc0MzE1YTdlYjAwM2MwZmViZjRkOTUyM2IyMmQ5OTI=
data/README CHANGED
@@ -1,58 +1,10 @@
1
1
  NAME
2
- Terminator
2
+ terminator
3
3
 
4
4
  SYNOPSIS
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
- 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
-
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
-
5
+ an external timeout mechanism based on processes and signals. safe on
6
+ windows. safe for system calls. safe for minors.
7
+
56
8
  INSTALL
57
9
  gem install terminator
58
10
 
@@ -61,14 +13,11 @@ URIS
61
13
  http://rubyforge.org/projects/codeforpeople
62
14
 
63
15
  HISTORY
16
+ 1.0.0
17
+ cleanup for 1.9
18
+
64
19
  0.4.2
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)
20
+ initial version with
72
21
 
73
22
  AUTHORS
74
23
  ara.t.howard - ara.t.howard@gmail.com
@@ -88,8 +37,17 @@ SAMPLES
88
37
 
89
38
  ~ > ruby samples/a.rb
90
39
 
91
- samples/a.rb:3: 2s (Terminator::Error)
92
- from samples/a.rb:3
40
+ samples/a.rb:3:in `<main>': Timeout out after 2.0s (Terminator::Error)
41
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:127:in `eval'
42
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:127:in `block in terminate'
43
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:129:in `call'
44
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:129:in `block in terminate'
45
+ from samples/a.rb:4:in `call'
46
+ from samples/a.rb:4:in `sleep'
47
+ from samples/a.rb:4:in `block in <main>'
48
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:136:in `call'
49
+ from /Users/ahoward/git/ahoward/terminator/lib/terminator.rb:136:in `terminate'
50
+ from samples/a.rb:3:in `<main>'
93
51
 
94
52
 
95
53
  <========< samples/b.rb >========>
@@ -141,8 +99,8 @@ SAMPLES
141
99
 
142
100
  ~ > ruby samples/d.rb
143
101
 
144
- signaled @ 1221026177
145
- woke up @ 1221026178
102
+ signaled @ 1376702274
103
+ woke up @ 1376702275
146
104
 
147
105
 
148
106
  <========< samples/e.rb >========>
@@ -150,7 +108,7 @@ SAMPLES
150
108
  ~ > cat samples/e.rb
151
109
 
152
110
  require 'terminator'
153
-
111
+
154
112
  puts "Looping 1000 times on the terminator..."
155
113
  success = false
156
114
  1.upto(1000) do |i|
@@ -158,12 +116,12 @@ SAMPLES
158
116
  Terminator.terminate(1) do
159
117
  success = true
160
118
  end
161
- print "\b\b\b#{i}"
162
119
  end
163
- puts "\nI was successful" if success
120
+ puts "\nsuccess!" if success
164
121
 
165
122
  ~ > ruby samples/e.rb
166
-
123
+
167
124
  Looping 1000 times on the terminator...
168
- 1000
169
- I was successful
125
+
126
+ success!
127
+
@@ -0,0 +1,27 @@
1
+ NAME
2
+ terminator
3
+
4
+ SYNOPSIS
5
+ an external timeout mechanism based on processes and signals. safe on
6
+ windows. safe for system calls. safe for minors.
7
+
8
+ INSTALL
9
+ gem install terminator
10
+
11
+ URIS
12
+ http://codeforpeople.com/lib/ruby
13
+ http://rubyforge.org/projects/codeforpeople
14
+
15
+ HISTORY
16
+ 1.0.0
17
+ cleanup for 1.9
18
+
19
+ 0.4.2
20
+ initial version with
21
+
22
+ AUTHORS
23
+ ara.t.howard - ara.t.howard@gmail.com
24
+ mikel lindsaar - raasdnil@gmail.com
25
+
26
+ SAMPLES
27
+ @samples
@@ -0,0 +1,392 @@
1
+ This.rubyforge_project = 'codeforpeople'
2
+ This.author = "Ara T. Howard"
3
+ This.email = "ara.t.howard@gmail.com"
4
+ This.homepage = "https://github.com/ahoward/#{ This.lib }"
5
+
6
+
7
+ task :default do
8
+ puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
9
+ end
10
+
11
+ task :test do
12
+ run_tests!
13
+ end
14
+
15
+ namespace :test do
16
+ task(:unit){ run_tests!(:unit) }
17
+ task(:functional){ run_tests!(:functional) }
18
+ task(:integration){ run_tests!(:integration) }
19
+ end
20
+
21
+ def run_tests!(which = nil)
22
+ which ||= '**'
23
+ test_dir = File.join(This.dir, "test")
24
+ test_glob ||= File.join(test_dir, "#{ which }/**_test.rb")
25
+ test_rbs = Dir.glob(test_glob).sort
26
+
27
+ div = ('=' * 119)
28
+ line = ('-' * 119)
29
+
30
+ test_rbs.each_with_index do |test_rb, index|
31
+ testno = index + 1
32
+ command = "#{ File.basename(This.ruby) } -I ./lib -I ./test/lib #{ test_rb }"
33
+
34
+ puts
35
+ say(div, :color => :cyan, :bold => true)
36
+ say("@#{ testno } => ", :bold => true, :method => :print)
37
+ say(command, :color => :cyan, :bold => true)
38
+ say(line, :color => :cyan, :bold => true)
39
+
40
+ system(command)
41
+
42
+ say(line, :color => :cyan, :bold => true)
43
+
44
+ status = $?.exitstatus
45
+
46
+ if status.zero?
47
+ say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
48
+ say("SUCCESS", :color => :green, :bold => true)
49
+ else
50
+ say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
51
+ say("FAILURE", :color => :red, :bold => true)
52
+ end
53
+ say(line, :color => :cyan, :bold => true)
54
+
55
+ exit(status) unless status.zero?
56
+ end
57
+ end
58
+
59
+
60
+ task :gemspec do
61
+ ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem']
62
+ ignore_directories = ['pkg', 'db']
63
+ ignore_files = ['test/log', 'test/db.yml', 'a.rb', 'b.rb'] + Dir['db/*'] + %w'db'
64
+
65
+ shiteless =
66
+ lambda do |list|
67
+ list.delete_if do |entry|
68
+ next unless test(?e, entry)
69
+ extension = File.basename(entry).split(%r/[.]/).last
70
+ ignore_extensions.any?{|ext| ext === extension}
71
+ end
72
+ list.delete_if do |entry|
73
+ next unless test(?d, entry)
74
+ dirname = File.expand_path(entry)
75
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
76
+ end
77
+ list.delete_if do |entry|
78
+ next unless test(?f, entry)
79
+ filename = File.expand_path(entry)
80
+ ignore_files.any?{|file| File.expand_path(file) == filename}
81
+ end
82
+ end
83
+
84
+ lib = This.lib
85
+ object = This.object
86
+ version = This.version
87
+ files = shiteless[Dir::glob("**/**")]
88
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
89
+ #has_rdoc = true #File.exist?('doc')
90
+ test_files = test(?e, "test/#{ lib }.rb") ? "test/#{ lib }.rb" : nil
91
+ summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
92
+ description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
93
+ license = object.respond_to?(:license) ? object.license : "same as ruby's"
94
+
95
+ if This.extensions.nil?
96
+ This.extensions = []
97
+ extensions = This.extensions
98
+ %w( Makefile configure extconf.rb ).each do |ext|
99
+ extensions << ext if File.exists?(ext)
100
+ end
101
+ end
102
+ extensions = [extensions].flatten.compact
103
+
104
+ # TODO
105
+ if This.dependencies.nil?
106
+ dependencies = []
107
+ else
108
+ case This.dependencies
109
+ when Hash
110
+ dependencies = This.dependencies.values
111
+ when Array
112
+ dependencies = This.dependencies
113
+ end
114
+ end
115
+
116
+ template =
117
+ if test(?e, 'gemspec.erb')
118
+ Template{ IO.read('gemspec.erb') }
119
+ else
120
+ Template {
121
+ <<-__
122
+ ## <%= lib %>.gemspec
123
+ #
124
+
125
+ Gem::Specification::new do |spec|
126
+ spec.name = <%= lib.inspect %>
127
+ spec.version = <%= version.inspect %>
128
+ spec.platform = Gem::Platform::RUBY
129
+ spec.summary = <%= lib.inspect %>
130
+ spec.description = <%= description.inspect %>
131
+ spec.license = <%= license.inspect %>
132
+
133
+ spec.files =\n<%= files.sort.pretty_inspect %>
134
+ spec.executables = <%= executables.inspect %>
135
+
136
+ spec.require_path = "lib"
137
+
138
+ spec.test_files = <%= test_files.inspect %>
139
+
140
+ <% dependencies.each do |lib_version| %>
141
+ spec.add_dependency(*<%= Array(lib_version).flatten.inspect %>)
142
+ <% end %>
143
+
144
+ spec.extensions.push(*<%= extensions.inspect %>)
145
+
146
+ spec.rubyforge_project = <%= This.rubyforge_project.inspect %>
147
+ spec.author = <%= This.author.inspect %>
148
+ spec.email = <%= This.email.inspect %>
149
+ spec.homepage = <%= This.homepage.inspect %>
150
+ end
151
+ __
152
+ }
153
+ end
154
+
155
+ Fu.mkdir_p(This.pkgdir)
156
+ gemspec = "#{ lib }.gemspec"
157
+ open(gemspec, "w"){|fd| fd.puts(template)}
158
+ This.gemspec = gemspec
159
+ end
160
+
161
+ task :gem => [:clean, :gemspec] do
162
+ Fu.mkdir_p(This.pkgdir)
163
+ before = Dir['*.gem']
164
+ cmd = "gem build #{ This.gemspec }"
165
+ `#{ cmd }`
166
+ after = Dir['*.gem']
167
+ gem = ((after - before).first || after.first) or abort('no gem!')
168
+ Fu.mv(gem, This.pkgdir)
169
+ This.gem = File.join(This.pkgdir, File.basename(gem))
170
+ end
171
+
172
+ task :readme do
173
+ samples = ''
174
+ prompt = '~ > '
175
+ lib = This.lib
176
+ version = This.version
177
+
178
+ Dir['sample*/*'].sort.each do |sample|
179
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
180
+
181
+ cmd = "cat #{ sample }"
182
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
183
+ samples << Util.indent(`#{ cmd }`, 4) << "\n"
184
+
185
+ cmd = "ruby #{ sample }"
186
+ samples << Util.indent(prompt + cmd, 2) << "\n\n"
187
+
188
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'"
189
+ samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
190
+ end
191
+
192
+ template =
193
+ if test(?e, 'readme.erb')
194
+ Template{ IO.read('readme.erb') }
195
+ else
196
+ Template {
197
+ <<-__
198
+ NAME
199
+ #{ lib }
200
+
201
+ DESCRIPTION
202
+
203
+ INSTALL
204
+ gem install #{ lib }
205
+
206
+ SAMPLES
207
+ #{ samples }
208
+ __
209
+ }
210
+ end
211
+
212
+ open("README", "w"){|fd| fd.puts template}
213
+ end
214
+
215
+
216
+ task :clean do
217
+ Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
218
+ end
219
+
220
+
221
+ task :release => [:clean, :gemspec, :gem] do
222
+ gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
223
+ raise "which one? : #{ gems.inspect }" if gems.size > 1
224
+ raise "no gems?" if gems.size < 1
225
+
226
+ cmd = "gem push #{ This.gem }"
227
+ puts cmd
228
+ puts
229
+ system(cmd)
230
+ abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
231
+
232
+ cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.gem }"
233
+ puts cmd
234
+ puts
235
+ system(cmd)
236
+ abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
237
+ end
238
+
239
+
240
+
241
+
242
+
243
+ BEGIN {
244
+ # support for this rakefile
245
+ #
246
+ $VERBOSE = nil
247
+
248
+ require 'ostruct'
249
+ require 'erb'
250
+ require 'fileutils'
251
+ require 'rbconfig'
252
+ require 'pp'
253
+
254
+ # fu shortcut
255
+ #
256
+ Fu = FileUtils
257
+
258
+ # cache a bunch of stuff about this rakefile/environment
259
+ #
260
+ This = OpenStruct.new
261
+
262
+ This.file = File.expand_path(__FILE__)
263
+ This.dir = File.dirname(This.file)
264
+ This.pkgdir = File.join(This.dir, 'pkg')
265
+
266
+ # grok lib
267
+ #
268
+ lib = ENV['LIB']
269
+ unless lib
270
+ lib = File.basename(Dir.pwd).sub(/[-].*$/, '')
271
+ end
272
+ This.lib = lib
273
+
274
+ # grok version
275
+ #
276
+ version = ENV['VERSION']
277
+ unless version
278
+ require "./lib/#{ This.lib }"
279
+ This.name = lib.capitalize
280
+ This.object = eval(This.name)
281
+ version = This.object.send(:version)
282
+ end
283
+ This.version = version
284
+
285
+ # see if dependencies are export by the module
286
+ #
287
+ if This.object.respond_to?(:dependencies)
288
+ This.dependencies = This.object.dependencies
289
+ end
290
+
291
+ # we need to know the name of the lib an it's version
292
+ #
293
+ abort('no lib') unless This.lib
294
+ abort('no version') unless This.version
295
+
296
+ # discover full path to this ruby executable
297
+ #
298
+ c = Config::CONFIG
299
+ bindir = c["bindir"] || c['BINDIR']
300
+ ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
301
+ ruby_ext = c['EXEEXT'] || ''
302
+ ruby = File.join(bindir, (ruby_install_name + ruby_ext))
303
+ This.ruby = ruby
304
+
305
+ # some utils
306
+ #
307
+ module Util
308
+ def indent(s, n = 2)
309
+ s = unindent(s)
310
+ ws = ' ' * n
311
+ s.gsub(%r/^/, ws)
312
+ end
313
+
314
+ def unindent(s)
315
+ indent = nil
316
+ s.each_line do |line|
317
+ next if line =~ %r/^\s*$/
318
+ indent = line[%r/^\s*/] and break
319
+ end
320
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
321
+ end
322
+ extend self
323
+ end
324
+
325
+ # template support
326
+ #
327
+ class Template
328
+ def initialize(&block)
329
+ @block = block
330
+ @template = block.call.to_s
331
+ end
332
+ def expand(b=nil)
333
+ ERB.new(Util.unindent(@template)).result((b||@block).binding)
334
+ end
335
+ alias_method 'to_s', 'expand'
336
+ end
337
+ def Template(*args, &block) Template.new(*args, &block) end
338
+
339
+ # colored console output support
340
+ #
341
+ This.ansi = {
342
+ :clear => "\e[0m",
343
+ :reset => "\e[0m",
344
+ :erase_line => "\e[K",
345
+ :erase_char => "\e[P",
346
+ :bold => "\e[1m",
347
+ :dark => "\e[2m",
348
+ :underline => "\e[4m",
349
+ :underscore => "\e[4m",
350
+ :blink => "\e[5m",
351
+ :reverse => "\e[7m",
352
+ :concealed => "\e[8m",
353
+ :black => "\e[30m",
354
+ :red => "\e[31m",
355
+ :green => "\e[32m",
356
+ :yellow => "\e[33m",
357
+ :blue => "\e[34m",
358
+ :magenta => "\e[35m",
359
+ :cyan => "\e[36m",
360
+ :white => "\e[37m",
361
+ :on_black => "\e[40m",
362
+ :on_red => "\e[41m",
363
+ :on_green => "\e[42m",
364
+ :on_yellow => "\e[43m",
365
+ :on_blue => "\e[44m",
366
+ :on_magenta => "\e[45m",
367
+ :on_cyan => "\e[46m",
368
+ :on_white => "\e[47m"
369
+ }
370
+ def say(phrase, *args)
371
+ options = args.last.is_a?(Hash) ? args.pop : {}
372
+ options[:color] = args.shift.to_s.to_sym unless args.empty?
373
+ keys = options.keys
374
+ keys.each{|key| options[key.to_s.to_sym] = options.delete(key)}
375
+
376
+ color = options[:color]
377
+ bold = options.has_key?(:bold)
378
+
379
+ parts = [phrase]
380
+ parts.unshift(This.ansi[color]) if color
381
+ parts.unshift(This.ansi[:bold]) if bold
382
+ parts.push(This.ansi[:clear]) if parts.size > 1
383
+
384
+ method = options[:method] || :puts
385
+
386
+ Kernel.send(method, parts.join)
387
+ end
388
+
389
+ # always run out of the project dir
390
+ #
391
+ Dir.chdir(This.dir)
392
+ }
@@ -1 +1 @@
1
- Sun, 21 Sep 2008 10:59:58 +1000
1
+ Sun, 21 Sep 2008 11:02:40 +1000
@@ -101,48 +101,59 @@ require 'fattr'
101
101
  # end
102
102
  # #=> RuntimeError: (eval):1:in `irb_binding': Oops... I failed...
103
103
  module Terminator
104
- Version = '0.4.4'
104
+ Version = "1.0.0"
105
+
106
+ def Terminator.version
107
+ Terminator::Version
108
+ end
109
+
110
+ def Terminator.description
111
+ "an external timeout mechanism based on processes and signals"
112
+ end
113
+
114
+ def Terminator.license
115
+ "same as ruby's"
116
+ end
117
+
118
+ def Terminator.dependencies
119
+ {
120
+ 'fattr' => [ 'fattr' , ' >= 2.2' ] ,
121
+ }
122
+ end
105
123
 
106
124
  # Terminator.terminate has two ways you can call it. You can either just specify:
107
125
  #
108
126
  # Terminator.terminate(seconds) { code_to_execute }
109
127
  #
110
- # where seconds is an integer number greater than or equal to 1. If you pass a float
111
- # in on seconds, Terminator will call to_i on it and convert it to an integer. This
112
- # is because Terminator is not a precise tool, due to it calling a new ruby instance,
113
- # and spawning a new process, relying on split second accuracy is a folly.
114
- #
115
128
  # If you want to pass in the block, please use:
116
129
  #
117
130
  # Terminator.terminate(:seconds => seconds, :trap => block) { code_to_execute }
118
131
  #
119
132
  # Where block is an anonymous method that gets called when the timeout occurs.
120
133
  def terminate options = {}, &block
121
- options = { :seconds => Float(options).to_i } unless Hash === options
122
-
123
- seconds = getopt :seconds, options
134
+ options = { :seconds => Float(options) } unless Hash === options
124
135
 
125
- raise ::Terminator::Error, "Time to kill must be at least 1 second" unless seconds >= 1
136
+ seconds = getopt(:seconds, options)
126
137
 
127
- trap = getopt :trap, options, lambda{ eval("raise(::Terminator::Error, 'Timeout out after #{ seconds }s')", block) }
138
+ default_trap = lambda{ eval("raise(::Terminator::Error, 'Timeout out after #{ seconds }s')", block.binding) }
139
+ actual_trap = getopt(:trap, options, default_trap)
140
+ signal_trap = lambda{|*_| actual_trap.call()}
128
141
 
129
- handler = Signal.trap(signal, &trap)
142
+ previous_trap = Signal.trap(signal, &signal_trap)
130
143
 
131
- terminator_pid = plot_to_kill pid, :in => seconds, :with => signal
144
+ terminator_pid = plot_to_kill(pid, :in => seconds, :with => signal)
132
145
 
133
146
  begin
134
147
  block.call
135
- nuke_terminator(terminator_pid)
136
148
  ensure
137
- Signal.trap(signal, handler)
149
+ nuke_terminator(terminator_pid)
150
+ Signal.trap(signal, previous_trap)
138
151
  end
139
152
  end
140
153
 
141
- private
142
-
143
154
  def nuke_terminator(pid)
144
155
  Process.kill("KILL", pid) rescue nil
145
- Process.wait(pid)
156
+ Process.wait(pid) rescue nil
146
157
  end
147
158
 
148
159
  def plot_to_kill pid, options = {}
@@ -152,7 +163,7 @@ module Terminator
152
163
  end
153
164
 
154
165
  def send_terminator(pid, seconds)
155
- process = IO.popen(%[#{ ruby } -e'sleep #{seconds}.to_i; Process.kill("#{signal}", #{pid}) rescue nil;'], 'w+')
166
+ process = IO.popen(%[#{ ruby } -e'sleep #{seconds}; Process.kill("#{signal}", #{pid}) rescue nil;'], 'w+')
156
167
  process.pid
157
168
  end
158
169
 
@@ -161,7 +172,7 @@ module Terminator
161
172
  end
162
173
 
163
174
  fattr :ruby do
164
- c = ::Config::CONFIG
175
+ c = (defined?(::RbConfig) ? ::RbConfig : ::Config)::CONFIG
165
176
  ruby = File::join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
166
177
  raise "ruby @ #{ ruby } not executable!?" unless test(?e, ruby)
167
178
  ruby
@@ -7,6 +7,5 @@ success = false
7
7
  Terminator.terminate(1) do
8
8
  success = true
9
9
  end
10
- print "\b\b\b#{i}"
11
10
  end
12
- puts "\nI was successful" if success
11
+ puts "\nsuccess!" if success
@@ -0,0 +1,69 @@
1
+ ## terminator.gemspec
2
+ #
3
+
4
+ Gem::Specification::new do |spec|
5
+ spec.name = "terminator"
6
+ spec.version = "1.0.0"
7
+ spec.platform = Gem::Platform::RUBY
8
+ spec.summary = "terminator"
9
+ spec.description = "an external timeout mechanism based on processes and signals"
10
+ spec.license = "same as ruby's"
11
+
12
+ spec.files =
13
+ ["README",
14
+ "README.tmpl",
15
+ "Rakefile",
16
+ "doc",
17
+ "doc/classes",
18
+ "doc/classes/Terminator",
19
+ "doc/classes/Terminator.html",
20
+ "doc/classes/Terminator.src",
21
+ "doc/classes/Terminator.src/M000001.html",
22
+ "doc/classes/Terminator/Error.html",
23
+ "doc/created.rid",
24
+ "doc/files",
25
+ "doc/files/lib",
26
+ "doc/files/lib/terminator_rb.html",
27
+ "doc/files/samples",
28
+ "doc/files/samples/a_rb.html",
29
+ "doc/files/samples/b_rb.html",
30
+ "doc/files/samples/c_rb.html",
31
+ "doc/files/samples/d_rb.html",
32
+ "doc/files/samples/e_rb.html",
33
+ "doc/files/spec",
34
+ "doc/files/spec/terminator_spec_rb.html",
35
+ "doc/fr_class_index.html",
36
+ "doc/fr_file_index.html",
37
+ "doc/fr_method_index.html",
38
+ "doc/index.html",
39
+ "doc/rdoc-style.css",
40
+ "gen_readme.rb",
41
+ "lib",
42
+ "lib/terminator.rb",
43
+ "samples",
44
+ "samples/a.rb",
45
+ "samples/b.rb",
46
+ "samples/c.rb",
47
+ "samples/d.rb",
48
+ "samples/e.rb",
49
+ "spec",
50
+ "spec/terminator_spec.rb",
51
+ "terminator.gemspec"]
52
+
53
+ spec.executables = []
54
+
55
+ spec.require_path = "lib"
56
+
57
+ spec.test_files = nil
58
+
59
+
60
+ spec.add_dependency(*["fattr", " >= 2.2"])
61
+
62
+
63
+ spec.extensions.push(*[])
64
+
65
+ spec.rubyforge_project = "codeforpeople"
66
+ spec.author = "Ara T. Howard"
67
+ spec.email = "ara.t.howard@gmail.com"
68
+ spec.homepage = "https://github.com/ahoward/terminator"
69
+ end
metadata CHANGED
@@ -1,99 +1,85 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: terminator
3
- version: !ruby/object:Gem::Version
4
- version: 0.4.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Ara T. Howard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2008-09-21 00:00:00 +10:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
11
+ date: 2013-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
16
14
  name: fattr
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
17
20
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
- description:
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ description: an external timeout mechanism based on processes and signals
26
28
  email: ara.t.howard@gmail.com
27
29
  executables: []
28
-
29
30
  extensions: []
30
-
31
31
  extra_rdoc_files: []
32
-
33
- files:
34
- - doc
35
- - doc/classes
36
- - doc/classes/Terminator
37
- - doc/classes/Terminator/Error.html
32
+ files:
33
+ - README
34
+ - README.tmpl
35
+ - Rakefile
38
36
  - doc/classes/Terminator.html
39
- - doc/classes/Terminator.src
40
37
  - doc/classes/Terminator.src/M000001.html
38
+ - doc/classes/Terminator/Error.html
41
39
  - doc/created.rid
42
- - doc/files
43
- - doc/files/lib
44
40
  - doc/files/lib/terminator_rb.html
45
- - doc/files/samples
46
41
  - doc/files/samples/a_rb.html
47
42
  - doc/files/samples/b_rb.html
48
43
  - doc/files/samples/c_rb.html
49
44
  - doc/files/samples/d_rb.html
50
45
  - doc/files/samples/e_rb.html
51
- - doc/files/spec
52
46
  - doc/files/spec/terminator_spec_rb.html
53
47
  - doc/fr_class_index.html
54
48
  - doc/fr_file_index.html
55
49
  - doc/fr_method_index.html
56
50
  - doc/index.html
57
51
  - doc/rdoc-style.css
58
- - gemspec.rb
59
52
  - gen_readme.rb
60
- - install.rb
61
- - lib
62
53
  - lib/terminator.rb
63
- - README
64
- - samples
65
54
  - samples/a.rb
66
55
  - samples/b.rb
67
56
  - samples/c.rb
68
57
  - samples/d.rb
69
58
  - samples/e.rb
70
- - spec
71
59
  - spec/terminator_spec.rb
72
- has_rdoc: true
73
- homepage: http://codeforpeople.com/lib/ruby/terminator/
60
+ - terminator.gemspec
61
+ homepage: https://github.com/ahoward/terminator
62
+ licenses:
63
+ - same as ruby's
64
+ metadata: {}
74
65
  post_install_message:
75
66
  rdoc_options: []
76
-
77
- require_paths:
67
+ require_paths:
78
68
  - lib
79
- required_ruby_version: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: "0"
84
- version:
85
- required_rubygems_version: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: "0"
90
- version:
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
91
79
  requirements: []
92
-
93
80
  rubyforge_project: codeforpeople
94
- rubygems_version: 1.2.0
81
+ rubygems_version: 2.0.3
95
82
  signing_key:
96
- specification_version: 2
83
+ specification_version: 4
97
84
  summary: terminator
98
85
  test_files: []
99
-
data/gemspec.rb DELETED
@@ -1,39 +0,0 @@
1
- #! /usr/bin/env gem build
2
- #:stopdoc:
3
-
4
- lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
5
-
6
- require 'rubygems'
7
-
8
- Gem::Specification::new do |spec|
9
- $VERBOSE = nil
10
-
11
- shiteless = lambda do |list|
12
- list.delete_if do |file|
13
- file =~ %r/\.svn/ or
14
- file =~ %r/\.tmp/
15
- end
16
- end
17
-
18
- spec.name = lib
19
- spec.version = version
20
- spec.platform = Gem::Platform::RUBY
21
- spec.summary = lib
22
-
23
- spec.files = shiteless[Dir::glob("**/**")]
24
- spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename exe}
25
-
26
- spec.require_path = "lib"
27
-
28
- spec.has_rdoc = File::exist? "doc"
29
- spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
30
- #spec.add_dependency 'lib', '>= version'
31
- spec.add_dependency 'fattr'
32
-
33
- spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
34
-
35
- spec.rubyforge_project = 'codeforpeople'
36
- spec.author = "Ara T. Howard"
37
- spec.email = "ara.t.howard@gmail.com"
38
- spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
39
- end
data/install.rb DELETED
@@ -1,215 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #:stopdoc:
3
- require 'rbconfig'
4
- require 'find'
5
- require 'ftools'
6
- require 'tempfile'
7
- include Config
8
-
9
- LIBDIR = "lib"
10
- LIBDIR_MODE = 0644
11
-
12
- BINDIR = "bin"
13
- BINDIR_MODE = 0755
14
-
15
-
16
- $srcdir = CONFIG["srcdir"]
17
- $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
18
- $libdir = File.join(CONFIG["libdir"], "ruby", $version)
19
- $archdir = File.join($libdir, CONFIG["arch"])
20
- $site_libdir = $:.find {|x| x =~ /site_ruby$/}
21
- $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
22
- $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
23
- $ruby_ext = CONFIG['EXEEXT'] || ''
24
- $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
25
-
26
- if !$site_libdir
27
- $site_libdir = File.join($libdir, "site_ruby")
28
- elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
29
- $site_libdir = File.join($site_libdir, $version)
30
- end
31
-
32
- def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
33
- #{{{
34
- path = []
35
- dir = []
36
- Find.find(srcdir) do |f|
37
- next unless FileTest.file?(f)
38
- next if (f = f[srcdir.length+1..-1]) == nil
39
- next if (/CVS$/ =~ File.dirname(f))
40
- next if (/\.svn/ =~ File.dirname(f))
41
- next if f =~ %r/\.lnk/
42
- next if f =~ %r/\.svn/
43
- next if f =~ %r/\.swp/
44
- next if f =~ %r/\.svn/
45
- path.push f
46
- dir |= [File.dirname(f)]
47
- end
48
- for f in dir
49
- next if f == "."
50
- next if f == "CVS"
51
- File::makedirs(File.join(destdir, f))
52
- end
53
- for f in path
54
- next if (/\~$/ =~ f)
55
- next if (/^\./ =~ File.basename(f))
56
- unless bin
57
- File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
58
- else
59
- from = File.join(srcdir, f)
60
- to = File.join(destdir, f)
61
- shebangify(from) do |sf|
62
- $deferr.print from, " -> ", File::catname(from, to), "\n"
63
- $deferr.printf "chmod %04o %s\n", mode, to
64
- File::install(sf, to, mode, false)
65
- end
66
- end
67
- end
68
- #}}}
69
- end
70
- def shebangify f
71
- #{{{
72
- open(f) do |fd|
73
- buf = fd.read 42
74
- if buf =~ %r/^\s*#\s*!.*ruby/o
75
- ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
76
- begin
77
- fd.rewind
78
- ftmp.puts "#!#{ $ruby }"
79
- while((buf = fd.read(8192)))
80
- ftmp.write buf
81
- end
82
- ftmp.close
83
- yield ftmp.path
84
- ensure
85
- ftmp.close!
86
- end
87
- else
88
- yield f
89
- end
90
- end
91
- #}}}
92
- end
93
- def ARGV.switch
94
- #{{{
95
- return nil if self.empty?
96
- arg = self.shift
97
- return nil if arg == '--'
98
- if arg =~ /^-(.)(.*)/
99
- return arg if $1 == '-'
100
- raise 'unknown switch "-"' if $2.index('-')
101
- self.unshift "-#{$2}" if $2.size > 0
102
- "-#{$1}"
103
- else
104
- self.unshift arg
105
- nil
106
- end
107
- #}}}
108
- end
109
- def ARGV.req_arg
110
- #{{{
111
- self.shift || raise('missing argument')
112
- #}}}
113
- end
114
- def linkify d, linked = []
115
- #--{{{
116
- if test ?d, d
117
- versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
118
- versioned.each do |v|
119
- src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
120
- lnk = nil
121
- begin
122
- if test ?l, dst
123
- lnk = "#{ dst }.lnk"
124
- puts "#{ dst } -> #{ lnk }"
125
- File::rename dst, lnk
126
- end
127
- unless test ?e, dst
128
- puts "#{ src } -> #{ dst }"
129
- File::copy src, dst
130
- linked << dst
131
- end
132
- ensure
133
- if lnk
134
- at_exit do
135
- puts "#{ lnk } -> #{ dst }"
136
- File::rename lnk, dst
137
- end
138
- end
139
- end
140
- end
141
- end
142
- linked
143
- #--}}}
144
- end
145
-
146
-
147
- #
148
- # main program
149
- #
150
-
151
- libdir = $site_libdir
152
- bindir = $bindir
153
- no_linkify = false
154
- linked = nil
155
- help = false
156
-
157
- usage = <<-usage
158
- #{ File::basename $0 }
159
- -d, --destdir <destdir>
160
- -l, --libdir <libdir>
161
- -b, --bindir <bindir>
162
- -r, --ruby <ruby>
163
- -n, --no_linkify
164
- -s, --sudo
165
- -h, --help
166
- usage
167
-
168
- begin
169
- while switch = ARGV.switch
170
- case switch
171
- when '-d', '--destdir'
172
- libdir = ARGV.req_arg
173
- when '-l', '--libdir'
174
- libdir = ARGV.req_arg
175
- when '-b', '--bindir'
176
- bindir = ARGV.req_arg
177
- when '-r', '--ruby'
178
- $ruby = ARGV.req_arg
179
- when '-n', '--no_linkify'
180
- no_linkify = true
181
- when '-s', '--sudo'
182
- sudo = 'sudo'
183
- when '-h', '--help'
184
- help = true
185
- else
186
- raise "unknown switch #{switch.dump}"
187
- end
188
- end
189
- rescue
190
- STDERR.puts $!.to_s
191
- STDERR.puts usage
192
- exit 1
193
- end
194
-
195
- if help
196
- STDOUT.puts usage
197
- exit
198
- end
199
-
200
- system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
201
-
202
- unless no_linkify
203
- linked = linkify('lib') + linkify('bin')
204
- end
205
-
206
- system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
207
-
208
- install_rb(LIBDIR, libdir, LIBDIR_MODE)
209
- install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
210
-
211
- if linked
212
- linked.each{|path| File::rm_f path}
213
- end
214
-
215
- system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')