Skip to content

[Bug]: AsyncWebSocketConnection either doesn't close the socket or hangs for 10 seconds when it does #114

Description

@aFlocker

SDK package and version

polymarket-client==0.1.0b7

Runtime

Python 3.14.3, uv 0.10.6

What happened?

2 related problems I found:

1) If I press Ctrl+C in the middle of an event stream, it will exit immediately without closing the socket
I belive this is because the KeyboardInterrupt exception is caught in the try block of _read_loop() in _internal/ws/connection.py and in the finally: on line 177 it claims the socket but then never calls socket.close()
Maybe this was on purpose or it was assumed the socket was dropped? Any subsequent cleanup code that calls AsyncWebSocketConnection.close() which calls ._shutdown(), will also not close the socket because it has already been claimed.

2) Conversely, if any error is thrown higher up, inside the event stream context, it will hang for 10 seconds before exiting the context
The cleanup code will correctly end up calling AsyncWebSocketConnection.close() which will call ._shutdown() and that will be able to claim the socket, but when it calls socket.close() it will hang for 10 seconds. It looks like it's sending the close frame but the polymarket server isn't acknowledging it, so it has to wait for a timeout. One solution might be to expose a close_timeout_s similar to the open_timeout_s in the __init__()?

Minimal reproduction

try:
    async with AsyncPublicClient() as client:
        stream = await client.subscribe(
            CryptoPricesSpec(
                topic="prices.crypto.binance",
                symbols=["btcusdt"],
            )
        )
        async with stream:
            async for event in stream:
                raise RuntimeError("Error inside event")
                # if this is the only stream subscribed
                # it will hang for 10 seconds trying to close the socket
except Exception as e:
    # it will take 10 seconds 
    # from the error being thrown
    # before it even reaches this point
    pass

Expected behavior, actual behavior, or logs

It would be great if when an error is encountered inside the event stream handling it could be caught immediately so one could re-subscribe ASAP

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions