4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/spawn.rb', line 4
def self.spawn(*cmd, &b)
pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
ps.first.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
cid = fork {
pw.last.close
STDIN.reopen pw.first
pw.first.close
pr.first.close
STDOUT.reopen pr.last
pr.last.close
pe.first.close
STDERR.reopen pe.last
pe.last.close
STDOUT.sync = STDERR.sync = true
begin
r, w = IO.pipe
max_fd = r.to_i - 1
r.close
w.close
(3..max_fd).each do |fd|
begin
IO.for_fd(fd).fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
rescue Errno::EBADF
end
end
exec(*cmd)
raise 'forty-two'
rescue Exception => e
Marshal.dump(e, ps.last)
ps.last.flush
end
ps.last.close unless (ps.last.closed?)
exit!
}
[pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
begin
e = Marshal.load ps.first
raise(Exception === e ? e : "unknown failure!")
rescue EOFError 42
ensure
ps.first.close
end
pw.last.sync = true
pi = [pw.last, pr.first, pe.first]
if b
begin
b[cid, *pi]
Process.waitpid2(cid).last
ensure
pi.each{|fd| fd.close unless fd.closed?}
end
else
[cid, pw.last, pr.first, pe.first]
end
end
|