fixed fail to exit upon ^C

This commit is contained in:
k4yt3x 2022-02-28 06:49:41 +00:00
parent 49e0375eee
commit 2bfcb13976
6 changed files with 43 additions and 40 deletions

View File

@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Video Decoder
Author: K4YT3X
Date Created: June 17, 2021
Last Modified: February 27, 2022
Last Modified: February 28, 2022
"""
# local imports
@ -163,27 +163,26 @@ class VideoDecoder(threading.Thread):
else:
logger.debug("Decoding queue depleted")
# flush the remaining data in STDOUT and close PIPE
# flush the remaining data in STDOUT and STDERR
self.decoder.stdout.flush()
self.decoder.stdout.close()
# flush the remaining data in STDERR and wait for it to be read
self.decoder.stderr.flush()
# send SIGINT (2) to FFmpeg
# this instructs it to finalize and exit
self.decoder.send_signal(signal.SIGINT)
# wait for process to terminate
self.pipe_printer.stop()
# close PIPEs to prevent process from getting stuck
self.decoder.stdout.close()
self.decoder.stderr.close()
# wait for processes and threads to stop
self.pipe_printer.join()
# wait for process to exit
self.decoder.wait()
logger.info("Decoder thread exiting")
self.running = False
# wait for PIPE printer to exit
self.pipe_printer.stop()
self.pipe_printer.join()
logger.info("Decoder thread exiting")
return super().run()
def stop(self) -> None:

View File

@ -167,27 +167,26 @@ class VideoEncoder(threading.Thread):
else:
logger.debug("Encoding queue depleted")
# flush the remaining data in STDIN and close PIPE
# flush the remaining data in STDIN and STDERR
self.encoder.stdin.flush()
self.encoder.stdin.close()
# flush the remaining data in STDERR and wait for it to be read
self.encoder.stderr.flush()
# send SIGINT (2) to FFmpeg
# this instructs it to finalize and exit
self.encoder.send_signal(signal.SIGINT)
# wait for process to terminate
self.pipe_printer.stop()
# close PIPEs to prevent process from getting stuck
self.encoder.stdin.close()
self.encoder.stderr.close()
# wait for processes and threads to stop
self.pipe_printer.join()
# wait for process to exit
self.encoder.wait()
logger.info("Encoder thread exiting")
self.running = False
# wait for PIPE printer to exit
self.pipe_printer.stop()
self.pipe_printer.join()
logger.info("Encoder thread exiting")
return super().run()
def stop(self) -> None:

View File

@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: Interpolator
Author: K4YT3X
Date Created: May 27, 2021
Last Modified: February 16, 2022
Last Modified: February 28, 2022
"""
# local imports
@ -113,7 +113,6 @@ class Interpolator(multiprocessing.Process):
break
logger.info(f"Interpolator process {self.name} terminating")
self.running = False
return super().run()
def _stop(self, _signal_number, _frame) -> None:

View File

@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Name: PIPE Printer
Author: K4YT3X
Date Created: February 27, 2022
Last Modified: February 27, 2022
Last Modified: February 28, 2022
"""
# built-in imports
@ -39,6 +39,11 @@ class PipePrinter(threading.Thread):
# set read mode to non-blocking
os.set_blocking(self.stderr.fileno(), False)
def _print_output(self) -> None:
output = self.stderr.read()
if output is not None and len(output) != 0:
print(output.decode(), file=sys.stderr)
def run(self) -> None:
self.running = True
@ -46,9 +51,12 @@ class PipePrinter(threading.Thread):
while self.running:
time.sleep(0.5)
output = self.stderr.read()
if output is not None:
print(output.decode(), file=sys.stderr)
try:
self._print_output()
# pipe closed
except ValueError:
break
return super().run()

View File

@ -190,7 +190,6 @@ class Upscaler(multiprocessing.Process):
logger.opt(colors=True).info(
f"Upscaler process <blue>{self.name}</blue> terminating"
)
self.running = False
return super().run()
def _stop(self, _signal_number, _frame) -> None:

View File

@ -27,7 +27,7 @@ __ __ _ _ ___ __ __
Name: Video2X
Creator: K4YT3X
Date Created: February 24, 2018
Last Modified: February 27, 2022
Last Modified: February 28, 2022
Editor: BrianPetkovsek
Last Modified: June 17, 2019
@ -290,14 +290,7 @@ class Video2X:
logger.exception(e)
exception.append(e)
# if no exceptions were produced
else:
logger.success("Processing completed successfully")
finally:
# mark processing queue as closed
self.processing_queue.close()
# stop processor processes
logger.info("Stopping processor processes")
for process in self.processor_processes:
@ -307,13 +300,16 @@ class Video2X:
for process in self.processor_processes:
process.join()
# ensure both the decoder and the encoder have exited
# stop encoder and decoder
logger.info("Stopping decoder and encoder threads")
self.decoder.stop()
self.encoder.stop()
self.decoder.join()
self.encoder.join()
# mark processing queue as closed
self.processing_queue.close()
# raise the error if there is any
if len(exception) > 0:
raise exception[0]
@ -549,7 +545,7 @@ def main() -> int:
"<magenta>Copyright (C) 2018-2022 K4YT3X and contributors.</magenta>"
)
# initialize upscaler object
# initialize video2x object
video2x = Video2X()
if args.action == "upscale":
@ -573,8 +569,6 @@ def main() -> int:
args.algorithm,
)
return 0
# don't print the traceback for manual terminations
except KeyboardInterrupt as e:
return 2
@ -582,3 +576,8 @@ def main() -> int:
except Exception as e:
logger.exception(e)
return 1
# if no exceptions were produced
else:
logger.success("Processing completed successfully")
return 0