diff --git a/repeater/plugins/__main__.py b/repeater/plugins/__main__.py index 3f62949..dd3a010 100644 --- a/repeater/plugins/__main__.py +++ b/repeater/plugins/__main__.py @@ -104,8 +104,8 @@ def main(argv: Optional[list[str]] = None) -> int: for sig in (signal.SIGINT, signal.SIGTERM): try: signal.signal(sig, _handle_signal) - except Exception: - pass + except (OSError, ValueError) as exc: + logger.debug("Could not register signal %s: %s", sig, exc) logger.info("Plugin root: %s", plugins_root) logger.info("IPC socket: %s", socket_path) diff --git a/repeater/plugins/ipc.py b/repeater/plugins/ipc.py index 01fa9a2..331a028 100644 --- a/repeater/plugins/ipc.py +++ b/repeater/plugins/ipc.py @@ -93,9 +93,11 @@ class PluginIPCServer: self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self._sock.bind(str(self.socket_path)) try: - os.chmod(self.socket_path, 0o660) - except OSError: - pass + # Repeater and the manager may be separate processes in one service + # group, so the local IPC socket is intentionally group-writable. + os.chmod(self.socket_path, 0o660) # nosec B103 + except OSError as exc: + logger.debug("Could not set IPC socket permissions: %s", exc) self._sock.listen(16) self._sock.settimeout(1.0) self._stop.clear() @@ -123,10 +125,13 @@ class PluginIPCServer: pass def _serve_loop(self) -> None: - assert self._sock is not None + sock = self._sock + if sock is None: + logger.error("IPC serve loop started without a socket") + return while not self._stop.is_set(): try: - conn, _ = self._sock.accept() + conn, _ = sock.accept() except socket.timeout: continue except OSError: diff --git a/repeater/plugins/runtime.py b/repeater/plugins/runtime.py index a2827d8..37f07e3 100644 --- a/repeater/plugins/runtime.py +++ b/repeater/plugins/runtime.py @@ -571,8 +571,8 @@ class PluginRuntime: pass try: proc.wait(timeout=2) - except Exception: - pass + except Exception as exc: + logger.debug("Wait after killing %s failed: %s", plugin_id, exc) with self._lock: self._cleanup_handle(plugin_id) @@ -593,12 +593,12 @@ class PluginRuntime: try: if handle.process.poll() is not None: self._exit_codes[plugin_id] = handle.process.returncode - except Exception: - pass + except Exception as exc: + logger.debug("Could not record exit status for %s: %s", plugin_id, exc) try: handle.log_fp.close() - except Exception: - pass + except Exception as exc: + logger.debug("Could not close plugin log for %s: %s", plugin_id, exc) @staticmethod def _rotate_log_if_needed(log_file: Path) -> None: diff --git a/repeater/web/plugin_endpoints.py b/repeater/web/plugin_endpoints.py index 6f817a5..6dc1ba0 100644 --- a/repeater/web/plugin_endpoints.py +++ b/repeater/web/plugin_endpoints.py @@ -136,12 +136,9 @@ class PluginAPIEndpoints: else: delete_data = bool(raw) # JSON body optional - try: - body = self._json_body() - if "delete_data" in body: - delete_data = bool(body.get("delete_data")) - except Exception: - pass + body = self._json_body() + if "delete_data" in body: + delete_data = bool(body.get("delete_data")) def _uninstall(): return self._client_or_raise().uninstall(plugin_id, delete_data=delete_data) diff --git a/tests/conftest.py b/tests/conftest.py index 90b24a3..e515ace 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,6 +16,7 @@ and does not point at the cause. The autouse fixture below fails the *responsible* test instead, at the moment it leaks the timer. """ + import threading import pytest diff --git a/tests/test_sqlite_upgrade_existing_db.py b/tests/test_sqlite_upgrade_existing_db.py index 052c82b..6055f36 100644 --- a/tests/test_sqlite_upgrade_existing_db.py +++ b/tests/test_sqlite_upgrade_existing_db.py @@ -16,6 +16,7 @@ packets and doing no RX/TX. These tests build a database with the *old* packets schema and assert that a handler opens it, ends up with both columns and the index, and can insert. """ + import os import shutil import sqlite3 @@ -59,9 +60,7 @@ CREATE TABLE packets ( def _make_legacy_db(path): con = sqlite3.connect(path) con.execute(_OLD_PACKETS_SCHEMA) - con.execute( - "INSERT INTO packets (timestamp, type, length) VALUES (?, ?, ?)", (1.0, 1, 10) - ) + con.execute("INSERT INTO packets (timestamp, type, length) VALUES (?, ?, ?)", (1.0, 1, 10)) con.commit() con.close() @@ -77,10 +76,7 @@ def _columns(path, table="packets"): def _indexes(path): con = sqlite3.connect(path) try: - return { - r[0] - for r in con.execute("SELECT name FROM sqlite_master WHERE type='index'") - } + return {r[0] for r in con.execute("SELECT name FROM sqlite_master WHERE type='index'")} finally: con.close() @@ -117,10 +113,7 @@ def test_upstream_index_exists_after_upgrade(legacy_db): def _tables(path): con = sqlite3.connect(path) try: - return { - r[0] - for r in con.execute("SELECT name FROM sqlite_master WHERE type='table'") - } + return {r[0] for r in con.execute("SELECT name FROM sqlite_master WHERE type='table'")} finally: con.close() @@ -145,8 +138,7 @@ def test_schema_init_runs_to_completion(legacy_db): tables = _tables(path) for late in ("room_messages", "room_client_sync"): assert late in tables, ( - "%s is missing: _init_database did not run to completion on an " - "existing database" % late + "%s is missing: _init_database did not run to completion on an existing database" % late ) @@ -159,8 +151,7 @@ def test_recording_works_after_upgrade(legacy_db): try: before = con.execute("SELECT COUNT(*) FROM packets").fetchone()[0] con.execute( - "INSERT INTO packets (timestamp, type, length, upstream_hash) " - "VALUES (?, ?, ?, ?)", + "INSERT INTO packets (timestamp, type, length, upstream_hash) VALUES (?, ?, ?, ?)", (2.0, 1, 12, "ABCD"), ) con.commit()