issue #148: parent: prevent race in iter_read()
There is no guarantee on the ordering select() returns file descriptors. So if, e.g. in the case of sudo_nonexistent.yml, sudo prints an error to a single FD before exitting, there was previously no gurantee iter_read() would read off the error before failing due to detecting disconnect on any FD. Now instead we keep reading while any non-disconnected FD exists.
This commit is contained in:
parent
e43c6c531b
commit
46a311165e
|
@ -51,7 +51,7 @@ echo \
|
|||
# Build the binaries.
|
||||
make -C ${TRAVIS_BUILD_DIR}/tests/ansible
|
||||
|
||||
sudo apt install -y sshpass
|
||||
[ ! "$(type -p sshpass)" ] && sudo apt install -y sshpass
|
||||
|
||||
echo travis_fold:end:job_setup
|
||||
|
||||
|
|
|
@ -379,10 +379,11 @@ def write_all(fd, s, deadline=None):
|
|||
|
||||
|
||||
def iter_read(fds, deadline=None):
|
||||
fds = list(fds)
|
||||
bits = []
|
||||
timeout = None
|
||||
|
||||
while True:
|
||||
while fds:
|
||||
if deadline is not None:
|
||||
timeout = max(0, deadline - time.time())
|
||||
if timeout == 0:
|
||||
|
@ -394,15 +395,19 @@ def iter_read(fds, deadline=None):
|
|||
|
||||
for fd in rfds:
|
||||
s, disconnected = mitogen.core.io_op(os.read, fd, 4096)
|
||||
IOLOG.debug('iter_read(%r) -> %r', fd, s)
|
||||
if disconnected or not s:
|
||||
raise mitogen.core.StreamError(
|
||||
'EOF on stream; last 300 bytes received: %r' %
|
||||
(''.join(bits)[-300:],)
|
||||
)
|
||||
IOLOG.debug('iter_read(%r) -> disconnected', fd)
|
||||
fds.remove(fd)
|
||||
else:
|
||||
IOLOG.debug('iter_read(%r) -> %r', fd, s)
|
||||
bits.append(s)
|
||||
yield s
|
||||
|
||||
bits.append(s)
|
||||
yield s
|
||||
if not fds:
|
||||
raise mitogen.core.StreamError(
|
||||
'EOF on stream; last 300 bytes received: %r' %
|
||||
(''.join(bits)[-300:],)
|
||||
)
|
||||
|
||||
raise mitogen.core.TimeoutError('read timed out')
|
||||
|
||||
|
|
Loading…
Reference in New Issue