Skip to content

Commit c9a869d

Browse files
committed
(MODULES-8748) Improve pipe reading in the PowerShell Manager
Previously the powershell manager was modified to read in data from the pipe until all data was read, in 8K chunks. However it was noted that this would be causing more IO calls than needed due to the 8K chunks. In this commit, the reader will attempt to read all bytes in a single call and use the string concatenation method to reduce the number the potential number of internal objects being created. Also the is_readable? method was updated to also check that the stream is not EOF. In odd cases the stream can show that it's ready to read, but a sysread call will throw an EOF, for example this could occur when data is buffered in a slow way.
1 parent a250d39 commit c9a869d

File tree

1 file changed

+10
-11
lines changed

1 file changed

+10
-11
lines changed

lib/puppet_x/puppetlabs/powershell/powershell_manager.rb

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def self.instance_key(cmd, args, options)
274274
def self.is_readable?(stream, timeout = 0.5)
275275
raise Errno::EPIPE if !is_stream_valid?(stream)
276276
read_ready = IO.select([stream], [], [], timeout)
277-
read_ready && stream == read_ready[0][0]
277+
read_ready && stream == read_ready[0][0] && !stream.eof?
278278
end
279279

280280
# when a stream has been closed by handle, but Ruby still has a file
@@ -395,17 +395,16 @@ def read_streams
395395
# read a Little Endian 32-bit integer for length of response
396396
expected_response_length = pipe.sysread(4).unpack('V').first
397397

398-
if expected_response_length == 0
399-
nil
400-
else
401-
# reads the expected bytes as a binary string or fails
402-
buffer = ""
403-
# Reads in the pipe data 8K, or less, at a time
404-
while (buffer.length < expected_response_length)
405-
buffer << pipe.sysread([expected_response_length - buffer.length, 8192].min)
406-
end
407-
buffer
398+
next nil if expected_response_length == 0
399+
# reads the expected bytes as a binary string or fails
400+
buffer = ""
401+
# sysread may not return all of the requested bytes due to buffering or the
402+
# underlying IO system. Keep reading from the pipe until all the bytes are read
403+
loop do
404+
buffer.concat(pipe.sysread(expected_response_length - buffer.length))
405+
break if buffer.length >= expected_response_length
408406
end
407+
buffer
409408
end
410409

411410
Puppet.debug "Waited #{Time.now - start_time} total seconds."

0 commit comments

Comments
 (0)