subexec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.rdoc +29 -0
  2. data/VERSION +1 -0
  3. data/lib/subexec.rb +86 -0
  4. metadata +70 -0
data/README.rdoc ADDED
@@ -0,0 +1,29 @@
1
+ = Subexec
2
+ by Peter Kieltyka
3
+ http://github/nulayer/subexec
4
+
5
+ === Description
6
+
7
+ Subexec is a simple library that spawns an external command with
8
+ an optional timeout parameter. It relies on Ruby 1.9's Process.spawn
9
+ method. Also, it works with synchronous and asynchronous code.
10
+
11
+ Useful for libraries that are Ruby wrappers for CLI's. For example,
12
+ resizing images with ImageMagick's mogrify command sometimes stalls
13
+ and never returns control back to the original process. Enter Subexec.
14
+
15
+ === Usage
16
+
17
+ sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 5
18
+ puts sub.output # returns: hello
19
+ puts sub.exitstatus # returns: 0
20
+
21
+ sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 1
22
+ puts sub.output # returns:
23
+ puts sub.exitstatus # returns:
24
+
25
+
26
+ === Limitations
27
+
28
+ Supports only Ruby 1.9.
29
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/lib/subexec.rb ADDED
@@ -0,0 +1,86 @@
1
+ # = Subexec
2
+ # * by Peter Kieltyka
3
+ # * http://github/nulayer/subprocess
4
+ #
5
+ # === Description
6
+ #
7
+ # Subexec is a simple library that spawns an external command with
8
+ # an optional timeout parameter. It relies on Ruby 1.9's Process.spawn
9
+ # method. Also, it works with synchronous and asynchronous code.
10
+ #
11
+ # Useful for libraries that are Ruby wrappers for CLI's. For example,
12
+ # resizing images with ImageMagick's mogrify command sometimes stalls
13
+ # and never returns control back to the original process. Subexec
14
+ # executes mogrify and preempts if gets lost.
15
+ #
16
+ # === Usage
17
+ #
18
+ # # Print hello
19
+ # sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 5
20
+ # puts sub.output # returns: hello
21
+ # puts sub.exitstatus # returns: 0
22
+ #
23
+ # # Timeout process after a second
24
+ # sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 1
25
+ # puts sub.output # returns:
26
+ # puts sub.exitstatus # returns:
27
+
28
+ class Subexec
29
+
30
+ attr_accessor :pid
31
+ attr_accessor :command
32
+ attr_accessor :timeout
33
+ attr_accessor :timer
34
+ attr_accessor :output
35
+ attr_accessor :exitstatus
36
+
37
+ def self.run(command, options={})
38
+ new(command, options)
39
+ end
40
+
41
+ def initialize(command, options={})
42
+ self.command = command
43
+ self.timeout = options[:timeout] || -1 # default is to never timeout
44
+ run!
45
+ end
46
+
47
+ def run!
48
+ r, w = IO.pipe
49
+ self.pid = Process.spawn(command, STDERR=>STDOUT, STDOUT=>w)
50
+ w.close
51
+
52
+ self.timer = Time.now + timeout
53
+ timed_out = false
54
+
55
+ loop do
56
+ begin
57
+ flags = (timeout > 0 ? Process::WUNTRACED|Process::WNOHANG : 0)
58
+ ret = Process.waitpid(pid, flags)
59
+ rescue Errno::ECHILD
60
+ break
61
+ end
62
+
63
+ break if ret == pid
64
+ sleep 0.001
65
+ if Time.now > timer
66
+ timed_out = true
67
+ break
68
+ end
69
+ end
70
+
71
+ if timed_out
72
+ # The subprocess timed out -- kill it
73
+ Process.kill(9, pid) rescue Errno::ESRCH
74
+ self.exitstatus = nil
75
+ else
76
+ # The subprocess exited on its own
77
+ self.exitstatus = $?.exitstatus
78
+ self.output = r.readlines.join("")
79
+ end
80
+ r.close
81
+
82
+ self
83
+ end
84
+
85
+ end
86
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subexec
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Peter Kieltyka
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-24 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Subexec spawns an external command with a timeout
23
+ email:
24
+ - peter@nulayer.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - README.rdoc
33
+ - VERSION
34
+ - lib/subexec.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/nulayer/subexec
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 3
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.3.7
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Subexec spawns an external command with a timeout
69
+ test_files: []
70
+