Skip to content

Prevent WebSocket._thread from speed-reading closed sockets#3

Open
rdash-fenix wants to merge 1 commit intoch-iv:mainfrom
rdash-fenix:safe_hard_close
Open

Prevent WebSocket._thread from speed-reading closed sockets#3
rdash-fenix wants to merge 1 commit intoch-iv:mainfrom
rdash-fenix:safe_hard_close

Conversation

@rdash-fenix
Copy link
Copy Markdown

Noticed that a program I was writing in flask had a very high CPU usage, py-spy and some tinkering led me to discover it was an endless loop in WebSocket._thread. I could repeatably cause the fault condition by opening the endpoint in curl and then killing it so it could not send a close message.

Per python's socket documentation, calls to recv() on a closed socket do not yield an OSError like one would expect, but instead simply return an empty bytes instance. Between this and wsproto's parser just returning None when it receives an empty bytes instance, you have a loop that pegs the CPU.

My patch simply adds a check for an empty return, and injects the OSError the code is otherwise expecting. The other case where recv() could return no bytes is if a zero-length datagram was received (which would not be possible/valid given websocket's use of TCP), so this simple check should be safe.

Passed against the test suite, and functions correctly against both of the provided examples (as well as the codebase where I discovered it).

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.

1 participant