open4 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/open4.rb +9 -3
  2. metadata +2 -3
  3. data/lib/open4-0.9.5.rb +0 -387
@@ -5,7 +5,7 @@ require 'thread'
5
5
 
6
6
  module Open4
7
7
  #--{{{
8
- VERSION = '0.9.5'
8
+ VERSION = '0.9.6'
9
9
  def self.version() VERSION end
10
10
 
11
11
  class Error < ::StandardError; end
@@ -260,7 +260,7 @@ module Open4
260
260
  stdout_timeout = getopt[ %w( stdout_timeout io_timeout ) ]
261
261
  stderr_timeout = getopt[ %w( stderr_timeout ) ]
262
262
  status = getopt[ %w( status ) ]
263
- cwd = getopt[ %w( cwd dir ), Dir.pwd ]
263
+ cwd = getopt[ %w( cwd dir ) ]
264
264
 
265
265
  exitstatus =
266
266
  case exitstatus
@@ -279,7 +279,7 @@ module Open4
279
279
 
280
280
  status =
281
281
  begin
282
- Dir.chdir(cwd) do
282
+ chdir(cwd) do
283
283
  Timeout::timeout(timeout) do
284
284
  popen4(*argv) do |c, i, o, e|
285
285
  started = true
@@ -319,6 +319,12 @@ module Open4
319
319
  end
320
320
  module_function :spawn
321
321
 
322
+ def chdir cwd, &block
323
+ return(block.call Dir.pwd) unless cwd
324
+ Dir.chdir cwd, &block
325
+ end
326
+ module_function :chdir
327
+
322
328
  def background arg, *argv
323
329
  #--{{{
324
330
  require 'thread'
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: open4
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.9.5
7
- date: 2007-07-13 00:00:00 -06:00
6
+ version: 0.9.6
7
+ date: 2007-07-18 00:00:00 -06:00
8
8
  summary: open4
9
9
  require_paths:
10
10
  - lib
@@ -32,7 +32,6 @@ files:
32
32
  - gemspec.rb
33
33
  - install.rb
34
34
  - lib
35
- - lib/open4-0.9.5.rb
36
35
  - lib/open4.rb
37
36
  - README
38
37
  - sample
