From cd4cbdb00aa2e5f02fd594910c9cced312f433ba Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Mon, 8 Apr 2024 20:31:14 +0300 Subject: [PATCH] isolation_provider: Get exit code without timing out Get the exit code of the spawned process for the doc-to-pixels phase, without timing out. More specifically, if the spawned process has not finished within a generous amount of time (hardcode to 15 seconds), return UnexpectedConversionError, with a custom message. This way, the happy path is not affected, and we still make our best to learn the underlying cause of the I/O error. --- dangerzone/isolation_provider/base.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/dangerzone/isolation_provider/base.py b/dangerzone/isolation_provider/base.py index 0f76571..9e6ddfd 100644 --- a/dangerzone/isolation_provider/base.py +++ b/dangerzone/isolation_provider/base.py @@ -22,6 +22,7 @@ DOC_TO_PIXELS_LOG_END = "----- DOC TO PIXELS LOG END -----" PIXELS_TO_PDF_LOG_START = "----- PIXELS TO PDF LOG START -----" PIXELS_TO_PDF_LOG_END = "----- PIXELS TO PDF LOG END -----" +TIMEOUT_EXCEPTION = 15 def read_bytes(f: IO[bytes], size: int, exact: bool = True) -> bytes: """Read bytes from a file-like object.""" @@ -174,9 +175,23 @@ class IsolationProvider(ABC): if self.progress_callback: self.progress_callback(error, text, percentage) - def get_proc_exception(self, p: subprocess.Popen) -> Exception: + def get_proc_exception( + self, p: subprocess.Popen, timeout: int = TIMEOUT_EXCEPTION + ) -> Exception: """Returns an exception associated with a process exit code""" - error_code = p.wait(3) + try: + error_code = p.wait(timeout) + except subprocess.TimeoutExpired: + return errors.UnexpectedConversionError( + "Encountered an I/O error during document to pixels conversion," + f" but the conversion process is still running after {timeout} seconds" + f" (PID: {p.pid})" + ) + except Exception: + return errors.UnexpectedConversionError( + "Encountered an I/O error during document to pixels conversion," + f" but the status of the conversion process is unknown (PID: {p.pid})" + ) return errors.exception_from_error_code(error_code) @abstractmethod