From f5159d9e03b7fd18a077ab57ae91ef03d09fda56 Mon Sep 17 00:00:00 2001 From: Zdenek Styblik Date: Tue, 3 Sep 2024 22:53:29 +0200 Subject: [PATCH] Set timeout on pipe open I cannot explain intricacies, however I've noticed that rss2irc got indefinitely stuck when iibot got into some ~funky~ unexpected state. Based on contents of stack and strace I came to conclusion this was when open() was called on pipe(because iibot uses named pipes for input). Therefore, let's add timeout around open() call and we shall see. --- lib/config_options.py | 2 ++ rss2irc.py | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/config_options.py b/lib/config_options.py index 33b1fb7..1f468b1 100644 --- a/lib/config_options.py +++ b/lib/config_options.py @@ -7,3 +7,5 @@ CACHE_EXPIRATION = 86400 # seconds DATA_SOURCE_EXPIRATION = 30 * 86400 # seconds HTTP_TIMEOUT = 30 # seconds +PIPE_OPEN_TIMEOUT = 60 # seconds +PIPE_WRITE_TIMEOUT = 5 # seconds diff --git a/rss2irc.py b/rss2irc.py index a3c527b..516a170 100755 --- a/rss2irc.py +++ b/rss2irc.py @@ -258,7 +258,7 @@ def read_cache(logger: logging.Logger, cache_file: str) -> CachedData: def signal_handler(signum, frame): """Handle SIGALRM signal.""" - raise ValueError + raise TimeoutError def scrub_items(logger: logging.Logger, cache: CachedData) -> None: @@ -308,13 +308,16 @@ def write_data( sleep: int = 2, ) -> None: """Write data into file.""" + signal.signal(signal.SIGALRM, signal_handler) + signal.alarm(config_options.PIPE_OPEN_TIMEOUT) with open(output, "wb") as fhandle: + signal.alarm(0) for url in list(data.keys()): message = format_message(url, data[url], handle) try: write_message(logger, fhandle, message) time.sleep(sleep) - except ValueError: + except (TimeoutError, ValueError): logger.debug("%s", traceback.format_exc()) logger.debug("Failed to write %s, %s", url, data[url]) data.pop(url) @@ -325,10 +328,10 @@ def write_message( ) -> None: """Write message into file handle. - Sets up SIGALRM and raises `ValueError` if alarm is due. + Sets up SIGALRM and raises `TimeoutError` if alarm is due. """ signal.signal(signal.SIGALRM, signal_handler) - signal.alarm(5) + signal.alarm(config_options.PIPE_WRITE_TIMEOUT) try: fhandle_stat = os.fstat(fhandle.fileno()) is_fifo = stat.S_ISFIFO(fhandle_stat.st_mode)