command_runner_ng 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/command_runner.rb +27 -25
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 130d48c47f75bc4bf9cda29964b2ee29f34c1c57
4
- data.tar.gz: f63abf2a6127e4ccbe0d669ef75baaeaa93726ab
3
+ metadata.gz: 341dc1d0132412d53c1e5d258d7a6a03e96e3a4e
4
+ data.tar.gz: 94ac85a463daa4020bf069c47adba3a99fe4aebb
5
5
  SHA512:
6
- metadata.gz: 8f31d164defc091230024b5b1d6ef0f1a37650d48c3fdab131e8220ea4cfc904aad24c33469ed5d27ffce0744876ef966f0f8e424e355dd03ed3e45a87fd91a9
7
- data.tar.gz: 3b7d20c02db29c8ded423ba1471fd7c5b0e2d6775d50541ab5a882366cb485e80c7770d395a0ef36344519b110627a519572d71b782eff1ecab457de60d97d88
6
+ metadata.gz: 175e6af549e49bf1269032c11f0881ca5b89f79706ba706f082cba51af96b1a1ef13bf04d5d7955d64c3057af39096c94be946350934c25b10e71cfc6b741aac
7
+ data.tar.gz: 5308811978a0c87a00e2aef3766b95fb733da28bcf32f58f327e65f1a58f5633f9b7143eddf4f5a1e9f3fc591bdcfb78a6286026a5e40b50123a9a01e20a42f9
@@ -27,9 +27,8 @@ module CommandRunner
27
27
  # to the caller of run.
28
28
  #
29
29
  def self.run(*args, timeout: nil)
30
- # These could be tweakable through vararg opts
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
- else
84
- IO.select([io], nil, nil, tick)
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 of the child.
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_runner_ng
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Kamstrup Erlandsen