subexec 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/subexec.rb +38 -38
  2. metadata +42 -32
@@ -1,32 +1,32 @@
1
1
  # # Subexec
2
2
  # * by Peter Kieltyka
3
3
  # * http://github/nulayer/subexec
4
- #
4
+ #
5
5
  # ## Description
6
- #
6
+ #
7
7
  # Subexec is a simple library that spawns an external command with
8
8
  # an optional timeout parameter. It relies on Ruby 1.9's Process.spawn
9
9
  # method. Also, it works with synchronous and asynchronous code.
10
- #
10
+ #
11
11
  # Useful for libraries that are Ruby wrappers for CLI's. For example,
12
12
  # resizing images with ImageMagick's mogrify command sometimes stalls
13
13
  # and never returns control back to the original process. Subexec
14
14
  # executes mogrify and preempts if it gets lost.
15
- #
15
+ #
16
16
  # ## Usage
17
- #
17
+ #
18
18
  # # Print hello
19
19
  # sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 5
20
20
  # puts sub.output # returns: hello
21
21
  # puts sub.exitstatus # returns: 0
22
- #
22
+ #
23
23
  # # Timeout process after a second
24
24
  # sub = Subexec.run "echo 'hello' && sleep 3", :timeout => 1
25
- # puts sub.output # returns:
25
+ # puts sub.output # returns:
26
26
  # puts sub.exitstatus # returns:
27
27
 
28
28
  class Subexec
29
- VERSION = '0.2.2'
29
+ VERSION = '0.2.3'
30
30
 
31
31
  attr_accessor :pid,
32
32
  :command,
@@ -41,7 +41,7 @@ class Subexec
41
41
  sub.run!
42
42
  sub
43
43
  end
44
-
44
+
45
45
  def initialize(command, options={})
46
46
  self.command = command
47
47
  self.lang = options[:lang] || "C"
@@ -49,7 +49,7 @@ class Subexec
49
49
  self.log_file = options[:log_file]
50
50
  self.exitstatus = 0
51
51
  end
52
-
52
+
53
53
  def run!
54
54
  if RUBY_VERSION >= '1.9' && RUBY_ENGINE != 'jruby'
55
55
  spawn
@@ -60,43 +60,43 @@ class Subexec
60
60
 
61
61
 
62
62
  private
63
-
63
+
64
64
  def spawn
65
65
  # TODO: weak implementation for log_file support.
66
66
  # Ideally, the data would be piped through to both descriptors
67
- r, w = IO.pipe
68
- if !log_file.nil?
69
- self.pid = Process.spawn({'LANG' => self.lang}, command, [:out, :err] => [log_file, 'a'])
70
- else
71
- self.pid = Process.spawn({'LANG' => self.lang}, command, STDERR=>w, STDOUT=>w)
72
- end
67
+ r, w = IO.pipe
68
+
69
+ log_to_file = !log_file.nil?
70
+ log_opts = log_to_file ? {[:out, :err] => [log_file, 'a']} : {STDERR=>w, STDOUT=>w}
71
+ self.pid = Process.spawn({'LANG' => self.lang}, command, log_opts)
73
72
  w.close
74
-
73
+
75
74
  @timer = Time.now + timeout
76
75
  timed_out = false
77
76
 
78
- waitpid = Proc.new do
79
- begin
80
- flags = (timeout > 0 ? Process::WUNTRACED|Process::WNOHANG : 0)
81
- Process.waitpid(pid, flags)
77
+ self.output = ''
78
+
79
+ append_to_output = Proc.new do
80
+ self.output << r.readlines.join('') unless log_to_file
81
+ end
82
+
83
+ loop do
84
+ ret = begin
85
+ Process.waitpid(pid, Process::WUNTRACED|Process::WNOHANG)
82
86
  rescue Errno::ECHILD
83
87
  break
84
88
  end
85
- end
86
89
 
87
- if timeout > 0
88
- loop do
89
- ret = waitpid.call
90
+ break if ret == pid
90
91
 
