Closed ysangkok closed 6 months ago
Would it be possible to get a traceback?
@domenkozar There is no place in SomeException that currently stores call stacks, but there are proposals about that, see 0330-exceptions-backtraces.rst
https://stackoverflow.com/questions/3757289/when-is-tcp-option-so-linger-0-required gives hints this might not be correct server behavior.
@domenkozar
A Connection Reset, as far as I understand, is something that can happen to any TCP connection. For example, this answer claims that a router can provoke a Connection Reset. The router is routing traffic oblivious to its content, it wouldn't know how to cleanly close arbitrary application protocols. And they could be using TLS, which would make it impossible.
Let's say that there is an intermediate router that crashed because it overheated or got its power supply cut. I believe that in that case, you'd receive a Connection Reset on the client, just as provoked by this server.
If we take for granted that a Connection Reset might happen occasionally to routed TCP connections on the internet, I'd say that the websockets
library should support them in a graceful manner, and, if possible, employ the Haskell type system to help the programmer handle the case even though they might not know about it.
This bug exists because I think the documentation and API design of the websockets library doesn't account for the existence of Connection Reset.
The point of the SO_LINGER is to provoke the Connection Reset without setting up an actual router and cutting power to it. I am not trying to close the connection in a graceful manner. I am using SO_LINGER not because it is required in any way (which is what the linked StackOverflow question is about), but because I believe it is the most convenient way in this example server to provoke a reset. On the client, I don't think you can tell whether SO_LINGER was used or not, so if the Connection Reset is generated, I am happy with using SO_LINGER, since it provokes the edge case I wish to demonstrate that websockets
doesn't handle well.
I submitted this issue because I think that the handling of the Connection Reset isn't modelled cleanly in the websockets
library. And I believe SO_LINGER is the most convenient manner of provoking Connection Reset.
I see similar error now when doing benchmarks: https://github.com/jaspervdj/websockets/actions/runs/7289260823/job/19863526629?pr=235#step:11:152
When receving messages we should catch isResourceVanishedError and throw it as connection closed.
It's an exception that the socket was closed and the operation failed.
I tested the linked PR which seems to make the reset appear as a close:
inner Caught: SomeException : ConnectionClosed: ConnectionClosed
All good!
This means the API user won't be able to tell the difference, but I suppose that's on purpose. So it seems to work as intended.
Using this client:
and this server:
After 3 seconds, I get the following message in the client:
This is an IOException/IOError thrown in
receiveDataMessage
. The documentation claims "This will throw ConnectionClosed if the TCP connection dies unexpectedly." But isn't a Connection Reset a kind of connection closing? I think the documentation is misleading to not mention the IOException. One gets the impression that only ConnectionException (the type of ConnectionClosed) needs to get caught.Tagging @OwenGraves.