command_runner_ng 0.0.1 → 0.0.2
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 +4 -4
- data/lib/command_runner.rb +27 -25
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 341dc1d0132412d53c1e5d258d7a6a03e96e3a4e
|
4
|
+
data.tar.gz: 94ac85a463daa4020bf069c47adba3a99fe4aebb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 175e6af549e49bf1269032c11f0881ca5b89f79706ba706f082cba51af96b1a1ef13bf04d5d7955d64c3057af39096c94be946350934c25b10e71cfc6b741aac
|
7
|
+
data.tar.gz: 5308811978a0c87a00e2aef3766b95fb733da28bcf32f58f327e65f1a58f5633f9b7143eddf4f5a1e9f3fc591bdcfb78a6286026a5e40b50123a9a01e20a42f9
|
data/lib/command_runner.rb
CHANGED
@@ -27,9 +27,8 @@ module CommandRunner
|
|
27
27
|
# to the caller of run.
|
28
28
|
#
|
29
29
|
def self.run(*args, timeout: nil)
|
30
|
-
#
|
30
|
+
# This could be tweakable through vararg opts
|
31
31
|
tick = 0.1
|
32
|
-
bufsize = 4096
|
33
32
|
|
34
33
|
now = Time.now
|
35
34
|
|
@@ -58,37 +57,19 @@ module CommandRunner
|
|
58
57
|
io = IO.popen(*args, :err=>[:child, :out])
|
59
58
|
data = ""
|
60
59
|
|
61
|
-
# Wait until stdout closes
|
62
|
-
while Time.now < deadline_sequence.first[:deadline] do
|
63
|
-
IO.select([io], nil, nil, tick)
|
64
|
-
begin
|
65
|
-
data << io.read_nonblock(bufsize)
|
66
|
-
rescue IO::WaitReadable
|
67
|
-
# Ignore: tick time reached without io
|
68
|
-
rescue EOFError
|
69
|
-
# Child closed stdout (probably dead, but not necessarily)
|
70
|
-
break
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
60
|
# Run through all deadlines until command completes.
|
75
61
|
# We could merge this block into the selecting block above,
|
76
62
|
# but splitting like this saves us a Process.wait syscall per iteration.
|
63
|
+
eof = false
|
77
64
|
deadline_sequence.each do |point|
|
78
65
|
while Time.now < point[:deadline]
|
79
66
|
if Process.wait(io.pid, Process::WNOHANG)
|
67
|
+
read_nonblock_safe!(io, data, tick)
|
80
68
|
result = {out: data, status: $?}
|
81
69
|
io.close
|
82
70
|
return result
|
83
|
-
|
84
|
-
|
85
|
-
begin
|
86
|
-
data << io.read_nonblock(bufsize)
|
87
|
-
rescue IO::WaitReadable
|
88
|
-
# Ignore: tick time reached without io
|
89
|
-
rescue EOFError
|
90
|
-
# Child closed stdout (probably dead, but not necessarily)
|
91
|
-
end
|
71
|
+
elsif !eof
|
72
|
+
eof = read_nonblock_safe!(io, data, tick)
|
92
73
|
end
|
93
74
|
end
|
94
75
|
|
@@ -116,12 +97,33 @@ module CommandRunner
|
|
116
97
|
end
|
117
98
|
end
|
118
99
|
|
119
|
-
# Either we didn't have a deadline, or none of the deadlines killed
|
100
|
+
# Either we didn't have a deadline, or none of the deadlines killed off the child.
|
120
101
|
Process.wait(io.pid)
|
102
|
+
read_nonblock_safe!(io, data, tick)
|
121
103
|
result = {out: data, status: $?}
|
122
104
|
io.close
|
123
105
|
|
124
106
|
result
|
125
107
|
end
|
126
108
|
|
109
|
+
private
|
110
|
+
|
111
|
+
# Read data async, appending to data_out,
|
112
|
+
# returning true on EOF, false otherwise
|
113
|
+
def self.read_nonblock_safe!(io, data_out, tick)
|
114
|
+
IO.select([io], nil, nil, tick)
|
115
|
+
begin
|
116
|
+
# Read all available data until EAGAIN or EOF
|
117
|
+
loop do
|
118
|
+
data_out << io.read_nonblock(4096)
|
119
|
+
end
|
120
|
+
rescue IO::WaitReadable
|
121
|
+
# Ignore: tick time reached without io
|
122
|
+
return false
|
123
|
+
rescue EOFError
|
124
|
+
# Child closed stdout (probably dead, but not necessarily)
|
125
|
+
return true
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
127
129
|
end
|