More debug on watching

This commit is contained in:
Leo Vasanko 2025-08-13 11:08:38 -07:00
parent 20a5c66e77
commit af4e90357f

View File

@ -1,4 +1,5 @@
import asyncio import asyncio
import os
import shutil import shutil
import sys import sys
import threading import threading
@ -7,6 +8,7 @@ from contextlib import suppress
from os import stat_result from os import stat_result
from pathlib import Path, PurePosixPath from pathlib import Path, PurePosixPath
from stat import S_ISDIR, S_ISREG from stat import S_ISDIR, S_ISREG
import signal
import msgspec import msgspec
from natsort import humansorted, natsort_keygen, ns from natsort import humansorted, natsort_keygen, ns
@ -174,6 +176,9 @@ state = State()
rootpath: Path = None # type: ignore rootpath: Path = None # type: ignore
quit = threading.Event() quit = threading.Event()
# Keep a reference so the file stays open for faulthandler outputs
_faulthandler_file = None # type: ignore
## Filesystem scanning ## Filesystem scanning
@ -574,6 +579,29 @@ async def start(app, loop):
global rootpath global rootpath
config.load_config() config.load_config()
rootpath = config.config.path rootpath = config.config.path
# Optional: enable SIGUSR1 stack dumps in production for debugging hangs
# Control with env CISTA_STACK_DUMP (default: enabled). Sends all thread
# stacks to a per-process log in /tmp when receiving SIGUSR1.
if os.environ.get("CISTA_STACK_DUMP", "1") == "1":
try:
import faulthandler
global _faulthandler_file
if _faulthandler_file is None:
log_path = f"/tmp/cista-stacks-{os.getpid()}.log"
# Line-buffered text file so writes appear promptly
_faulthandler_file = open(log_path, "a", buffering=1)
faulthandler.enable(file=_faulthandler_file)
faulthandler.register(
signal.SIGUSR1, file=_faulthandler_file, all_threads=True, chain=True
)
logger.info(
"Stack dump enabled: send SIGUSR1 to PID %s to write all thread stacks to %s",
os.getpid(),
log_path,
)
except Exception:
logger.exception("Failed to enable SIGUSR1 stack dump handler")
use_inotify = sys.platform == "linux" use_inotify = sys.platform == "linux"
app.ctx.watcher = threading.Thread( app.ctx.watcher = threading.Thread(
target=watcher_inotify if use_inotify else watcher_poll, target=watcher_inotify if use_inotify else watcher_poll,