aboutsummaryrefslogtreecommitdiff
path: root/src/server/client_transport.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-08-10 21:01:45 +0300
committerGitHub <noreply@github.com>2026-08-10 21:01:45 +0300
commit7e4ab7b034078b5ac22b514fb7008f0b288687a6 (patch)
tree1512a1e625f6609268131a3edf5f707089f86b3d /src/server/client_transport.rs
parentbbd7c2094a44fcbcc4a3a3aedef236c4d697d793 (diff)
fix(server): prioritize shutdown requests (#2624)
refs #2612
Diffstat (limited to 'src/server/client_transport.rs')
-rw-r--r--src/server/client_transport.rs36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/server/client_transport.rs b/src/server/client_transport.rs
index b5023b97..f1237c89 100644
--- a/src/server/client_transport.rs
+++ b/src/server/client_transport.rs
@@ -522,6 +522,10 @@ pub(crate) fn handle_client_handshake(
server_event_tx: &mpsc::Sender<ServerEvent>,
should_quit: &Arc<AtomicBool>,
) -> io::Result<()> {
+ if should_quit.load(Ordering::Acquire) {
+ return Ok(());
+ }
+
// Reset to blocking mode — the accept loop sets nonblocking but
// the handshake thread needs blocking I/O for read_message/write_message.
stream.set_nonblocking(false)?;
@@ -624,6 +628,10 @@ pub(crate) fn handle_client_handshake(
}
};
+ if should_quit.load(Ordering::Acquire) {
+ return Ok(());
+ }
+
// Send Welcome.
let welcome = ServerMessage::Welcome {
version: PROTOCOL_VERSION,
@@ -653,8 +661,13 @@ pub(crate) fn handle_client_handshake(
client_writer_loop(write_stream, client_id, writer_queue, writer_event_tx);
});
+ if should_quit.load(Ordering::Acquire) {
+ send_shutdown_to_unregistered_client(&writer);
+ return Ok(());
+ }
+
// Notify the main loop about the new client.
- let _ = server_event_tx.blocking_send(ServerEvent::ClientConnected {
+ let connected = ServerEvent::ClientConnected {
client_id,
cols: client_cols,
rows: client_rows,
@@ -665,12 +678,31 @@ pub(crate) fn handle_client_handshake(
direct_attach_requested,
direct_graphics,
writer,
- });
+ };
+ if let Err(err) = server_event_tx.blocking_send(connected) {
+ if let ServerEvent::ClientConnected { writer, .. } = err.0 {
+ send_shutdown_to_unregistered_client(&writer);
+ }
+ }
// Enter read loop — read client messages and forward to main loop.
client_read_loop(stream, client_id, server_event_tx, should_quit)
}
+fn send_shutdown_to_unregistered_client(writer: &ClientWriter) {
+ let mut framed = Vec::new();
+ if protocol::write_message(
+ &mut framed,
+ &ServerMessage::ServerShutdown {
+ reason: Some("server is shutting down".to_owned()),
+ },
+ )
+ .is_ok()
+ {
+ let _ = writer.control.send(framed);
+ }
+}
+
/// The client writer loop — prioritizes control messages over render frames.
fn client_writer_loop(
mut stream: LocalStream,