Fix unified_exec on windows (#7620)

Fix unified_exec on windows

Requires removal of PSUEDOCONSOLE_INHERIT_CURSOR flag so child processed
don't attempt to wait for cursor position response (and timeout).


https://github.com/wezterm/wezterm/compare/main...pakrym:wezterm:PSUEDOCONSOLE_INHERIT_CURSOR?expand=1

---------

Co-authored-by: pakrym-oai <pakrym@openai.com>
This commit is contained in:
Pavel Krymets
2025-12-05 12:09:43 -08:00
committed by GitHub
parent a8cbbdbc6e
commit f48d88067e
6 changed files with 128 additions and 11 deletions

View File

@@ -1,3 +1,4 @@
use core::fmt;
use std::collections::HashMap;
use std::io::ErrorKind;
use std::path::Path;
@@ -9,13 +10,20 @@ use std::time::Duration;
use anyhow::Result;
use portable_pty::native_pty_system;
use portable_pty::CommandBuilder;
use portable_pty::MasterPty;
use portable_pty::PtySize;
use portable_pty::SlavePty;
use tokio::sync::broadcast;
use tokio::sync::mpsc;
use tokio::sync::oneshot;
use tokio::sync::Mutex as TokioMutex;
use tokio::task::JoinHandle;
pub struct PtyPairWrapper {
pub _slave: Option<Box<dyn SlavePty + Send>>,
pub _master: Box<dyn MasterPty + Send>,
}
#[derive(Debug)]
pub struct ExecCommandSession {
writer_tx: mpsc::Sender<Vec<u8>>,
@@ -26,6 +34,15 @@ pub struct ExecCommandSession {
wait_handle: StdMutex<Option<JoinHandle<()>>>,
exit_status: Arc<AtomicBool>,
exit_code: Arc<StdMutex<Option<i32>>>,
// PtyPair must be preserved because the process will receive Control+C if the
// slave is closed
_pair: StdMutex<PtyPairWrapper>,
}
impl fmt::Debug for PtyPairWrapper {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
impl ExecCommandSession {
@@ -39,6 +56,7 @@ impl ExecCommandSession {
wait_handle: JoinHandle<()>,
exit_status: Arc<AtomicBool>,
exit_code: Arc<StdMutex<Option<i32>>>,
pair: PtyPairWrapper,
) -> (Self, broadcast::Receiver<Vec<u8>>) {
let initial_output_rx = output_tx.subscribe();
(
@@ -51,6 +69,7 @@ impl ExecCommandSession {
wait_handle: StdMutex::new(Some(wait_handle)),
exit_status,
exit_code,
_pair: StdMutex::new(pair),
},
initial_output_rx,
)
@@ -192,6 +211,16 @@ pub async fn spawn_pty_process(
let _ = exit_tx.send(code);
});
let pair = PtyPairWrapper {
_slave: if cfg!(windows) {
// Keep the slave handle alive on Windows to prevent the process from receiving Control+C
Some(pair.slave)
} else {
None
},
_master: pair.master,
};
let (session, output_rx) = ExecCommandSession::new(
writer_tx,
output_tx,
@@ -201,6 +230,7 @@ pub async fn spawn_pty_process(
wait_handle,
exit_status,
exit_code,
pair,
);
Ok(SpawnedPty {