open4 0.9.5 → 0.9.6

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.
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