diff options
author | Zac Medico <zmedico@gentoo.org> | 2024-02-09 08:22:45 -0800 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2024-02-09 15:52:11 -0800 |
commit | ad61940b03be2f24c0b54c1070a4923abe18e633 (patch) | |
tree | 18e5b6c51ba93c569d339e75cec749c85e7c12ca | |
parent | test_gpkg_path_case: Add missing playground cleanup (diff) | |
download | portage-ad61940b03be2f24c0b54c1070a4923abe18e633.tar.gz portage-ad61940b03be2f24c0b54c1070a4923abe18e633.tar.bz2 portage-ad61940b03be2f24c0b54c1070a4923abe18e633.zip |
gpkg: Less aggressive subprocess.Popen kill in order to avoid BrokenPipeError
Do not kill tar_stream_reader instances if we can successfully
close them, since that can trigger BrokenPipeError during
self.proc.stdin.close() calls, and this state is best avoided
because it's unclear how the caller should handle the error.
If a BrokenPipeError does occur then simply print a traceback
and hope that the corresponding file descriptor is closed
during garbage collection. Do not try to reverse the order
of self.proc.kill() and self.proc.stdin.close() as in commit
fba76a545f2 since that triggered pypy ci job hangs for which
no reliable solution has been found so far.
Bug: https://bugs.gentoo.org/923368
Signed-off-by: Zac Medico <zmedico@gentoo.org>
-rw-r--r-- | lib/portage/gpkg.py | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/lib/portage/gpkg.py b/lib/portage/gpkg.py index 031b3f87c..f1d8f97f8 100644 --- a/lib/portage/gpkg.py +++ b/lib/portage/gpkg.py @@ -1,7 +1,8 @@ -# Copyright 2001-2020 Gentoo Authors +# Copyright 2001-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 import tarfile +import traceback import io import threading import subprocess @@ -151,7 +152,10 @@ class tar_stream_writer: if self.proc is not None: self.killed = True self.proc.kill() - self.proc.stdin.close() + try: + self.proc.stdin.close() + except BrokenPipeError: + traceback.print_exc() self.close() def _cmd_read_thread(self): @@ -213,7 +217,7 @@ class tar_stream_writer: if self.proc is not None: self.proc.stdin.close() if self.proc.wait() != os.EX_OK: - if not self.error: + if not (self.killed or self.error): raise CompressorOperationFailed("compression failed") if self.read_thread.is_alive(): self.read_thread.join() @@ -349,7 +353,10 @@ class tar_stream_reader: if self.proc is not None: self.killed = True self.proc.kill() - self.proc.stdin.close() + try: + self.proc.stdin.close() + except BrokenPipeError: + traceback.print_exc() self.close() def read(self, bufsize=-1): @@ -986,11 +993,13 @@ class gpkg: try: image_safe = tar_safe_extract(image, "image") image_safe.extractall(decompress_dir) + image_tar.close() except Exception as ex: writemsg(colorize("BAD", "!!!Extract failed.")) raise finally: - image_tar.kill() + if not image_tar.closed: + image_tar.kill() def update_metadata(self, metadata, new_basename=None, force=False): """ |