Compare commits

...

1 Commits

Author SHA1 Message Date
lrawnsley
151dadc741 fix: ignore SIGPIPE to prevent gateway crash on broken TCP connections
When a local HTTP server the gateway holds a TCP connection to is killed,
the next write to the orphaned socket can deliver SIGPIPE. If the signal
disposition has been reset to SIG_DFL, Python's process terminates
immediately, taking down the whole gateway (and every attached session)
with no exception and no reconnect.

Set SIGPIPE to SIG_IGN at gateway startup so writes to closed sockets
raise BrokenPipeError / ConnectionResetError instead, which the existing
network-error handlers already route to the reconnect / clean-shutdown
paths. Guarded by hasattr(signal, 'SIGPIPE') for Windows and
except (OSError, ValueError) for the not-in-main-thread case. Mirrors the
handler already present in tui_gateway/entry.py.
2026-06-28 20:56:26 -07:00

View File

@@ -18542,6 +18542,21 @@ async def start_gateway(config: Optional[GatewayConfig] = None, replace: bool =
logger.debug("spawn_async_diagnostic failed: %s", _e)
asyncio.create_task(runner.stop())
# Ignore SIGPIPE so that broken TCP connections (e.g. when a local
# HTTP server the gateway is connected to is killed) do not crash
# the gateway process. Python's default SIGPIPE handler terminates
# the process, which takes down the entire Telegram session. By
# ignoring the signal, writes to closed sockets raise
# BrokenPipeError / ConnectionResetError instead, which the
# existing exception handlers can catch and recover from.
if hasattr(signal, "SIGPIPE"):
try:
signal.signal(signal.SIGPIPE, signal.SIG_IGN) # windows-footgun: ok — guarded by hasattr above + try/except (OSError, ValueError)
logger.info("SIGPIPE handler set to SIG_IGN (broken-pipe protection)")
except (OSError, ValueError):
# Can fail if not in main thread or signal is blocked
pass
def restart_signal_handler():
runner.request_restart(detached=False, via_service=True)