@@ -1,387 +0,0 @@
1
- # vim: ts=2:sw=2:sts=2:et:fdm=marker
2
- require 'fcntl'
3
- require 'timeout'
4
- require 'thread'
5
-
6
- module Open4
7
- #--{{{
8
- VERSION = '0.9.5'
9
- def self.version() VERSION end
10
-
11
- class Error < ::StandardError; end
12
-
13
- def popen4(*cmd, &b)
14
- #--{{{
15
- pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
16
-
17
- verbose = $VERBOSE
18
- begin
19
- $VERBOSE = nil
20
- ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
21
-
22
- cid = fork {
23
- pw.last.close
24
- STDIN.reopen pw.first
25
- pw.first.close
26
-
27
- pr.first.close
28
- STDOUT.reopen pr.last
29
- pr.last.close
30
-
31
- pe.first.close
32
- STDERR.reopen pe.last
33
- pe.last.close
34
-
35
- STDOUT.sync = STDERR.sync = true
36
-
37
- begin
38
- exec(*cmd)
39
- raise 'forty-two'
40
- rescue Exception => e
41
- Marshal.dump(e, ps.last)
42
- ps.last.flush
43
- end
44
- ps.last.close unless (ps.last.closed?)
45
- exit!
46
- }
47
- ensure
48
- $VERBOSE = verbose
49
- end
50
-
51
- [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
52
-
53
- begin
54
- e = Marshal.load ps.first
55
- raise(Exception === e ? e : "unknown failure!")
56
- rescue EOFError # If we get an EOF error, then the exec was successful
57
- 42
58
- ensure
59
- ps.first.close
60
- end
61
-
62
- pw.last.sync = true
63
-
64
- pi = [pw.last, pr.first, pe.first]
65
-
66
- if b
67
- begin
68
- b[cid, *pi]
69
- Process.waitpid2(cid).last
70
- ensure
71
- pi.each{|fd| fd.close unless fd.closed?}
72
- end
73
- else
74
- [cid, pw.last, pr.first, pe.first]
75
- end
76
- #--}}}
77
- end
78
- alias open4 popen4
79
- module_function :popen4
80
- module_function :open4
81
-
82
- class SpawnError < Error
83
- #--{{{
84
- attr 'cmd'
85
- attr 'status'
86
- attr 'signals'
87
- def exitstatus
88
- @status.exitstatus
89
- end
90
- def initialize cmd, status
91
- @cmd, @status = cmd, status
92
- @signals = {}
93
- if status.signaled?
94
- @signals['termsig'] = status.termsig
95
- @signals['stopsig'] = status.stopsig
96
- end
97
- sigs = @signals.map{|k,v| "#{ k }:#{ v.inspect }"}.join(' ')
98
- super "cmd <#{ cmd }> failed with status <#{ exitstatus.inspect }> signals <#{ sigs }>"
99
- end
100
- #--}}}
101
- end
102
-
103
- class ThreadEnsemble
104
- #--{{{
105
- attr 'threads'
106
-
107
- def initialize cid
108
- @cid, @threads, @argv, @done, @running = cid, [], [], Queue.new, false
109
- @killed = false
110
- end
111
-
112
- def add_thread *a, &b
113
- @running ? raise : (@argv << [a, b])
114
- end
115
-
116
- #
117
- # take down process more nicely
118
- #
119
- def killall
120
- c = Thread.critical
121
- return nil if @killed
122
- Thread.critical = true
123
- (@threads - [Thread.current]).each{|t| t.kill rescue nil}
124
- @killed = true
125
- ensure
126
- Thread.critical = c
127
- end
128
-
129
- def run
130
- @running = true
131
-
132
- begin
133
- @argv.each do |a, b|
134
- @threads << Thread.new(*a) do |*a|
135
- begin
136
- b[*a]
137
- ensure
138
- killall rescue nil if $!
139
- @done.push Thread.current
140
- end
141
- end
142
- end
143
- rescue
144
- killall
145
- raise
146
- ensure
147
- all_done
148
- end
149
-
150
- @threads.map{|t| t.value}
151
- end
152
-
153
- def all_done
154
- @threads.size.times{ @done.pop }
155
- end
156
- #--}}}
157
- end
158
-
159
- def to timeout = nil
160
- #--{{{
161
- Timeout.timeout(timeout){ yield }
162
- #--}}}
163
- end
164
- module_function :to
165
-
166
- def new_thread *a, &b
167
- #--{{{
168
- cur = Thread.current
169
- Thread.new(*a) do |*a|
170
- begin
171
- b[*a]
172
- rescue Exception => e
173
- cur.raise e
174
- end
175
- end
176
- #--}}}
177
- end
178
- module_function :new_thread
179
-
180
- def getopts opts = {}
181
- #--{{{
182
- lambda do |*args|
183
- keys, default, ignored = args
184
- catch('opt') do
185
- [keys].flatten.each do |key|
186
- [key, key.to_s, key.to_s.intern].each do |key|
187
- throw 'opt', opts[key] if opts.has_key?(key)
188
- end
189
- end
190
- default
191
- end
192
- end
193
- #--}}}
194
- end
195
- module_function :getopts
196
-
197
- def relay src, dst = nil, t = nil
198
- #--{{{
199
- unless src.nil?
200
- if src.respond_to? :gets
201
- while buf = to(t){ src.gets }
202
- dst << buf if dst
203
- end
204
-
205
- elsif src.respond_to? :each
206
- q = Queue.new
207
- th = nil
208
-
209
- timer_set = lambda do |t|
210
- th = new_thread{ to(t){ q.pop } }
211
- end
212
-
213
- timer_cancel = lambda do |t|
214
- th.kill if th rescue nil
215
- end
216
-
217
- timer_set[t]
218
- begin
219
- src.each do |buf|
220
- timer_cancel[t]
221
- dst << buf if dst
222
- timer_set[t]
223
- end
224
- ensure
225
- timer_cancel[t]
226
- end
227
-
228
- elsif src.respond_to? :read
229
- buf = to(t){ src.read }
230
- dst << buf if dst
231
-
232
- else
233
- buf = to(t){ src.to_s }
234
- dst << buf if dst
235
- end
236
- end
237
- #--}}}
238
- end
239
- module_function :relay
240
-
241
- def spawn arg, *argv
242
- #--{{{
243
- argv.unshift(arg)
244
- opts = ((argv.size > 1 and Hash === argv.last) ? argv.pop : {})
245
- argv.flatten!
246
- cmd = argv.join(' ')
247
-
248
-
249
- getopt = getopts opts
250
-
251
- ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
252
- ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
253
- exitstatus = getopt[ %w( exitstatus exit_status status ) ]
254
- stdin = getopt[ %w( stdin in i 0 ) << 0 ]
255
- stdout = getopt[ %w( stdout out o 1 ) << 1 ]
256
- stderr = getopt[ %w( stderr err e 2 ) << 2 ]
257
- pid = getopt[ 'pid' ]
258
- timeout = getopt[ %w( timeout spawn_timeout ) ]
259
- stdin_timeout = getopt[ %w( stdin_timeout ) ]
260
- stdout_timeout = getopt[ %w( stdout_timeout io_timeout ) ]
261
- stderr_timeout = getopt[ %w( stderr_timeout ) ]
262
- status = getopt[ %w( status ) ]
263
- cwd = getopt[ %w( cwd dir ), Dir.pwd ]
264
-
265
- exitstatus =
266
- case exitstatus
267
- when TrueClass, FalseClass
268
- ignore_exit_failure = true if exitstatus
269
- [0]
270
- else
271
- [*(exitstatus || 0)].map{|i| Integer i}
272
- end
273
-
274
- stdin ||= '' if stdin_timeout
275
- stdout ||= '' if stdout_timeout
276
- stderr ||= '' if stderr_timeout
277
-
278
- started = false
279
-
280
- status =
281
- begin
282
- Dir.chdir(cwd) do
283
- Timeout::timeout(timeout) do
284
- popen4(*argv) do |c, i, o, e|
285
- started = true
286
-
287
- %w( replace pid= << push update ).each do |msg|
288
- break(pid.send(msg, c)) if pid.respond_to? msg
289
- end
290
-
291
- te = ThreadEnsemble.new c
292
-
293
- te.add_thread(i, stdin) do |i, stdin|
294
- relay stdin, i, stdin_timeout
295
- i.close rescue nil
296
- end
297
-
298
- te.add_thread(o, stdout) do |o, stdout|
299
- relay o, stdout, stdout_timeout
300
- end
301
-
302
- te.add_thread(e, stderr) do |o, stderr|
303
- relay e, stderr, stderr_timeout
304
- end
305
-
306
- te.run
307
- end
308
- end
309
- end
310
- rescue
311
- raise unless(not started and ignore_exec_failure)
312
- end
313
-
314
- raise SpawnError.new(cmd, status) unless
315
- (ignore_exit_failure or (status.nil? and ignore_exec_failure) or exitstatus.include?(status.exitstatus))
316
-
317
- status
318
- #--}}}
319
- end
320
- module_function :spawn
321
-
322
- def background arg, *argv
323
- #--{{{
324
- require 'thread'
325
- q = Queue.new
326
- opts = { 'pid' => q, :pid => q }
327
- case argv.last
328
- when Hash
329
- argv.last.update opts
330
- else
331
- argv.push opts
332
- end
333
- thread = Thread.new(arg, argv){|arg, argv| spawn arg, *argv}
334
- sc = class << thread; self; end
335
- sc.module_eval {
336
- define_method(:pid){ @pid ||= q.pop }
337
- define_method(:spawn_status){ @spawn_status ||= value }
338
- define_method(:exitstatus){ @exitstatus ||= spawn_status.exitstatus }
339
- }
340
- thread
341
- #--}}}
342
- end
343
- alias bg background
344
- module_function :background
345
- module_function :bg
346
-
347
- def maim pid, opts = {}
348
- #--{{{
349
- getopt = getopts opts
350
- sigs = getopt[ 'signals', %w(SIGTERM SIGQUIT SIGKILL) ]
351
- suspend = getopt[ 'suspend', 4 ]
352
- pid = Integer pid
353
- existed = false
354
- sigs.each do |sig|
355
- begin
356
- Process.kill sig, pid
357
- existed = true
358
- rescue Errno::ESRCH
359
- return(existed ? nil : true)
360
- end
361
- return true unless alive? pid
362
- sleep suspend
363
- return true unless alive? pid
364
- end
365
- return(not alive?(pid))
366
- #--}}}
367
- end
368
- module_function :maim
369
-
370
- def alive pid
371
- #--{{{
372
- pid = Integer pid
373
- begin
374
- Process.kill 0, pid
375
- true
376
- rescue Errno::ESRCH
377
- false
378
- end
379
- #--}}}
380
- end
381
- alias alive? alive
382
- module_function :alive
383
- module_function :'alive?'
384
- #--}}}
385
- end
386
-
387
- def open4(*cmd, &b) cmd.size == 0 ? Open4 : Open4::popen4(*cmd, &b) end