91
- break if ret == pid
92
- sleep 0.01
93
- if Time.now > @timer
94
- timed_out = true
95
- break
96
- end
92
+ append_to_output.call
93
+
94
+ if timeout > 0 && Time.now > @timer
95
+ timed_out = true
96
+ break
97
97
  end
98
- else
99
- waitpid.call
98
+
99
+ sleep 0.01
100
100
  end
101
101
 
102
102
  if timed_out
@@ -106,18 +106,18 @@ class Subexec
106
106
  else
107
107
  # The subprocess exited on its own
108
108
  self.exitstatus = $?.exitstatus
109
- self.output = r.readlines.join("")
109
+ append_to_output.call
110
110
  end
111
111
  r.close
112
-
112
+
113
113
  self
114
114
  end
115
-
115
+
116
116
  def exec
117
117
  if !(RUBY_PLATFORM =~ /win32|mswin|mingw/).nil?
118
118
  self.output = `set LANG=#{lang} && #{command} 2>&1`
119
119
  else
120
- self.output = `LANG=#{lang} && export $LANG && #{command} 2>&1`
120
+ self.output = `LANG=#{lang} && export LANG && #{command} 2>&1`
121
121
  end
122
122
  self.exitstatus = $?.exitstatus
123
123
  end
metadata CHANGED
@@ -1,48 +1,50 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subexec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
5
- prerelease:
4
+ version: 0.2.3
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Peter Kieltyka
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-20 00:00:00.000000000 Z
12
+ date: 2013-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: !ruby/object:Gem::Requirement
18
17
  requirements:
19
- - - ! '>='
18
+ - - ">="
20
19
  - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
20
+ version: !binary |-
21
+ MA==
25
22
  none: false
23
+ requirement: !ruby/object:Gem::Requirement
26
24
  requirements:
27
- - - ! '>='
25
+ - - ">="
28
26
  - !ruby/object:Gem::Version
29
- version: '0'
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :development
30
32
  - !ruby/object:Gem::Dependency
31
33
  name: rspec
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
+ version_requirements: !ruby/object:Gem::Requirement
34
35
  requirements:
35
- - - ~>
36
+ - - "~>"
36
37
  - !ruby/object:Gem::Version
37
38
  version: 2.7.0
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
39
  none: false
40
+ requirement: !ruby/object:Gem::Requirement
42
41
  requirements:
43
- - - ~>
42
+ - - "~>"
44
43
  - !ruby/object:Gem::Version
45
44
  version: 2.7.0
45
+ none: false
46
+ prerelease: false
47
+ type: :development
46
48
  description: Subexec spawns a subprocess with an optional timeout
47
49
  email:
48
50
  - peter@nulayer.com
@@ -53,28 +55,36 @@ files:
53
55
  - README.md
54
56
  - lib/subexec.rb
55
57
  homepage: http://github.com/nulayer/subexec
56
- licenses: []
57
- post_install_message:
58
+ licenses:
59
+ - MIT
60
+ post_install_message:
58
61
  rdoc_options: []
59
62
  require_paths:
60
63
  - lib
61
64
  required_ruby_version: !ruby/object:Gem::Requirement
62
- none: false
63
65
  requirements:
64
- - - ! '>='
66
+ - - ">="
65
67
  - !ruby/object:Gem::Version
66
- version: '0'
67
- required_rubygems_version: !ruby/object:Gem::Requirement
68
+ segments:
69
+ - 0
70
+ version: !binary |-
71
+ MA==
72
+ hash: 2
68
73
  none: false
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
75
  requirements:
70
- - - ! '>='
76
+ - - ">="
71
77
  - !ruby/object:Gem::Version
72
- version: '0'
78
+ segments:
79
+ - 0
80
+ version: !binary |-
81
+ MA==
82
+ hash: 2
83
+ none: false
73
84
  requirements: []
74
- rubyforge_project:
75
- rubygems_version: 1.8.23
76
- signing_key:
85
+ rubyforge_project:
86
+ rubygems_version: 1.8.24
87
+ signing_key:
77
88
  specification_version: 3
78
89
  summary: Subexec spawns a subprocess with an optional timeout
79
90
  test_files: []
80
- has_rdoc: