fix(logging): don't crash the process if the system log can't be opened
_configure_logging opened InodeAwareRotatingFileHandler against DECNET_SYSTEM_LOGS (default: relative decnet.system.log) without guarding OSError. Under systemd with ProtectSystem=full + ProtectHome=read-only and no writable path baked into the unit, the first import of decnet.config raised OSError and the daemon died before it could even print a useful error — the root-cause log line showed up in journalctl as a stack trace rather than a warning. Wrap the handler attachment in try/except OSError and log a single WARNING via the already-installed stream handler. stderr is always attached, so losing the file handler means operators tail journalctl / docker logs instead — the daemon keeps running.
This commit is contained in:
@@ -82,19 +82,33 @@ def _configure_logging(dev: bool) -> None:
|
|||||||
_in_pytest = any(k.startswith("PYTEST") for k in os.environ)
|
_in_pytest = any(k.startswith("PYTEST") for k in os.environ)
|
||||||
if not _in_pytest:
|
if not _in_pytest:
|
||||||
_log_path = os.environ.get("DECNET_SYSTEM_LOGS", "decnet.system.log")
|
_log_path = os.environ.get("DECNET_SYSTEM_LOGS", "decnet.system.log")
|
||||||
file_handler = InodeAwareRotatingFileHandler(
|
# Never let file-handler attach failure kill the process. The
|
||||||
_log_path,
|
# stream handler above is already installed, so losing the file
|
||||||
mode="a",
|
# handler just means 'tail syslog / journalctl instead' — the
|
||||||
maxBytes=10 * 1024 * 1024, # 10 MB
|
# daemon itself must keep running. This path trips most
|
||||||
backupCount=5,
|
# commonly under systemd with ProtectSystem=full + ProtectHome=
|
||||||
encoding="utf-8",
|
# read-only when an operator hasn't passed a writable
|
||||||
)
|
# DECNET_SYSTEM_LOGS yet.
|
||||||
file_handler.setFormatter(fmt)
|
try:
|
||||||
root.addHandler(file_handler)
|
file_handler = InodeAwareRotatingFileHandler(
|
||||||
# Drop root ownership when invoked via sudo so non-root follow-up
|
_log_path,
|
||||||
# commands (e.g. `decnet api` after `sudo decnet deploy`) can append.
|
mode="a",
|
||||||
from decnet.privdrop import chown_to_invoking_user
|
maxBytes=10 * 1024 * 1024, # 10 MB
|
||||||
chown_to_invoking_user(_log_path)
|
backupCount=5,
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
file_handler.setFormatter(fmt)
|
||||||
|
root.addHandler(file_handler)
|
||||||
|
# Drop root ownership when invoked via sudo so non-root follow-up
|
||||||
|
# commands (e.g. `decnet api` after `sudo decnet deploy`) can append.
|
||||||
|
from decnet.privdrop import chown_to_invoking_user
|
||||||
|
chown_to_invoking_user(_log_path)
|
||||||
|
except OSError as exc:
|
||||||
|
logging.getLogger(__name__).warning(
|
||||||
|
"could not open %s (%s); continuing with stderr-only logging. "
|
||||||
|
"Set DECNET_SYSTEM_LOGS to a writable path to silence this.",
|
||||||
|
_log_path, exc,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_dev = os.environ.get("DECNET_DEVELOPER", "").lower() == "true"
|
_dev = os.environ.get("DECNET_DEVELOPER", "").lower() == "true"
|
||||||
|
|||||||
Reference in New Issue
Block a user