mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
gui: Avoid 450ms delay on startup(!)
In the case that the published symlink is stale, our default client connection logic was to retry connecting with backoff to give a newly spawned server a chance to startup. In the context of a newly launched gui process checking to see if an existing gui process can serve the same request, we don't need to give it any grace: it will either answer immediately or be deemed not useful. This commit limits us to a single connection attempt in the case where we're not automatically starting the server, which in turn constrains the overhead to something in the order of microseconds rather than nearly 0.5 seconds. While we're in here, I noticed that if we thought we had a socket to try and that failed, we'd always try to publish a new symlink. However, if we failed due to mismatched version info, we shouldn't publish over the top of the already running instance. refs: #1529
This commit is contained in:
parent
d1018c37ff
commit
58d969e77c
@ -164,12 +164,19 @@ fn process_unilateral(
|
|||||||
local_domain_id: Option<DomainId>,
|
local_domain_id: Option<DomainId>,
|
||||||
decoded: DecodedPdu,
|
decoded: DecodedPdu,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let local_domain_id = local_domain_id.ok_or_else(|| {
|
let local_domain_id = match local_domain_id {
|
||||||
anyhow::anyhow!(
|
Some(id) => id,
|
||||||
|
None => {
|
||||||
|
// FIXME: We currently get a bunch of these; we'll need
|
||||||
|
// to do something to advise the server when we want them.
|
||||||
|
// For now, we just ignore them.
|
||||||
|
log::trace!(
|
||||||
"client doesn't have a real local domain, \
|
"client doesn't have a real local domain, \
|
||||||
so unilateral message cannot be processed by it"
|
so unilateral message cannot be processed by it"
|
||||||
)
|
);
|
||||||
})?;
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
if let Some(pane_id) = decoded.pdu.pane_id() {
|
if let Some(pane_id) = decoded.pdu.pane_id() {
|
||||||
promise::spawn::spawn_into_main_thread(async move {
|
promise::spawn::spawn_into_main_thread(async move {
|
||||||
process_unilateral_inner(pane_id, local_domain_id, decoded)
|
process_unilateral_inner(pane_id, local_domain_id, decoded)
|
||||||
@ -281,6 +288,7 @@ async fn client_thread_async(
|
|||||||
pub fn unix_connect_with_retry(
|
pub fn unix_connect_with_retry(
|
||||||
target: &UnixTarget,
|
target: &UnixTarget,
|
||||||
just_spawned: bool,
|
just_spawned: bool,
|
||||||
|
max_attempts: Option<u64>,
|
||||||
) -> anyhow::Result<UnixStream> {
|
) -> anyhow::Result<UnixStream> {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
@ -288,7 +296,9 @@ pub fn unix_connect_with_retry(
|
|||||||
std::thread::sleep(std::time::Duration::from_millis(200));
|
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
}
|
}
|
||||||
|
|
||||||
for iter in 0..10 {
|
let max_attempts = max_attempts.unwrap_or(10);
|
||||||
|
|
||||||
|
for iter in 0..max_attempts {
|
||||||
if iter > 0 {
|
if iter > 0 {
|
||||||
std::thread::sleep(std::time::Duration::from_millis(iter * 10));
|
std::thread::sleep(std::time::Duration::from_millis(iter * 10));
|
||||||
}
|
}
|
||||||
@ -561,7 +571,9 @@ impl Reconnectable {
|
|||||||
ui.output_str(&format!("Connect to {:?}\n", target));
|
ui.output_str(&format!("Connect to {:?}\n", target));
|
||||||
log::trace!("connect to {:?}", target);
|
log::trace!("connect to {:?}", target);
|
||||||
|
|
||||||
let stream = match unix_connect_with_retry(&target, false) {
|
let max_attempts = if no_auto_start { Some(1) } else { None };
|
||||||
|
|
||||||
|
let stream = match unix_connect_with_retry(&target, false, max_attempts) {
|
||||||
Ok(stream) => stream,
|
Ok(stream) => stream,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if no_auto_start || unix_dom.no_serve_automatically || !initial {
|
if no_auto_start || unix_dom.no_serve_automatically || !initial {
|
||||||
@ -603,7 +615,7 @@ impl Reconnectable {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
unix_connect_with_retry(&target, true).with_context(|| {
|
unix_connect_with_retry(&target, true, None).with_context(|| {
|
||||||
format!("(after spawning server) failed to connect to {:?}", target)
|
format!("(after spawning server) failed to connect to {:?}", target)
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ impl Publish {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_spawn(
|
pub fn try_spawn(
|
||||||
&self,
|
&mut self,
|
||||||
cmd: Option<CommandBuilder>,
|
cmd: Option<CommandBuilder>,
|
||||||
config: &ConfigHandle,
|
config: &ConfigHandle,
|
||||||
) -> anyhow::Result<bool> {
|
) -> anyhow::Result<bool> {
|
||||||
@ -437,12 +437,14 @@ impl Publish {
|
|||||||
let vers = client.verify_version_compat(&mut ui).await?;
|
let vers = client.verify_version_compat(&mut ui).await?;
|
||||||
|
|
||||||
if vers.executable_path != std::env::current_exe().context("resolve executable path")? {
|
if vers.executable_path != std::env::current_exe().context("resolve executable path")? {
|
||||||
|
*self = Publish::NoConnectNoPublish;
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Running GUI is a different executable from us, will start a new one");
|
"Running GUI is a different executable from us, will start a new one");
|
||||||
}
|
}
|
||||||
if vers.config_file_path
|
if vers.config_file_path
|
||||||
!= std::env::var_os("WEZTERM_CONFIG_FILE").map(Into::into)
|
!= std::env::var_os("WEZTERM_CONFIG_FILE").map(Into::into)
|
||||||
{
|
{
|
||||||
|
*self = Publish::NoConnectNoPublish;
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Running GUI has different config from us, will start a new one"
|
"Running GUI has different config from us, will start a new one"
|
||||||
);
|
);
|
||||||
@ -567,7 +569,7 @@ fn run_terminal_gui(opts: StartCommand) -> anyhow::Result<()> {
|
|||||||
// First, let's see if we can ask an already running wezterm to do this.
|
// First, let's see if we can ask an already running wezterm to do this.
|
||||||
// We must do this before we start the gui frontend as the scheduler
|
// We must do this before we start the gui frontend as the scheduler
|
||||||
// requirements are different.
|
// requirements are different.
|
||||||
let publish = Publish::resolve(&mux, &config, opts.always_new_process);
|
let mut publish = Publish::resolve(&mux, &config, opts.always_new_process);
|
||||||
log::trace!("{:?}", publish);
|
log::trace!("{:?}", publish);
|
||||||
if publish.try_spawn(cmd.clone(), &config)? {
|
if publish.try_spawn(cmd.clone(), &config)? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -578,7 +578,7 @@ async fn run_cli_async(config: config::ConfigHandle, cli: CliCommand) -> anyhow:
|
|||||||
Mux::set_mux(&mux);
|
Mux::set_mux(&mux);
|
||||||
let unix_dom = config.unix_domains.first().unwrap();
|
let unix_dom = config.unix_domains.first().unwrap();
|
||||||
let target = unix_dom.target();
|
let target = unix_dom.target();
|
||||||
let stream = unix_connect_with_retry(&target, false)?;
|
let stream = unix_connect_with_retry(&target, false, None)?;
|
||||||
|
|
||||||
// Spawn a thread to pull data from the socket and write
|
// Spawn a thread to pull data from the socket and write
|
||||||
// it to stdout
|
// it to stdout
|
||||||
|
Loading…
Reference in New Issue
Block a user