1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 13:16:39 +03:00

mux: avoid WindowTitleChanged cycle

double-tapping the window title could lead to a cycle between
client and server.

The cycle is broken here by having the client defer advising
the server of a title change, and sending the now-current
title rather than the title embedded in the notification
from the mux layer.

refs: #1598
refs: #522
This commit is contained in:
Wez Furlong 2023-04-03 20:22:12 -07:00
parent c3472cc969
commit 25be7fb9b1
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
3 changed files with 47 additions and 10 deletions

View File

@ -339,6 +339,7 @@ macro_rules! pdu {
Pdu::$name(s) => {
let (data, is_compressed) = serialize(s)?;
let encoded_size = encode_raw($vers, serial, &data, is_compressed, w)?;
log::debug!("encode {} size={encoded_size}", stringify!($name));
metrics::histogram!("pdu.size", encoded_size as f64, "pdu" => stringify!($name));
metrics::histogram!("pdu.size.rate", encoded_size as f64, "pdu" => stringify!($name));
Ok(())
@ -354,6 +355,7 @@ macro_rules! pdu {
Pdu::$name(s) => {
let (data, is_compressed) = serialize(s)?;
let encoded_size = encode_raw_async($vers, serial, &data, is_compressed, w).await?;
log::debug!("encode_async {} size={encoded_size}", stringify!($name));
metrics::histogram!("pdu.size", encoded_size as f64, "pdu" => stringify!($name));
metrics::histogram!("pdu.size.rate", encoded_size as f64, "pdu" => stringify!($name));
Ok(())
@ -362,6 +364,17 @@ macro_rules! pdu {
}
}
pub fn pdu_name(&self) -> &'static str {
match self {
Pdu::Invalid{..} => "Invalid",
$(
Pdu::$name(_) => {
stringify!($name)
}
,)*
}
}
pub fn decode<R: std::io::Read>(r: R) -> Result<DecodedPdu, Error> {
let decoded = decode_raw(r).context("decoding a PDU")?;
match decoded.ident {

View File

@ -391,7 +391,11 @@ async fn client_thread_async(
Ok(ReaderMessage::Readable) => {
match Pdu::decode_async(&mut stream, Some(next_serial)).await {
Ok(decoded) => {
log::trace!("decoded serial {}", decoded.serial);
log::debug!(
"decoded serial {} {}",
decoded.serial,
decoded.pdu.pdu_name()
);
if decoded.serial == 0 {
process_unilateral(local_domain_id, decoded)
.context("processing unilateral PDU from server")

View File

@ -361,17 +361,37 @@ fn mux_notify_client_domain(local_domain_id: DomainId, notif: MuxNotification) -
}
}
}
MuxNotification::WindowTitleChanged { window_id, title } => {
MuxNotification::WindowTitleChanged {
window_id,
title: _,
} => {
if let Some(remote_window_id) = client_domain.local_to_remote_window_id(window_id) {
if let Some(inner) = client_domain.inner() {
promise::spawn::spawn(async move {
inner
.client
.set_window_title(codec::WindowTitleChanged {
window_id: remote_window_id,
title,
})
.await
promise::spawn::spawn_into_main_thread(async move {
// De-bounce the title propagation.
// There is a bit of a race condition with these async
// updates that can trigger a cycle of WindowTitleChanged
// PDUs being exchanged between client and server if the
// title is changed twice in quick succession.
// To avoid that, here on the client, we wait a second
// and then report the now-current name of the window, rather
// than propagating the title encoded in the MuxNotification.
smol::Timer::after(std::time::Duration::from_secs(1)).await;
if let Some(mux) = Mux::try_get() {
let title = mux
.get_window(window_id)
.map(|win| win.get_title().to_string());
if let Some(title) = title {
inner
.client
.set_window_title(codec::WindowTitleChanged {
window_id: remote_window_id,
title,
})
.await?;
}
}
anyhow::Result::<()>::Ok(())
})
.detach();
}