websockets icon indicating copy to clipboard operation
websockets copied to clipboard

Threading server should close connections on exit

Open aaugustin opened this issue 1 year ago • 4 comments

Essentially, it should behave like the asyncio server. It could also gain the connections attribute.

aaugustin avatar Aug 22 '24 13:08 aaugustin

This would also be more elegant than f9cea9cca568dc92704de3744639eb4248278a8f.

aaugustin avatar Sep 09 '24 20:09 aaugustin

Implementing this may hit #1596.

aaugustin avatar Feb 16 '25 10:02 aaugustin

Hi, I just ran some tests to try to understand how the (sync) connections are handled in WebSockets (I described one in #1596).

So, what about the server side? I noticed that a server process with active connections also has some issues when exiting. I think graceful server shutdowns/restarts can be handled within the library.

I have an idea on how to fix it. Would it be okay to work on it?

Proposed approach

We can store a set of initiated threads/connections in the Server instance. Then, gracefully close all active connections in Server.shutdown(). This set, e.g. called connections, must also be accessible from conn_handler(), so we can initiate it within def serve() and either set the connections property of the newly created Server instance from this function, or (maybe more reasonable way) pass it as a constructor argument.

With this fix, it would be easier for users to implement graceful shutdowns/service restarts. Of course, threads can still be blocked in the handler functions, but that'd be a different issue.

What do you think?

darkhaniop avatar Apr 04 '25 14:04 darkhaniop

I have the same / a related issue: To terminate a threading websockets server with open connections, I have to hit Ctrl+C twice. This is a minor annoyance, but I would like to fix it. For my use case, setting daemon=True for threading.Thread in Server.serve_forever would fix the problem, as all daemon threads are automatically terminated when the main thread terminates.

Maybe someone can elaborate on the comment in sync/server.py: "we cannot use daemon threads, or else all connections would be terminate brutally when closing the server." Is there currently a way to terminate connection threads less brutally than daemon=True would? Or is there a specific use case where it is desired to terminate the listener thread but keep connection threads running?

TobiasKaiser avatar Jun 12 '25 12:06 TobiasKaiser