From 667e35bf1643fad35ab5216d09457644b72d44e8 Mon Sep 17 00:00:00 2001 From: n9k Date: Sat, 11 Jun 2022 22:24:58 +0000 Subject: [PATCH] Handle OSErrors reading playlist, give reasons for offline --- anonstream/segments.py | 49 +++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/anonstream/segments.py b/anonstream/segments.py index e69bd88..cf7c429 100644 --- a/anonstream/segments.py +++ b/anonstream/segments.py @@ -25,11 +25,12 @@ class UnsafePath(Exception): def get_mtime(): try: mtime = os.path.getmtime(CONFIG['SEGMENT_PLAYLIST']) - except FileNotFoundError as e: - raise Stale from e + except OSError as e: + raise Stale(f"couldn't stat playlist: {e}") from e else: - if time.time() - mtime >= CONFIG['SEGMENT_PLAYLIST_STALE_THRESHOLD']: - raise Stale + mtime_ago = time.time() - mtime + if mtime_ago >= CONFIG['SEGMENT_PLAYLIST_STALE_THRESHOLD']: + raise Stale(f'last modified {mtime_ago:.1f}s ago') return mtime @ttl_cache(CONFIG['SEGMENT_PLAYLIST_CACHE_LIFETIME']) @@ -38,13 +39,18 @@ def get_playlist(): try: mtime = get_mtime() except Stale as e: - raise Offline from e + reason, *_ = e.args + raise Offline(f'stale playlist: {reason}') from e else: - playlist = m3u8._load_from_file(CONFIG['SEGMENT_PLAYLIST']) - if playlist.is_endlist: - raise Offline - if len(playlist.segments) == 0: - raise Offline + try: + playlist = m3u8._load_from_file(CONFIG['SEGMENT_PLAYLIST']) + except OSError: + raise Offline(f"couldn't read playlist: {e}") from e + else: + if playlist.is_endlist: + raise Offline('playlist ended') + if len(playlist.segments) == 0: + raise Offline('empty playlist') return playlist, mtime @@ -79,10 +85,11 @@ def get_next_segment(uri): async def get_segment_uris(token): try: segment = get_starting_segment() - except Offline: + except Offline as e: + reason, *_ = e.args print( f'[debug @ {time.time():.3f}: {token=}] ' - f'stream went offline before we could find any segments' + f'stream went offline before we could find any segments ({reason})' ) return @@ -96,11 +103,12 @@ async def get_segment_uris(token): while True: try: next_segment = get_next_segment(segment.uri) - except Offline: + except Offline as e: + reason, *_ = e.args print( f'[debug @ {time.time():.3f}: {token=}] ' - f'stream went offline while looking for the segment ' - f'following {uri=}' + f'stream went offline while looking for the ' + f'segment following {segment.uri!r} ({reason})' ) return else: @@ -110,7 +118,8 @@ async def get_segment_uris(token): elif time.monotonic() - t0 >= CONFIG['SEGMENT_SEARCH_TIMEOUT']: print( f'[debug @ {time.time():.3f}: {token=}] ' - f'timed out looking for the segment following {uri=}' + f'timed out looking for the segment following ' + f'{segment.uri!r} ' f'(timeout={CONFIG["SEGMENT_SEARCH_TIMEOUT"]}s)' ) return @@ -135,7 +144,7 @@ async def segments(segment_read_hook=lambda uri: None, token=None): unsafe_path, *_ = e.args print( f'[debug @ {time.time():.3f}: {token=}] ' - f'segment {uri=} has unsafe {path=}' + f'segment {uri=} has {unsafe_path=}' ) break @@ -150,4 +159,10 @@ async def segments(segment_read_hook=lambda uri: None, token=None): f'segment {uri=} at {path=} unexpectedly does not exist' ) break + except OSError as e: + print( + f'[debug @ {time.time():.3f}: {token=}] ' + f'segment {uri=} at {path=} cannot be read: {e}' + ) + break print(f'[debug @ {time.time():.3f}: {token=}] exiting segment generator')