Skip to content
This repository has been archived by the owner on Jul 19, 2021. It is now read-only.

Commit

Permalink
subprocess tee: check process end *after* reading
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkwah committed Aug 25, 2020
1 parent 9ce72fc commit 8ff0e7c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
11 changes: 10 additions & 1 deletion python/res/util/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,26 @@ def await_process_tee(process, *out_files):
"""Wait for process to finish, "tee"-ing the subprocess' stdout into all the
given file objects.
NB: We aren't checking if `os.write` succeeds. It succeeds if its return
value matches `len(bytes_)`. In other cases we might want to do something
smart, such as retry or raise an error. At the time of writing it is
uncertain what we should do, and it is assumed that data loss is acceptable.
"""
out_fds = [f.fileno() for f in out_files]
process_fd = process.stdout.fileno()

while process.poll() is None:
while True:
while True:
bytes_ = os.read(process_fd, 4096)
if bytes_ == b"": # check EOF
break
for fd in out_fds:
os.write(fd, bytes_)

# Check if process terminated
if process.poll() is not None:
break
process.stdout.close()

return process.returncode
18 changes: 18 additions & 0 deletions python/tests/res/util/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,21 @@ def test_await_process_tee(self):
self.assertTrue(process.stdout.closed)
self.assertEqual(cat_content, a_content)
self.assertEqual(cat_content, b_content)

@tmpdir()
def test_await_process_finished_tee(self):
with open("a", "wb") as a_fh, open("b", "wb") as b_fh:
process = Popen(["/bin/cat", "/bin/cat"], stdout=PIPE)
process.wait()
await_process_tee(process, a_fh, b_fh)

with open("a", "rb") as f:
a_content = f.read()
with open("b", "rb") as f:
b_content = f.read()
with open("/bin/cat", "rb") as f:
cat_content = f.read()

self.assertTrue(process.stdout.closed)
self.assertEqual(cat_content, a_content)
self.assertEqual(cat_content, b_content)

0 comments on commit 8ff0e7c

Please sign in to comment.