mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-06-25 17:29:24 +08:00
fix: catch OSError in websocket send to prevent server crash send_socket_catch_exception only caught ConnectionError and its
subclasses (ConnectionResetError, BrokenPipeError). When a client becomes unreachable mid-generation (laptop sleeps, drops off WiFi), the OS raises OSError: [Errno 113] No route to host (EHOSTUNREACH), which is a sibling of ConnectionError, not a subclass. It therefore escaped the handler, propagated through publish_loop, and could crash the entire server over a single dead client.
This commit is contained in:
parent
e1b9366898
commit
a4342e9aa1
@ -64,7 +64,7 @@ def _remove_sensitive_from_queue(queue: list) -> list:
|
|||||||
async def send_socket_catch_exception(function, message):
|
async def send_socket_catch_exception(function, message):
|
||||||
try:
|
try:
|
||||||
await function(message)
|
await function(message)
|
||||||
except (aiohttp.ClientError, aiohttp.ClientPayloadError, ConnectionResetError, BrokenPipeError, ConnectionError) as err:
|
except (aiohttp.ClientError, aiohttp.ClientPayloadError, OSError) as err:
|
||||||
logging.warning("send error: {}".format(err))
|
logging.warning("send error: {}".format(err))
|
||||||
|
|
||||||
# Track deprecated paths that have been warned about to only warn once per file
|
# Track deprecated paths that have been warned about to only warn once per file
|
||||||
|
|||||||
38
tests-unit/server_test/test_send_socket_catch_exception.py
Normal file
38
tests-unit/server_test/test_send_socket_catch_exception.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""Tests for server.send_socket_catch_exception.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import utils.install_util # noqa: F401
|
||||||
|
from server import send_socket_catch_exception
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.asyncio
|
||||||
|
|
||||||
|
|
||||||
|
class TestSendSocketCatchException:
|
||||||
|
"""The send helper must swallow client-disconnect errors, never propagate them."""
|
||||||
|
|
||||||
|
async def test_swallows_no_route_to_host(self, caplog):
|
||||||
|
|
||||||
|
async def failing_send(_message):
|
||||||
|
raise OSError(113, "No route to host")
|
||||||
|
|
||||||
|
await send_socket_catch_exception(failing_send, b"payload")
|
||||||
|
assert "send error" in caplog.text
|
||||||
|
|
||||||
|
async def test_swallows_connection_reset(self):
|
||||||
|
"""Existing behaviour preserved: ConnectionResetError is still caught."""
|
||||||
|
|
||||||
|
async def failing_send(_message):
|
||||||
|
raise ConnectionResetError("peer reset the connection")
|
||||||
|
|
||||||
|
await send_socket_catch_exception(failing_send, b"payload")
|
||||||
|
|
||||||
|
async def test_successful_send_delivers_message(self):
|
||||||
|
"""When the send succeeds the message is passed through and nothing is logged."""
|
||||||
|
received = []
|
||||||
|
|
||||||
|
async def ok_send(message):
|
||||||
|
received.append(message)
|
||||||
|
|
||||||
|
await send_socket_catch_exception(ok_send, b"hello")
|
||||||
|
assert received == [b"hello"]
|
||||||
Loading…
Reference in New Issue
Block a user