Windows: fix termination of process output redirection (#29923)

The parent thread in the process stdout redirection logic on Windows
was closing a file that was being read in child thread, which lead to
error-based termination of the reader thread. This updates the
interaction to avoid the error.
This commit is contained in:
John W. Parent 2022-04-26 15:56:13 -04:00 committed by GitHub
parent 0f4b228eff
commit 83b91246b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 26 deletions

View File

@ -809,19 +809,23 @@ def __enter__(self):
def background_reader(reader, echo_writer, _kill): def background_reader(reader, echo_writer, _kill):
# for each line printed to logfile, read it # for each line printed to logfile, read it
# if echo: write line to user # if echo: write line to user
while True: try:
is_killed = _kill.wait(.1) while True:
self.stderr.flush() is_killed = _kill.wait(.1)
self.stdout.flush() # Flush buffered build output to file
line = reader.readline() # stdout/err fds refer to log file
while line: self.stderr.flush()
if self.echo: self.stdout.flush()
self.echo_writer.write('{0}'.format(line.decode()))
self.echo_writer.flush()
line = reader.readline()
if is_killed: line = reader.readline()
break if self.echo and line:
echo_writer.write('{0}'.format(line.decode()))
echo_writer.flush()
if is_killed:
break
finally:
reader.close()
self._active = True self._active = True
with replace_environment(self.env): with replace_environment(self.env):
@ -837,7 +841,6 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self._ioflag = False self._ioflag = False
else: else:
self.writer.close() self.writer.close()
self.reader.close()
self.echo_writer.flush() self.echo_writer.flush()
self.stdout.flush() self.stdout.flush()
self.stderr.flush() self.stderr.flush()
@ -853,10 +856,7 @@ def force_echo(self):
if not self._active: if not self._active:
raise RuntimeError( raise RuntimeError(
"Can't call force_echo() outside log_output region!") "Can't call force_echo() outside log_output region!")
try: yield
yield self
finally:
pass
def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo, def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,

View File

@ -30,7 +30,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.colify import llnl.util.tty.colify
import llnl.util.tty.color as color import llnl.util.tty.color as color
from llnl.util.tty.log import log_output, winlog from llnl.util.tty.log import log_output
import spack import spack
import spack.cmd import spack.cmd
@ -605,14 +605,9 @@ def __call__(self, *argv, **kwargs):
out = StringIO() out = StringIO()
try: try:
if sys.platform == 'win32': with log_output(out):
with winlog(out): self.returncode = _invoke_command(
self.returncode = _invoke_command( self.command, self.parser, args, unknown)
self.command, self.parser, args, unknown)
else:
with log_output(out):
self.returncode = _invoke_command(
self.command, self.parser, args, unknown)
except SystemExit as e: except SystemExit as e:
self.returncode = e.code self.returncode = e.code