fix(remoteingress-core): guard tunnel frame sends with cancellation to prevent async send deadlocks

This commit is contained in:
2026-03-17 12:47:03 +00:00
parent 9a8760c18d
commit bfd9e58b4f
4 changed files with 41 additions and 11 deletions

View File

@@ -739,7 +739,11 @@ async fn handle_client_connection(
// Send OPEN frame with PROXY v1 header via control channel
let proxy_header = build_proxy_v1_header(&client_ip, edge_ip, client_port, dest_port);
let open_frame = encode_frame(stream_id, FRAME_OPEN, proxy_header.as_bytes());
if tunnel_ctrl_tx.send(open_frame).await.is_err() {
let send_ok = tokio::select! {
result = tunnel_ctrl_tx.send(open_frame) => result.is_ok(),
_ = client_token.cancelled() => false,
};
if !send_ok {
return;
}
@@ -814,7 +818,10 @@ async fn handle_client_connection(
// Send final window update for any remaining consumed bytes
if consumed_since_update > 0 {
let frame = encode_window_update(stream_id, FRAME_WINDOW_UPDATE, consumed_since_update);
let _ = wu_tx.send(frame).await;
tokio::select! {
_ = wu_tx.send(frame) => {}
_ = hub_to_client_token.cancelled() => {}
}
}
let _ = client_write.shutdown().await;
});
@@ -890,9 +897,13 @@ async fn handle_client_connection(
).await;
// NOW send CLOSE — the response has been fully delivered (or timed out).
// select! with cancellation guard prevents indefinite blocking if tunnel dies.
if !client_token.is_cancelled() {
let close_frame = encode_frame(stream_id, FRAME_CLOSE, &[]);
let _ = tunnel_data_tx.send(close_frame).await;
tokio::select! {
_ = tunnel_data_tx.send(close_frame) => {}
_ = client_token.cancelled() => {}
}
}
// Clean up