Manually handle out of storage and JPEG too big errors
This commit is contained in:
parent
9ab5a461c0
commit
f6ae4807ff
1 changed files with 48 additions and 18 deletions
|
|
@ -268,30 +268,51 @@ class FinalStitcher(BaseStitcher):
|
|||
raise RuntimeError("stdout pipe was not created")
|
||||
# Stop opening pipe blocking writing to it
|
||||
os.set_blocking(process.stdout.fileno(), False)
|
||||
output_lines = self._log_ongoing(process)
|
||||
returncode = process.wait()
|
||||
full_output = "".join(output_lines)
|
||||
|
||||
self._log_ongoing(process)
|
||||
|
||||
if process.poll() == 0:
|
||||
if returncode == 0:
|
||||
self.logger.info("Stitching complete")
|
||||
elif process.poll() == -9:
|
||||
|
||||
elif returncode == -9:
|
||||
raise ExternalSigkillError(
|
||||
"Stitching was killed by an external process. This is "
|
||||
"most likely due to running out of memory."
|
||||
"Stitching was killed by an external process. "
|
||||
"Most likely due to running out of memory."
|
||||
)
|
||||
|
||||
elif returncode == 1:
|
||||
if "No space left on device" in full_output or "Errno 28" in full_output:
|
||||
raise ChildProcessError(
|
||||
"Not enough space on disk to stitch. Please delete some scans or increase your storage size."
|
||||
)
|
||||
if (
|
||||
"Maximum supported image dimension" in full_output
|
||||
or "OSError: broken data stream when writing image file" in full_output
|
||||
):
|
||||
raise ChildProcessError(
|
||||
"Scan too big for stitching into a JPEG file. Download the full scan and stitch with alternate settings."
|
||||
)
|
||||
raise ChildProcessError(
|
||||
"Stitching errored with exit code 1.\nCheck the logs for more information."
|
||||
)
|
||||
else:
|
||||
raise ChildProcessError(
|
||||
f"Subprocess {STITCHING_CMD} errored with exit code {process.poll()}."
|
||||
f"Stitching errored with exit code {returncode}.\nCheck the logs for more information."
|
||||
)
|
||||
|
||||
def _log_ongoing(self, process: subprocess.Popen[str]) -> None:
|
||||
"""Log the ongoing process unless it is cancelled."""
|
||||
def _log_ongoing(self, process: subprocess.Popen[str]) -> list[str]:
|
||||
"""Log the ongoing process unless it is cancelled.
|
||||
|
||||
:returns: a list of all lines
|
||||
"""
|
||||
if process.stdout is None: # pragma: no cover - impossible with stdout=PIPE
|
||||
raise RuntimeError("stdout pipe was not created")
|
||||
|
||||
output_lines: list[str] = []
|
||||
# Poll returns None while running, will return the error code when finished
|
||||
while process.poll() is None:
|
||||
self.log_buffer(process.stdout)
|
||||
# Once buffer is clear sleep for 0.2s before trying again.
|
||||
output_lines.extend(self.log_buffer(process.stdout))
|
||||
|
||||
try:
|
||||
# This should act exactly like sleep if not started in a LabThings
|
||||
|
|
@ -304,11 +325,20 @@ class FinalStitcher(BaseStitcher):
|
|||
raise e
|
||||
|
||||
# Print everything in the buffer when program finishes
|
||||
self.log_buffer(process.stdout)
|
||||
output_lines.extend(self.log_buffer(process.stdout))
|
||||
|
||||
def log_buffer(self, buffer: IO[str]) -> None:
|
||||
"""Log everything in the buffer at INFO level."""
|
||||
# Use rstrip to remove newlines from each line, as logging provides its own
|
||||
# new lines
|
||||
while line := buffer.readline():
|
||||
self.logger.info(line.rstrip())
|
||||
return output_lines
|
||||
|
||||
def log_buffer(self, buffer: IO[str]) -> list[str]:
|
||||
"""Log everything currently available in the buffer and return lines."""
|
||||
lines: list[str] = []
|
||||
|
||||
while True:
|
||||
line = buffer.readline()
|
||||
if not line:
|
||||
break
|
||||
clean = line.rstrip()
|
||||
self.logger.info(clean)
|
||||
lines.append(line)
|
||||
|
||||
return lines
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue