open4 1.0.1 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE +3 -0
- data/README +38 -0
- data/README.erb +38 -0
- data/lib/open4.rb +109 -73
- data/open4.gemspec +32 -7
- data/rakefile +394 -0
- data/samples/jesse-caldwell.rb +131 -0
- data/samples/pfork4.rb +24 -0
- data/test/lib/test_case.rb +23 -0
- data/test/pfork4_test.rb +150 -0
- data/test/popen4_test.rb +82 -0
- data/test/popen4ext_test.rb +89 -0
- metadata +35 -38
- data/Rakefile +0 -225
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZTUyNzE3MzczYmM1N2M5ZTQ0MWY0ZTkxMGM2NDcwODQzZWU3YjBkZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDU2NWRlNGIxZjg5OGZmYjA5OGZhNDhhMTBiZDI2NTEyYzgxMTc5ZQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZDJjMzYwZjA5OGY5ODI2MDA3YzY5MmVkZjNjYjYzYTQyMjIzNmRjNzk3NDZi
|
10
|
+
NjRiMDExNjZjZDBkMWM5MWY0ZTlmNTYxNDRlODQ5NTNjMjk3YzcyNTYzYzU0
|
11
|
+
ZGIxYTNiZjc0MjdkY2JkZmNkYWIxYWY1MDlmY2RmYTdmZTUyZDk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzkxZDc2ODhjMjk4ZDEwMzM0YjIxYzEyYThiYTg3YmRlOTljYmRiOGUzMGY2
|
14
|
+
NTU0NmM4OTg2OTRlNDYwODMzMmU5ODA5OTkzNmYzMTgxYmIzY2ZlNGQ1NzE4
|
15
|
+
ZmY3ZDNlZmRmYzRiYmE2MGM0MDgxYjJhYWZkZTZhM2Q4ZmIyMzM=
|
data/LICENSE
ADDED
data/README
CHANGED
@@ -193,6 +193,44 @@ SAMPLES
|
|
193
193
|
42
|
194
194
|
/dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
|
195
195
|
|
196
|
+
----------------------------------------------------------------------------
|
197
|
+
pfork4 is similar to popen4, but instead of executing a command, it runs
|
198
|
+
ruby code in a child process. if the child process raises an exception, it
|
199
|
+
propagates to the parent.
|
200
|
+
----------------------------------------------------------------------------
|
201
|
+
|
202
|
+
harp: > cat sample/pfork4.rb
|
203
|
+
require 'open4'
|
204
|
+
|
205
|
+
echo = lambda do
|
206
|
+
$stdout.write $stdin.read
|
207
|
+
raise 'finish implementing me'
|
208
|
+
end
|
209
|
+
|
210
|
+
org_message = "hello, world!"
|
211
|
+
got_message = nil
|
212
|
+
exception = nil
|
213
|
+
|
214
|
+
begin
|
215
|
+
Open4.pfork4(echo) do |cid, stdin, stdout, stderr|
|
216
|
+
stdin.write org_message
|
217
|
+
stdin.close
|
218
|
+
got_message = stdout.read
|
219
|
+
end
|
220
|
+
rescue RuntimeError => e
|
221
|
+
exception = e.to_s
|
222
|
+
end
|
223
|
+
|
224
|
+
puts "org_message: #{org_message}"
|
225
|
+
puts "got_message: #{got_message}"
|
226
|
+
puts "exception : #{exception}"
|
227
|
+
|
228
|
+
|
229
|
+
harp: > ruby sample/pfork4.rb
|
230
|
+
org_message: hello, world!
|
231
|
+
got_message: hello, world!
|
232
|
+
exception : finish implementing me
|
233
|
+
|
196
234
|
HISTORY
|
197
235
|
1.0.0
|
198
236
|
- added ability for spawn to take a proc (respond_to?(:call))
|
data/README.erb
CHANGED
@@ -193,6 +193,44 @@ SAMPLES
|
|
193
193
|
42
|
194
194
|
/dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
|
195
195
|
|
196
|
+
----------------------------------------------------------------------------
|
197
|
+
pfork4 is similar to popen4, but instead of executing a command, it runs
|
198
|
+
ruby code in a child process. if the child process raises an exception, it
|
199
|
+
propagates to the parent.
|
200
|
+
----------------------------------------------------------------------------
|
201
|
+
|
202
|
+
harp: > cat sample/pfork4.rb
|
203
|
+
require 'open4'
|
204
|
+
|
205
|
+
echo = lambda do
|
206
|
+
$stdout.write $stdin.read
|
207
|
+
raise 'finish implementing me'
|
208
|
+
end
|
209
|
+
|
210
|
+
org_message = "hello, world!"
|
211
|
+
got_message = nil
|
212
|
+
exception = nil
|
213
|
+
|
214
|
+
begin
|
215
|
+
Open4.pfork4(echo) do |cid, stdin, stdout, stderr|
|
216
|
+
stdin.write org_message
|
217
|
+
stdin.close
|
218
|
+
got_message = stdout.read
|
219
|
+
end
|
220
|
+
rescue RuntimeError => e
|
221
|
+
exception = e.to_s
|
222
|
+
end
|
223
|
+
|
224
|
+
puts "org_message: #{org_message}"
|
225
|
+
puts "got_message: #{got_message}"
|
226
|
+
puts "exception : #{exception}"
|
227
|
+
|
228
|
+
|
229
|
+
harp: > ruby sample/pfork4.rb
|
230
|
+
org_message: hello, world!
|
231
|
+
got_message: hello, world!
|
232
|
+
exception : finish implementing me
|
233
|
+
|
196
234
|
HISTORY
|
197
235
|
1.0.0
|
198
236
|
- added ability for spawn to take a proc (respond_to?(:call))
|
data/lib/open4.rb
CHANGED
@@ -4,23 +4,69 @@ require 'timeout'
|
|
4
4
|
require 'thread'
|
5
5
|
|
6
6
|
module Open4
|
7
|
-
|
8
|
-
VERSION
|
9
|
-
|
7
|
+
VERSION = '1.3.4'
|
8
|
+
def Open4.version() VERSION end
|
9
|
+
|
10
|
+
def Open4.description
|
11
|
+
'open child process with handles on pid, stdin, stdout, and stderr: manage child processes and their io handles easily.'
|
12
|
+
end
|
10
13
|
|
11
14
|
class Error < ::StandardError; end
|
12
15
|
|
16
|
+
def pfork4(fun, &b)
|
17
|
+
Open4.do_popen(b, :block) do |ps_read, _|
|
18
|
+
ps_read.close
|
19
|
+
begin
|
20
|
+
fun.call
|
21
|
+
rescue SystemExit => e
|
22
|
+
# Make it seem to the caller that calling Kernel#exit in +fun+ kills
|
23
|
+
# the child process normally. Kernel#exit! bypasses this rescue
|
24
|
+
# block.
|
25
|
+
exit! e.status
|
26
|
+
else
|
27
|
+
exit! 0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
module_function :pfork4
|
32
|
+
|
13
33
|
def popen4(*cmd, &b)
|
14
|
-
|
34
|
+
Open4.do_popen(b, :init) do |ps_read, ps_write|
|
35
|
+
ps_read.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
36
|
+
ps_write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
37
|
+
exec(*cmd)
|
38
|
+
raise 'forty-two' # Is this really needed?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias open4 popen4
|
42
|
+
module_function :popen4
|
43
|
+
module_function :open4
|
44
|
+
|
45
|
+
def popen4ext(closefds=false, *cmd, &b)
|
46
|
+
Open4.do_popen(b, :init, closefds) do |ps_read, ps_write|
|
47
|
+
ps_read.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
48
|
+
ps_write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
49
|
+
exec(*cmd)
|
50
|
+
raise 'forty-two' # Is this really needed?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
module_function :popen4ext
|
54
|
+
|
55
|
+
def self.do_popen(b = nil, exception_propagation_at = nil, closefds=false, &cmd)
|
15
56
|
pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
|
16
57
|
|
17
58
|
verbose = $VERBOSE
|
18
59
|
begin
|
19
60
|
$VERBOSE = nil
|
20
|
-
ps.first.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
21
|
-
ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
22
61
|
|
23
62
|
cid = fork {
|
63
|
+
if closefds
|
64
|
+
exlist = [0, 1, 2] | [pw,pr,pe,ps].map{|p| [p.first.fileno, p.last.fileno] }.flatten
|
65
|
+
ObjectSpace.each_object(IO){|io|
|
66
|
+
io.close if (not io.closed?) and (not exlist.include? io.fileno) rescue nil
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
24
70
|
pw.last.close
|
25
71
|
STDIN.reopen pw.first
|
26
72
|
pw.first.close
|
@@ -36,52 +82,59 @@ module Open4
|
|
36
82
|
STDOUT.sync = STDERR.sync = true
|
37
83
|
|
38
84
|
begin
|
39
|
-
|
40
|
-
raise 'forty-two'
|
85
|
+
cmd.call(ps)
|
41
86
|
rescue Exception => e
|
42
87
|
Marshal.dump(e, ps.last)
|
43
88
|
ps.last.flush
|
89
|
+
ensure
|
90
|
+
ps.last.close unless ps.last.closed?
|
44
91
|
end
|
45
|
-
|
92
|
+
|
46
93
|
exit!
|
47
94
|
}
|
48
95
|
ensure
|
49
96
|
$VERBOSE = verbose
|
50
97
|
end
|
51
98
|
|
52
|
-
[pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
|
99
|
+
[ pw.first, pr.last, pe.last, ps.last ].each { |fd| fd.close }
|
53
100
|
|
54
|
-
|
55
|
-
e = Marshal.load ps.first
|
56
|
-
raise(Exception === e ? e : "unknown failure!")
|
57
|
-
rescue EOFError # If we get an EOF error, then the exec was successful
|
58
|
-
42
|
59
|
-
ensure
|
60
|
-
ps.first.close
|
61
|
-
end
|
101
|
+
Open4.propagate_exception cid, ps.first if exception_propagation_at == :init
|
62
102
|
|
63
103
|
pw.last.sync = true
|
64
104
|
|
65
|
-
pi = [pw.last, pr.first, pe.first]
|
105
|
+
pi = [ pw.last, pr.first, pe.first ]
|
106
|
+
|
107
|
+
begin
|
108
|
+
return [cid, *pi] unless b
|
66
109
|
|
67
|
-
if b
|
68
110
|
begin
|
69
|
-
b
|
70
|
-
Process.waitpid2(cid).last
|
111
|
+
b.call(cid, *pi)
|
71
112
|
ensure
|
72
|
-
pi.each{|fd| fd.close unless fd.closed?}
|
113
|
+
pi.each { |fd| fd.close unless fd.closed? }
|
73
114
|
end
|
74
|
-
|
75
|
-
|
115
|
+
|
116
|
+
Open4.propagate_exception cid, ps.first if exception_propagation_at == :block
|
117
|
+
|
118
|
+
Process.waitpid2(cid).last
|
119
|
+
ensure
|
120
|
+
ps.first.close unless ps.first.closed?
|
76
121
|
end
|
77
|
-
#--}}}
|
78
122
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
123
|
+
|
124
|
+
def self.propagate_exception(cid, ps_read)
|
125
|
+
e = Marshal.load ps_read
|
126
|
+
raise Exception === e ? e : "unknown failure!"
|
127
|
+
rescue EOFError
|
128
|
+
# Child process did not raise exception.
|
129
|
+
rescue
|
130
|
+
# Child process raised exception; wait it in order to avoid a zombie.
|
131
|
+
Process.waitpid2 cid
|
132
|
+
raise
|
133
|
+
ensure
|
134
|
+
ps_read.close
|
135
|
+
end
|
82
136
|
|
83
137
|
class SpawnError < Error
|
84
|
-
#--{{{
|
85
138
|
attr 'cmd'
|
86
139
|
attr 'status'
|
87
140
|
attr 'signals'
|
@@ -98,11 +151,9 @@ module Open4
|
|
98
151
|
sigs = @signals.map{|k,v| "#{ k }:#{ v.inspect }"}.join(' ')
|
99
152
|
super "cmd <#{ cmd }> failed with status <#{ exitstatus.inspect }> signals <#{ sigs }>"
|
100
153
|
end
|
101
|
-
#--}}}
|
102
154
|
end
|
103
155
|
|
104
156
|
class ThreadEnsemble
|
105
|
-
#--{{{
|
106
157
|
attr 'threads'
|
107
158
|
|
108
159
|
def initialize cid
|
@@ -132,9 +183,9 @@ module Open4
|
|
132
183
|
|
133
184
|
begin
|
134
185
|
@argv.each do |a, b|
|
135
|
-
@threads << Thread.new(*a) do |*
|
186
|
+
@threads << Thread.new(*a) do |*_a|
|
136
187
|
begin
|
137
|
-
b[*
|
188
|
+
b[*_a]
|
138
189
|
ensure
|
139
190
|
killall rescue nil if $!
|
140
191
|
@done.push Thread.current
|
@@ -154,54 +205,48 @@ module Open4
|
|
154
205
|
def all_done
|
155
206
|
@threads.size.times{ @done.pop }
|
156
207
|
end
|
157
|
-
#--}}}
|
158
208
|
end
|
159
209
|
|
160
210
|
def to timeout = nil
|
161
|
-
#--{{{
|
162
211
|
Timeout.timeout(timeout){ yield }
|
163
|
-
#--}}}
|
164
212
|
end
|
165
213
|
module_function :to
|
166
214
|
|
167
215
|
def new_thread *a, &b
|
168
|
-
#--{{{
|
169
216
|
cur = Thread.current
|
170
|
-
Thread.new(*a) do |*
|
217
|
+
Thread.new(*a) do |*_a|
|
171
218
|
begin
|
172
|
-
b[*
|
219
|
+
b[*_a]
|
173
220
|
rescue Exception => e
|
174
221
|
cur.raise e
|
175
222
|
end
|
176
223
|
end
|
177
|
-
#--}}}
|
178
224
|
end
|
179
225
|
module_function :new_thread
|
180
226
|
|
181
227
|
def getopts opts = {}
|
182
|
-
#--{{{
|
183
228
|
lambda do |*args|
|
184
|
-
keys, default,
|
185
|
-
catch(
|
229
|
+
keys, default, _ = args
|
230
|
+
catch(:opt) do
|
186
231
|
[keys].flatten.each do |key|
|
187
|
-
[key, key.to_s, key.to_s.intern].each do |
|
188
|
-
throw
|
232
|
+
[key, key.to_s, key.to_s.intern].each do |_key|
|
233
|
+
throw :opt, opts[_key] if opts.has_key?(_key)
|
189
234
|
end
|
190
235
|
end
|
191
236
|
default
|
192
237
|
end
|
193
238
|
end
|
194
|
-
#--}}}
|
195
239
|
end
|
196
240
|
module_function :getopts
|
197
241
|
|
198
242
|
def relay src, dst = nil, t = nil
|
199
|
-
#--{{{
|
200
243
|
send_dst =
|
201
244
|
if dst.respond_to?(:call)
|
202
245
|
lambda{|buf| dst.call(buf)}
|
246
|
+
elsif dst.respond_to?(:<<)
|
247
|
+
lambda{|buf| dst << buf }
|
203
248
|
else
|
204
|
-
lambda{|buf|
|
249
|
+
lambda{|buf| buf }
|
205
250
|
end
|
206
251
|
|
207
252
|
unless src.nil?
|
@@ -214,19 +259,19 @@ module Open4
|
|
214
259
|
q = Queue.new
|
215
260
|
th = nil
|
216
261
|
|
217
|
-
timer_set = lambda do |
|
218
|
-
th = new_thread{ to(
|
262
|
+
timer_set = lambda do |_t|
|
263
|
+
th = new_thread{ to(_t){ q.pop } }
|
219
264
|
end
|
220
265
|
|
221
|
-
timer_cancel = lambda do |
|
266
|
+
timer_cancel = lambda do |_t|
|
222
267
|
th.kill if th rescue nil
|
223
268
|
end
|
224
269
|
|
225
270
|
timer_set[t]
|
226
271
|
begin
|
227
|
-
src.each do |
|
272
|
+
src.each do |_buf|
|
228
273
|
timer_cancel[t]
|
229
|
-
send_dst[
|
274
|
+
send_dst[_buf]
|
230
275
|
timer_set[t]
|
231
276
|
end
|
232
277
|
ensure
|
@@ -242,12 +287,10 @@ module Open4
|
|
242
287
|
send_dst[buf]
|
243
288
|
end
|
244
289
|
end
|
245
|
-
#--}}}
|
246
290
|
end
|
247
291
|
module_function :relay
|
248
292
|
|
249
293
|
def spawn arg, *argv
|
250
|
-
#--{{{
|
251
294
|
argv.unshift(arg)
|
252
295
|
opts = ((argv.size > 1 and Hash === argv.last) ? argv.pop : {})
|
253
296
|
argv.flatten!
|
@@ -269,6 +312,7 @@ module Open4
|
|
269
312
|
stderr_timeout = getopt[ %w( stderr_timeout ) ]
|
270
313
|
status = getopt[ %w( status ) ]
|
271
314
|
cwd = getopt[ %w( cwd dir ) ]
|
315
|
+
closefds = getopt[ %w( close_fds ) ]
|
272
316
|
|
273
317
|
exitstatus =
|
274
318
|
case exitstatus
|
@@ -289,7 +333,7 @@ module Open4
|
|
289
333
|
begin
|
290
334
|
chdir(cwd) do
|
291
335
|
Timeout::timeout(timeout) do
|
292
|
-
|
336
|
+
popen4ext(closefds, *argv) do |c, i, o, e|
|
293
337
|
started = true
|
294
338
|
|
295
339
|
%w( replace pid= << push update ).each do |msg|
|
@@ -298,17 +342,17 @@ module Open4
|
|
298
342
|
|
299
343
|
te = ThreadEnsemble.new c
|
300
344
|
|
301
|
-
te.add_thread(i, stdin) do |
|
302
|
-
relay
|
303
|
-
|
345
|
+
te.add_thread(i, stdin) do |_i, _stdin|
|
346
|
+
relay _stdin, _i, stdin_timeout
|
347
|
+
_i.close rescue nil
|
304
348
|
end
|
305
349
|
|
306
|
-
te.add_thread(o, stdout) do |
|
307
|
-
relay
|
350
|
+
te.add_thread(o, stdout) do |_o, _stdout|
|
351
|
+
relay _o, _stdout, stdout_timeout
|
308
352
|
end
|
309
353
|
|
310
|
-
te.add_thread(e, stderr) do |
|
311
|
-
relay e,
|
354
|
+
te.add_thread(e, stderr) do |_o, _stderr| # HACK: I think this is a bug
|
355
|
+
relay e, _stderr, stderr_timeout
|
312
356
|
end
|
313
357
|
|
314
358
|
te.run
|
@@ -323,7 +367,6 @@ module Open4
|
|
323
367
|
(ignore_exit_failure or (status.nil? and ignore_exec_failure) or exitstatus.include?(status.exitstatus))
|
324
368
|
|
325
369
|
status
|
326
|
-
#--}}}
|
327
370
|
end
|
328
371
|
module_function :spawn
|
329
372
|
|
@@ -334,7 +377,6 @@ module Open4
|
|
334
377
|
module_function :chdir
|
335
378
|
|
336
379
|
def background arg, *argv
|
337
|
-
#--{{{
|
338
380
|
require 'thread'
|
339
381
|
q = Queue.new
|
340
382
|
opts = { 'pid' => q, :pid => q }
|
@@ -344,7 +386,7 @@ module Open4
|
|
344
386
|
else
|
345
387
|
argv.push opts
|
346
388
|
end
|
347
|
-
thread = Thread.new(arg, argv){|
|
389
|
+
thread = Thread.new(arg, argv){|_arg, _argv| spawn _arg, *_argv}
|
348
390
|
sc = class << thread; self; end
|
349
391
|
sc.module_eval {
|
350
392
|
define_method(:pid){ @pid ||= q.pop }
|
@@ -352,14 +394,12 @@ module Open4
|
|
352
394
|
define_method(:exitstatus){ @exitstatus ||= spawn_status.exitstatus }
|
353
395
|
}
|
354
396
|
thread
|
355
|
-
#--}}}
|
356
397
|
end
|
357
398
|
alias bg background
|
358
399
|
module_function :background
|
359
400
|
module_function :bg
|
360
401
|
|
361
402
|
def maim pid, opts = {}
|
362
|
-
#--{{{
|
363
403
|
getopt = getopts opts
|
364
404
|
sigs = getopt[ 'signals', %w(SIGTERM SIGQUIT SIGKILL) ]
|
365
405
|
suspend = getopt[ 'suspend', 4 ]
|
@@ -377,12 +417,10 @@ module Open4
|
|
377
417
|
return true unless alive? pid
|
378
418
|
end
|
379
419
|
return(not alive?(pid))
|
380
|
-
#--}}}
|
381
420
|
end
|
382
421
|
module_function :maim
|
383
422
|
|
384
423
|
def alive pid
|
385
|
-
#--{{{
|
386
424
|
pid = Integer pid
|
387
425
|
begin
|
388
426
|
Process.kill 0, pid
|
@@ -390,12 +428,10 @@ module Open4
|
|
390
428
|
rescue Errno::ESRCH
|
391
429
|
false
|
392
430
|
end
|
393
|
-
#--}}}
|
394
431
|
end
|
395
432
|
alias alive? alive
|
396
433
|
module_function :alive
|
397
434
|
module_function :'alive?'
|
398
|
-
#--}}}
|
399
435
|
end
|
400
436
|
|
401
437
|
def open4(*cmd, &b) cmd.size == 0 ? Open4 : Open4::popen4(*cmd, &b) end
|
data/open4.gemspec
CHANGED
@@ -3,26 +3,51 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "open4"
|
6
|
-
spec.version = "1.
|
6
|
+
spec.version = "1.3.4"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "open4"
|
9
|
+
spec.description = "open child process with handles on pid, stdin, stdout, and stderr: manage child processes and their io handles easily."
|
10
|
+
spec.license = "Ruby"
|
9
11
|
|
10
|
-
spec.
|
12
|
+
spec.files =
|
13
|
+
["LICENSE",
|
14
|
+
"README",
|
15
|
+
"README.erb",
|
16
|
+
"lib",
|
17
|
+
"lib/open4.rb",
|
18
|
+
"open4.gemspec",
|
19
|
+
"rakefile",
|
20
|
+
"samples",
|
21
|
+
"samples/bg.rb",
|
22
|
+
"samples/block.rb",
|
23
|
+
"samples/exception.rb",
|
24
|
+
"samples/jesse-caldwell.rb",
|
25
|
+
"samples/pfork4.rb",
|
26
|
+
"samples/simple.rb",
|
27
|
+
"samples/spawn.rb",
|
28
|
+
"samples/stdin_timeout.rb",
|
29
|
+
"samples/timeout.rb",
|
30
|
+
"test",
|
31
|
+
"test/lib",
|
32
|
+
"test/lib/test_case.rb",
|
33
|
+
"test/pfork4_test.rb",
|
34
|
+
"test/popen4_test.rb",
|
35
|
+
"test/popen4ext_test.rb",
|
36
|
+
"white_box",
|
37
|
+
"white_box/leak.rb"]
|
11
38
|
|
12
|
-
spec.files = ["lib", "lib/open4.rb", "open4.gemspec", "Rakefile", "README", "README.erb", "samples", "samples/bg.rb", "samples/block.rb", "samples/exception.rb", "samples/simple.rb", "samples/spawn.rb", "samples/stdin_timeout.rb", "samples/timeout.rb", "white_box", "white_box/leak.rb"]
|
13
39
|
spec.executables = []
|
14
40
|
|
15
41
|
spec.require_path = "lib"
|
16
42
|
|
17
|
-
spec.has_rdoc = true
|
18
43
|
spec.test_files = nil
|
19
|
-
|
20
|
-
|
44
|
+
|
45
|
+
|
21
46
|
|
22
47
|
spec.extensions.push(*[])
|
23
48
|
|
24
49
|
spec.rubyforge_project = "codeforpeople"
|
25
50
|
spec.author = "Ara T. Howard"
|
26
51
|
spec.email = "ara.t.howard@gmail.com"
|
27
|
-
spec.homepage = "
|
52
|
+
spec.homepage = "https://github.com/ahoward/open4"
|
28
53
|
end
|