fix: trimite alert Telegram la închidere fereastră CMD pe Windows
CTRL_CLOSE_EVENT omora procesul instant, înainte ca finally să ruleze. _run_live_win32 instalează SetConsoleCtrlHandler care cancelează task-ul asyncio → finally trimite "ATM oprit" și flushează notifier-ul (~5s fereastra). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1124,9 +1124,71 @@ async def _drain_cmd_queue(ctx: RunContext) -> None:
|
|||||||
|
|
||||||
def run_live(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
def run_live(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
||||||
"""Sync entry point — delegates to asyncio event loop."""
|
"""Sync entry point — delegates to asyncio event loop."""
|
||||||
|
if sys.platform == "win32":
|
||||||
|
_run_live_win32(cfg, duration_s=duration_s, capture_stub=capture_stub)
|
||||||
|
else:
|
||||||
asyncio.run(run_live_async(cfg, duration_s=duration_s, capture_stub=capture_stub))
|
asyncio.run(run_live_async(cfg, duration_s=duration_s, capture_stub=capture_stub))
|
||||||
|
|
||||||
|
|
||||||
|
def _run_live_win32(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
||||||
|
"""Windows variant: catches CTRL_CLOSE_EVENT so the finally block (Telegram alert) runs."""
|
||||||
|
try:
|
||||||
|
import win32api # type: ignore[import-untyped]
|
||||||
|
except ImportError:
|
||||||
|
asyncio.run(run_live_async(cfg, duration_s=duration_s, capture_stub=capture_stub))
|
||||||
|
return
|
||||||
|
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
_task: list[asyncio.Task] = []
|
||||||
|
|
||||||
|
def _close_handler(event: int) -> bool:
|
||||||
|
# CTRL_CLOSE_EVENT=2, CTRL_LOGOFF_EVENT=5, CTRL_SHUTDOWN_EVENT=6
|
||||||
|
if event in (2, 5, 6) and _task:
|
||||||
|
loop.call_soon_threadsafe(_task[0].cancel)
|
||||||
|
return True # tell Windows we handled it; gives ~5 s before force-kill
|
||||||
|
return False # CTRL+C / CTRL+BREAK: let Python's default handler fire
|
||||||
|
|
||||||
|
win32api.SetConsoleCtrlHandler(_close_handler, True)
|
||||||
|
|
||||||
|
async def _run() -> None:
|
||||||
|
t = asyncio.create_task(
|
||||||
|
run_live_async(cfg, duration_s=duration_s, capture_stub=capture_stub),
|
||||||
|
name="atm_live",
|
||||||
|
)
|
||||||
|
_task.append(t)
|
||||||
|
try:
|
||||||
|
await t
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
pass # finally in run_live_async already sent the Telegram alert
|
||||||
|
|
||||||
|
try:
|
||||||
|
loop.run_until_complete(_run())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
# CTRL+C: cancel the live task and let its finally block run
|
||||||
|
if _task and not _task[0].done():
|
||||||
|
_task[0].cancel()
|
||||||
|
try:
|
||||||
|
loop.run_until_complete(_task[0])
|
||||||
|
except (asyncio.CancelledError, Exception):
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
pending = asyncio.all_tasks(loop)
|
||||||
|
for t in pending:
|
||||||
|
t.cancel()
|
||||||
|
if pending:
|
||||||
|
try:
|
||||||
|
loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
loop.run_until_complete(loop.shutdown_asyncgens())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
asyncio.set_event_loop(None)
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
|
||||||
async def run_live_async(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
async def run_live_async(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
||||||
"""Main live monitoring loop. Imports are lazy to keep --help fast."""
|
"""Main live monitoring loop. Imports are lazy to keep --help fast."""
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user