mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Fix Windows PTY teardown by preserving ConPTY ownership (#20685)
## Why On Windows, background terminals could stay visible after their shell process had already exited. The elevated runner waits for the PTY output reader to reach EOF before it sends the final exit message, but the ConPTY helper was reducing ownership down to raw handles too early. That left the pseudoconsole's borrowed pipe handles alive past teardown, so EOF never propagated and the session stayed `running`. ## What changed - change `utils/pty/src/win/conpty.rs` to hand off owned ConPTY resources instead of leaking only raw handles - make `windows-sandbox-rs/src/conpty/mod.rs` keep the pseudoconsole owner and the backing pipe handles together until teardown - update the elevated runner and the legacy unified-exec backend to keep that `ConptyInstance` alive, take only the specific pipe handles they need, and drop the owner at teardown instead of trying to close a detached pseudoconsole handle later ## Testing - desktop app in `Auto-review`: 11 x `cmd /c "ping -n 3 google.com"` all exited cleanly and did not accumulate in the UI - desktop app in `Auto-review`: 5 x `cmd /c "ping -n 30 google.com"` appeared in the UI and drained back out on their own
This commit is contained in:
@@ -34,4 +34,6 @@ pub use pty::conpty_supported;
|
|||||||
/// Spawn a process attached to a PTY for interactive use.
|
/// Spawn a process attached to a PTY for interactive use.
|
||||||
pub use pty::spawn_process as spawn_pty_process;
|
pub use pty::spawn_process as spawn_pty_process;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
pub use win::PsuedoCon;
|
||||||
|
#[cfg(windows)]
|
||||||
pub use win::conpty::RawConPty;
|
pub use win::conpty::RawConPty;
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ use portable_pty::PtySystem;
|
|||||||
use portable_pty::SlavePty;
|
use portable_pty::SlavePty;
|
||||||
use portable_pty::cmdbuilder::CommandBuilder;
|
use portable_pty::cmdbuilder::CommandBuilder;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::os::windows::io::AsRawHandle;
|
|
||||||
use std::os::windows::io::RawHandle;
|
use std::os::windows::io::RawHandle;
|
||||||
|
use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use winapi::um::wincon::COORD;
|
use winapi::um::wincon::COORD;
|
||||||
@@ -82,13 +82,15 @@ impl RawConPty {
|
|||||||
self.con.raw_handle()
|
self.con.raw_handle()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_raw_handles(self) -> (RawHandle, RawHandle, RawHandle) {
|
pub fn into_handles(self) -> (PsuedoCon, FileDescriptor, FileDescriptor) {
|
||||||
let me = ManuallyDrop::new(self);
|
let me = ManuallyDrop::new(self);
|
||||||
(
|
unsafe {
|
||||||
me.con.raw_handle(),
|
(
|
||||||
me.input_write.as_raw_handle(),
|
ptr::read(&me.con),
|
||||||
me.output_read.as_raw_handle(),
|
ptr::read(&me.input_write),
|
||||||
)
|
ptr::read(&me.output_read),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ mod procthreadattr;
|
|||||||
mod psuedocon;
|
mod psuedocon;
|
||||||
|
|
||||||
pub use conpty::ConPtySystem;
|
pub use conpty::ConPtySystem;
|
||||||
|
pub use psuedocon::PsuedoCon;
|
||||||
pub use psuedocon::conpty_supported;
|
pub use psuedocon::conpty_supported;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -12,15 +12,16 @@ use crate::winutil::format_last_error;
|
|||||||
use crate::winutil::quote_windows_arg;
|
use crate::winutil::quote_windows_arg;
|
||||||
use crate::winutil::to_wide;
|
use crate::winutil::to_wide;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use codex_utils_pty::PsuedoCon;
|
||||||
use codex_utils_pty::RawConPty;
|
use codex_utils_pty::RawConPty;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
use std::os::windows::io::IntoRawHandle;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use windows_sys::Win32::Foundation::CloseHandle;
|
use windows_sys::Win32::Foundation::CloseHandle;
|
||||||
use windows_sys::Win32::Foundation::GetLastError;
|
use windows_sys::Win32::Foundation::GetLastError;
|
||||||
use windows_sys::Win32::Foundation::HANDLE;
|
use windows_sys::Win32::Foundation::HANDLE;
|
||||||
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
|
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
|
||||||
use windows_sys::Win32::System::Console::ClosePseudoConsole;
|
|
||||||
use windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT;
|
use windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT;
|
||||||
use windows_sys::Win32::System::Threading::CreateProcessAsUserW;
|
use windows_sys::Win32::System::Threading::CreateProcessAsUserW;
|
||||||
use windows_sys::Win32::System::Threading::EXTENDED_STARTUPINFO_PRESENT;
|
use windows_sys::Win32::System::Threading::EXTENDED_STARTUPINFO_PRESENT;
|
||||||
@@ -32,10 +33,10 @@ use crate::process::make_env_block;
|
|||||||
|
|
||||||
/// Owns a ConPTY handle and its backing pipe handles.
|
/// Owns a ConPTY handle and its backing pipe handles.
|
||||||
pub struct ConptyInstance {
|
pub struct ConptyInstance {
|
||||||
pub hpc: HANDLE,
|
pseudoconsole: Option<PsuedoCon>,
|
||||||
pub input_write: HANDLE,
|
input_write: HANDLE,
|
||||||
pub output_read: HANDLE,
|
output_read: HANDLE,
|
||||||
desktop: Option<LaunchDesktop>,
|
_desktop: Option<LaunchDesktop>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for ConptyInstance {
|
impl Drop for ConptyInstance {
|
||||||
@@ -47,19 +48,24 @@ impl Drop for ConptyInstance {
|
|||||||
if self.output_read != 0 && self.output_read != INVALID_HANDLE_VALUE {
|
if self.output_read != 0 && self.output_read != INVALID_HANDLE_VALUE {
|
||||||
CloseHandle(self.output_read);
|
CloseHandle(self.output_read);
|
||||||
}
|
}
|
||||||
if self.hpc != 0 && self.hpc != INVALID_HANDLE_VALUE {
|
|
||||||
ClosePseudoConsole(self.hpc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let _ = self.pseudoconsole.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConptyInstance {
|
impl ConptyInstance {
|
||||||
/// Consume the instance and return raw handles without closing them.
|
pub fn raw_handle(&self) -> Option<HANDLE> {
|
||||||
pub fn into_raw(self) -> (HANDLE, HANDLE, HANDLE, Option<LaunchDesktop>) {
|
self.pseudoconsole
|
||||||
let me = std::mem::ManuallyDrop::new(self);
|
.as_ref()
|
||||||
let desktop = unsafe { std::ptr::read(&me.desktop) };
|
.map(|pseudoconsole| pseudoconsole.raw_handle() as HANDLE)
|
||||||
(me.hpc, me.input_write, me.output_read, desktop)
|
}
|
||||||
|
|
||||||
|
pub fn take_input_write(&mut self) -> HANDLE {
|
||||||
|
std::mem::replace(&mut self.input_write, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_output_read(&mut self) -> HANDLE {
|
||||||
|
std::mem::replace(&mut self.output_read, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +76,13 @@ impl ConptyInstance {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn create_conpty(cols: i16, rows: i16) -> Result<ConptyInstance> {
|
pub fn create_conpty(cols: i16, rows: i16) -> Result<ConptyInstance> {
|
||||||
let raw = RawConPty::new(cols, rows)?;
|
let raw = RawConPty::new(cols, rows)?;
|
||||||
let (hpc, input_write, output_read) = raw.into_raw_handles();
|
let (pseudoconsole, input_write, output_read) = raw.into_handles();
|
||||||
|
|
||||||
Ok(ConptyInstance {
|
Ok(ConptyInstance {
|
||||||
hpc: hpc as HANDLE,
|
pseudoconsole: Some(pseudoconsole),
|
||||||
input_write: input_write as HANDLE,
|
input_write: input_write.into_raw_handle() as HANDLE,
|
||||||
output_read: output_read as HANDLE,
|
output_read: output_read.into_raw_handle() as HANDLE,
|
||||||
desktop: None,
|
_desktop: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +115,16 @@ pub fn spawn_conpty_process_as_user(
|
|||||||
si.StartupInfo.lpDesktop = desktop.startup_info_desktop();
|
si.StartupInfo.lpDesktop = desktop.startup_info_desktop();
|
||||||
|
|
||||||
let raw = RawConPty::new(/*cols*/ 80, /*rows*/ 24)?;
|
let raw = RawConPty::new(/*cols*/ 80, /*rows*/ 24)?;
|
||||||
let (hpc, input_write, output_read) = raw.into_raw_handles();
|
let (pseudoconsole, input_write, output_read) = raw.into_handles();
|
||||||
|
let hpc = pseudoconsole.raw_handle() as HANDLE;
|
||||||
let conpty = ConptyInstance {
|
let conpty = ConptyInstance {
|
||||||
hpc: hpc as HANDLE,
|
pseudoconsole: Some(pseudoconsole),
|
||||||
input_write: input_write as HANDLE,
|
input_write: input_write.into_raw_handle() as HANDLE,
|
||||||
output_read: output_read as HANDLE,
|
output_read: output_read.into_raw_handle() as HANDLE,
|
||||||
desktop: Some(desktop),
|
_desktop: Some(desktop),
|
||||||
};
|
};
|
||||||
let mut attrs = ProcThreadAttributeList::new(/*attr_count*/ 1)?;
|
let mut attrs = ProcThreadAttributeList::new(/*attr_count*/ 1)?;
|
||||||
attrs.set_pseudoconsole(conpty.hpc)?;
|
attrs.set_pseudoconsole(hpc)?;
|
||||||
si.lpAttributeList = attrs.as_mut_ptr();
|
si.lpAttributeList = attrs.as_mut_ptr();
|
||||||
|
|
||||||
let mut pi: PROCESS_INFORMATION = unsafe { std::mem::zeroed() };
|
let mut pi: PROCESS_INFORMATION = unsafe { std::mem::zeroed() };
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use anyhow::Result;
|
|||||||
use codex_windows_sandbox::ErrorPayload;
|
use codex_windows_sandbox::ErrorPayload;
|
||||||
use codex_windows_sandbox::ExitPayload;
|
use codex_windows_sandbox::ExitPayload;
|
||||||
use codex_windows_sandbox::FramedMessage;
|
use codex_windows_sandbox::FramedMessage;
|
||||||
use codex_windows_sandbox::LaunchDesktop;
|
|
||||||
use codex_windows_sandbox::LocalSid;
|
use codex_windows_sandbox::LocalSid;
|
||||||
use codex_windows_sandbox::Message;
|
use codex_windows_sandbox::Message;
|
||||||
use codex_windows_sandbox::OutputPayload;
|
use codex_windows_sandbox::OutputPayload;
|
||||||
@@ -57,7 +56,6 @@ use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ;
|
|||||||
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE;
|
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE;
|
||||||
use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING;
|
use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING;
|
||||||
use windows_sys::Win32::System::Console::COORD;
|
use windows_sys::Win32::System::Console::COORD;
|
||||||
use windows_sys::Win32::System::Console::ClosePseudoConsole;
|
|
||||||
use windows_sys::Win32::System::Console::ResizePseudoConsole;
|
use windows_sys::Win32::System::Console::ResizePseudoConsole;
|
||||||
use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject;
|
use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject;
|
||||||
use windows_sys::Win32::System::JobObjects::CreateJobObjectW;
|
use windows_sys::Win32::System::JobObjects::CreateJobObjectW;
|
||||||
@@ -87,8 +85,8 @@ struct IpcSpawnedProcess {
|
|||||||
stdout_handle: HANDLE,
|
stdout_handle: HANDLE,
|
||||||
stderr_handle: HANDLE,
|
stderr_handle: HANDLE,
|
||||||
stdin_handle: Option<HANDLE>,
|
stdin_handle: Option<HANDLE>,
|
||||||
|
conpty_owner: Option<codex_windows_sandbox::ConptyInstance>,
|
||||||
hpc_handle: Option<HANDLE>,
|
hpc_handle: Option<HANDLE>,
|
||||||
_desktop_owner: Option<LaunchDesktop>,
|
|
||||||
_pipe_handles: Option<PipeSpawnHandles>,
|
_pipe_handles: Option<PipeSpawnHandles>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,11 +261,11 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
|
|||||||
|
|
||||||
let effective_cwd = effective_cwd(&req.cwd, Some(log_dir.as_path()));
|
let effective_cwd = effective_cwd(&req.cwd, Some(log_dir.as_path()));
|
||||||
|
|
||||||
|
let mut conpty_owner = None;
|
||||||
let mut hpc_handle: Option<HANDLE> = None;
|
let mut hpc_handle: Option<HANDLE> = None;
|
||||||
let mut desktop_owner = None;
|
|
||||||
let mut pipe_handles = None;
|
let mut pipe_handles = None;
|
||||||
let (pi, stdout_handle, stderr_handle, stdin_handle) = if req.tty {
|
let (pi, stdout_handle, stderr_handle, stdin_handle) = if req.tty {
|
||||||
let (pi, conpty) = codex_windows_sandbox::spawn_conpty_process_as_user(
|
let (pi, mut conpty) = codex_windows_sandbox::spawn_conpty_process_as_user(
|
||||||
h_token.raw(),
|
h_token.raw(),
|
||||||
&req.command,
|
&req.command,
|
||||||
&effective_cwd,
|
&effective_cwd,
|
||||||
@@ -275,9 +273,10 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
|
|||||||
req.use_private_desktop,
|
req.use_private_desktop,
|
||||||
Some(log_dir.as_path()),
|
Some(log_dir.as_path()),
|
||||||
)?;
|
)?;
|
||||||
let (hpc, input_write, output_read, desktop) = conpty.into_raw();
|
hpc_handle = conpty.raw_handle();
|
||||||
hpc_handle = Some(hpc);
|
let input_write = conpty.take_input_write();
|
||||||
desktop_owner = desktop;
|
let output_read = conpty.take_output_read();
|
||||||
|
conpty_owner = Some(conpty);
|
||||||
let stdin_handle = if req.stdin_open {
|
let stdin_handle = if req.stdin_open {
|
||||||
Some(input_write)
|
Some(input_write)
|
||||||
} else {
|
} else {
|
||||||
@@ -323,8 +322,8 @@ fn spawn_ipc_process(req: &SpawnRequest) -> Result<IpcSpawnedProcess> {
|
|||||||
stdout_handle,
|
stdout_handle,
|
||||||
stderr_handle,
|
stderr_handle,
|
||||||
stdin_handle,
|
stdin_handle,
|
||||||
|
conpty_owner,
|
||||||
hpc_handle,
|
hpc_handle,
|
||||||
_desktop_owner: desktop_owner,
|
|
||||||
_pipe_handles: pipe_handles,
|
_pipe_handles: pipe_handles,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -526,6 +525,7 @@ pub fn main() -> Result<()> {
|
|||||||
let pi = ipc_spawn.pi;
|
let pi = ipc_spawn.pi;
|
||||||
let stdout_handle = ipc_spawn.stdout_handle;
|
let stdout_handle = ipc_spawn.stdout_handle;
|
||||||
let stderr_handle = ipc_spawn.stderr_handle;
|
let stderr_handle = ipc_spawn.stderr_handle;
|
||||||
|
let mut conpty_owner = ipc_spawn.conpty_owner;
|
||||||
let stdin_handle = ipc_spawn.stdin_handle;
|
let stdin_handle = ipc_spawn.stdin_handle;
|
||||||
let hpc_handle = Arc::new(StdMutex::new(ipc_spawn.hpc_handle));
|
let hpc_handle = Arc::new(StdMutex::new(ipc_spawn.hpc_handle));
|
||||||
|
|
||||||
@@ -605,13 +605,10 @@ pub fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(mut guard) = hpc_handle.lock()
|
if let Ok(mut guard) = hpc_handle.lock() {
|
||||||
&& let Some(hpc) = guard.take()
|
let _ = guard.take();
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
ClosePseudoConsole(hpc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
drop(conpty_owner.take());
|
||||||
|
|
||||||
let _ = out_thread.join();
|
let _ = out_thread.join();
|
||||||
if let Some(thread) = err_thread {
|
if let Some(thread) = err_thread {
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ pub use cap::load_or_create_cap_sids;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use cap::workspace_cap_sid_for_cwd;
|
pub use cap::workspace_cap_sid_for_cwd;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use conpty::ConptyInstance;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
pub use conpty::spawn_conpty_process_as_user;
|
pub use conpty::spawn_conpty_process_as_user;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use desktop::LaunchDesktop;
|
pub use desktop::LaunchDesktop;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::windows_common::finish_driver_spawn;
|
use super::windows_common::finish_driver_spawn;
|
||||||
use super::windows_common::normalize_windows_tty_input;
|
use super::windows_common::normalize_windows_tty_input;
|
||||||
use crate::acl::revoke_ace;
|
use crate::acl::revoke_ace;
|
||||||
|
use crate::conpty::ConptyInstance;
|
||||||
use crate::conpty::spawn_conpty_process_as_user;
|
use crate::conpty::spawn_conpty_process_as_user;
|
||||||
use crate::desktop::LaunchDesktop;
|
use crate::desktop::LaunchDesktop;
|
||||||
use crate::logging::log_failure;
|
use crate::logging::log_failure;
|
||||||
@@ -33,7 +34,6 @@ use windows_sys::Win32::Foundation::HANDLE;
|
|||||||
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
|
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
|
||||||
use windows_sys::Win32::Storage::FileSystem::WriteFile;
|
use windows_sys::Win32::Storage::FileSystem::WriteFile;
|
||||||
use windows_sys::Win32::System::Console::COORD;
|
use windows_sys::Win32::System::Console::COORD;
|
||||||
use windows_sys::Win32::System::Console::ClosePseudoConsole;
|
|
||||||
use windows_sys::Win32::System::Console::ResizePseudoConsole;
|
use windows_sys::Win32::System::Console::ResizePseudoConsole;
|
||||||
use windows_sys::Win32::System::Threading::GetExitCodeProcess;
|
use windows_sys::Win32::System::Threading::GetExitCodeProcess;
|
||||||
use windows_sys::Win32::System::Threading::INFINITE;
|
use windows_sys::Win32::System::Threading::INFINITE;
|
||||||
@@ -48,6 +48,7 @@ struct LegacyProcessHandles {
|
|||||||
output_join: std::thread::JoinHandle<()>,
|
output_join: std::thread::JoinHandle<()>,
|
||||||
writer_handle: tokio::task::JoinHandle<()>,
|
writer_handle: tokio::task::JoinHandle<()>,
|
||||||
hpc: Option<HANDLE>,
|
hpc: Option<HANDLE>,
|
||||||
|
conpty_owner: Option<ConptyInstance>,
|
||||||
token_handle: HANDLE,
|
token_handle: HANDLE,
|
||||||
desktop: Option<LaunchDesktop>,
|
desktop: Option<LaunchDesktop>,
|
||||||
}
|
}
|
||||||
@@ -66,8 +67,8 @@ fn spawn_legacy_process(
|
|||||||
writer_rx: mpsc::Receiver<Vec<u8>>,
|
writer_rx: mpsc::Receiver<Vec<u8>>,
|
||||||
logs_base_dir: Option<&Path>,
|
logs_base_dir: Option<&Path>,
|
||||||
) -> Result<LegacyProcessHandles> {
|
) -> Result<LegacyProcessHandles> {
|
||||||
let (pi, output_join, writer_handle, hpc, desktop) = if tty {
|
let (pi, output_join, writer_handle, hpc, conpty_owner, desktop) = if tty {
|
||||||
let (pi, conpty) = spawn_conpty_process_as_user(
|
let (pi, mut conpty) = spawn_conpty_process_as_user(
|
||||||
h_token,
|
h_token,
|
||||||
command,
|
command,
|
||||||
cwd,
|
cwd,
|
||||||
@@ -75,14 +76,14 @@ fn spawn_legacy_process(
|
|||||||
use_private_desktop,
|
use_private_desktop,
|
||||||
logs_base_dir,
|
logs_base_dir,
|
||||||
)?;
|
)?;
|
||||||
let (hpc, input_write, output_read, desktop) = conpty.into_raw();
|
let hpc = conpty.raw_handle();
|
||||||
let output_join = spawn_output_reader(output_read, stdout_tx);
|
let output_join = spawn_output_reader(conpty.take_output_read(), stdout_tx);
|
||||||
let writer_handle = spawn_input_writer(
|
let writer_handle = spawn_input_writer(
|
||||||
Some(input_write),
|
Some(conpty.take_input_write()),
|
||||||
writer_rx,
|
writer_rx,
|
||||||
/*normalize_newlines*/ true,
|
/*normalize_newlines*/ true,
|
||||||
);
|
);
|
||||||
(pi, output_join, writer_handle, Some(hpc), desktop)
|
(pi, output_join, writer_handle, hpc, Some(conpty), None)
|
||||||
} else {
|
} else {
|
||||||
let pipe_handles = spawn_process_with_pipes(
|
let pipe_handles = spawn_process_with_pipes(
|
||||||
h_token,
|
h_token,
|
||||||
@@ -120,6 +121,7 @@ fn spawn_legacy_process(
|
|||||||
output_join,
|
output_join,
|
||||||
writer_handle,
|
writer_handle,
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
Some(pipe_handles.desktop),
|
Some(pipe_handles.desktop),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -128,6 +130,7 @@ fn spawn_legacy_process(
|
|||||||
output_join,
|
output_join,
|
||||||
writer_handle,
|
writer_handle,
|
||||||
hpc,
|
hpc,
|
||||||
|
conpty_owner,
|
||||||
token_handle: h_token,
|
token_handle: h_token,
|
||||||
desktop,
|
desktop,
|
||||||
})
|
})
|
||||||
@@ -328,6 +331,7 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
|
|||||||
output_join,
|
output_join,
|
||||||
writer_handle,
|
writer_handle,
|
||||||
hpc,
|
hpc,
|
||||||
|
mut conpty_owner,
|
||||||
token_handle,
|
token_handle,
|
||||||
desktop,
|
desktop,
|
||||||
} = match spawn_legacy_process(
|
} = match spawn_legacy_process(
|
||||||
@@ -386,12 +390,10 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
|
|||||||
}
|
}
|
||||||
if let Some(hpc) = hpc_for_wait
|
if let Some(hpc) = hpc_for_wait
|
||||||
&& let Ok(mut guard) = hpc.lock()
|
&& let Ok(mut guard) = hpc.lock()
|
||||||
&& let Some(hpc) = guard.take()
|
|
||||||
{
|
{
|
||||||
unsafe {
|
let _ = guard.take();
|
||||||
ClosePseudoConsole(hpc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
drop(conpty_owner.take());
|
||||||
unsafe {
|
unsafe {
|
||||||
if token_handle != 0 && token_handle != INVALID_HANDLE_VALUE {
|
if token_handle != 0 && token_handle != INVALID_HANDLE_VALUE {
|
||||||
CloseHandle(token_handle);
|
CloseHandle(token_handle);
|
||||||
|
|||||||
Reference in New Issue
Block a user