Skip to content

Conversation

@tsachiherman
Copy link

Issue

The existing code in go-algorand is using two go-routines for reading/writing and a separate go-routine for opening/closing the connections.
When a client connection becomes non-responsive ( i.e. the writer is not returning ), the current implementation tries to close the connection. However, per WebSocket specification, the client is supposed to send a Close message first.

The close message is being sent using the WriteControl method, which is supposed to be able to run concurrently with WriteMessage. However, both reaches Conn.write where it attempt to acquire a writing lock.

Since the WriteMessage -> Conn.write is stuck ( but the WriteControl doesn't really know it's stuck indefinitely ), the WriteControl -> Conn.write get blocks indefinitely as well.

Unlike the WriteMessage, when calling WriteControl, we provide a deadline : a timestamp after which we don't care if the message was actually sent. In this PR, I have added handling that would limit the time the Conn.write would wait to that deadline.

From spec perspective, it would be a violation of the WebSocket protocol; however, given that the other party is no longer responsive, a successful writing of a Close message is not possible, it would probably be just fine.

@tsachiherman tsachiherman requested a review from cce November 17, 2021 14:16
@tsachiherman tsachiherman self-assigned this Nov 17, 2021
@cce
Copy link

cce commented Nov 17, 2021

Related: gorilla#704

@tsachiherman tsachiherman merged commit 84c5e74 into master Nov 17, 2021
@tsachiherman tsachiherman deleted the tsachi/fixdeadlockingwrites branch November 17, 2021 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants