open4 1.0.1 → 1.3.4
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.
- 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
|