Remove unnecessary lifetimes from winpty
This commit is contained in:
parent
047719bcd2
commit
72df0c06bf
|
@ -98,11 +98,7 @@ impl Drop for Conpty {
|
||||||
unsafe impl Send for Conpty {}
|
unsafe impl Send for Conpty {}
|
||||||
unsafe impl Sync for Conpty {}
|
unsafe impl Sync for Conpty {}
|
||||||
|
|
||||||
pub fn new<'a, C>(
|
pub fn new<C>(config: &Config<C>, size: &SizeInfo, _window_id: Option<usize>) -> Option<Pty> {
|
||||||
config: &Config<C>,
|
|
||||||
size: &SizeInfo,
|
|
||||||
_window_id: Option<usize>,
|
|
||||||
) -> Option<Pty<'a>> {
|
|
||||||
if !config.enable_experimental_conpty_backend {
|
if !config.enable_experimental_conpty_backend {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +128,7 @@ pub fn new<'a, C>(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(result == S_OK);
|
assert_eq!(result, S_OK);
|
||||||
|
|
||||||
let mut success;
|
let mut success;
|
||||||
|
|
||||||
|
@ -266,7 +262,7 @@ impl OnResize for ConptyHandle {
|
||||||
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
||||||
if let Some(coord) = coord_from_sizeinfo(sizeinfo) {
|
if let Some(coord) = coord_from_sizeinfo(sizeinfo) {
|
||||||
let result = unsafe { (self.api.ResizePseudoConsole)(self.handle, coord) };
|
let result = unsafe { (self.api.ResizePseudoConsole)(self.handle, coord) };
|
||||||
assert!(result == S_OK);
|
assert_eq!(result, S_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,13 @@ pub fn is_conpty() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum PtyHandle<'a> {
|
pub enum PtyHandle {
|
||||||
Winpty(winpty::WinptyHandle<'a>),
|
Winpty(winpty::WinptyHandle),
|
||||||
Conpty(conpty::ConptyHandle),
|
Conpty(conpty::ConptyHandle),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pty<'a> {
|
pub struct Pty {
|
||||||
handle: PtyHandle<'a>,
|
handle: PtyHandle,
|
||||||
// TODO: It's on the roadmap for the Conpty API to support Overlapped I/O.
|
// TODO: It's on the roadmap for the Conpty API to support Overlapped I/O.
|
||||||
// See https://github.com/Microsoft/console/issues/262
|
// See https://github.com/Microsoft/console/issues/262
|
||||||
// When support for that lands then it should be possible to use
|
// When support for that lands then it should be possible to use
|
||||||
|
@ -58,13 +58,13 @@ pub struct Pty<'a> {
|
||||||
child_watcher: ChildExitWatcher,
|
child_watcher: ChildExitWatcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Pty<'a> {
|
impl Pty {
|
||||||
pub fn resize_handle(&self) -> impl OnResize + 'a {
|
pub fn resize_handle(&self) -> impl OnResize {
|
||||||
self.handle.clone()
|
self.handle.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<'a, C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) -> Pty<'a> {
|
pub fn new<C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) -> Pty {
|
||||||
if let Some(pty) = conpty::new(config, size, window_id) {
|
if let Some(pty) = conpty::new(config, size, window_id) {
|
||||||
info!("Using Conpty agent");
|
info!("Using Conpty agent");
|
||||||
IS_CONPTY.store(true, Ordering::Relaxed);
|
IS_CONPTY.store(true, Ordering::Relaxed);
|
||||||
|
@ -187,7 +187,7 @@ impl Write for EventedWritablePipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> OnResize for PtyHandle<'a> {
|
impl OnResize for PtyHandle {
|
||||||
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
||||||
match self {
|
match self {
|
||||||
PtyHandle::Winpty(w) => w.resize(sizeinfo),
|
PtyHandle::Winpty(w) => w.resize(sizeinfo),
|
||||||
|
@ -199,7 +199,7 @@ impl<'a> OnResize for PtyHandle<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EventedReadWrite for Pty<'a> {
|
impl EventedReadWrite for Pty {
|
||||||
type Reader = EventedReadablePipe;
|
type Reader = EventedReadablePipe;
|
||||||
type Writer = EventedWritablePipe;
|
type Writer = EventedWritablePipe;
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ impl<'a> EventedReadWrite for Pty<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EventedPty for Pty<'a> {
|
impl EventedPty for Pty {
|
||||||
fn child_event_token(&self) -> mio::Token {
|
fn child_event_token(&self) -> mio::Token {
|
||||||
self.child_event_token
|
self.child_event_token
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,24 +34,24 @@ use crate::tty::windows::Pty;
|
||||||
// We store a raw pointer because we need mutable access to call
|
// We store a raw pointer because we need mutable access to call
|
||||||
// on_resize from a separate thread. Winpty internally uses a mutex
|
// on_resize from a separate thread. Winpty internally uses a mutex
|
||||||
// so this is safe, despite outwards appearance.
|
// so this is safe, despite outwards appearance.
|
||||||
pub struct Agent<'a> {
|
pub struct Agent {
|
||||||
winpty: *mut Winpty<'a>,
|
winpty: *mut Winpty,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle can be cloned freely and moved between threads.
|
/// Handle can be cloned freely and moved between threads.
|
||||||
pub type WinptyHandle<'a> = Arc<Agent<'a>>;
|
pub type WinptyHandle = Arc<Agent>;
|
||||||
|
|
||||||
// Because Winpty has a mutex, we can do this.
|
// Because Winpty has a mutex, we can do this.
|
||||||
unsafe impl<'a> Send for Agent<'a> {}
|
unsafe impl Send for Agent {}
|
||||||
unsafe impl<'a> Sync for Agent<'a> {}
|
unsafe impl Sync for Agent {}
|
||||||
|
|
||||||
impl<'a> Agent<'a> {
|
impl Agent {
|
||||||
pub fn new(winpty: Winpty<'a>) -> Self {
|
pub fn new(winpty: Winpty) -> Self {
|
||||||
Self { winpty: Box::into_raw(Box::new(winpty)) }
|
Self { winpty: Box::into_raw(Box::new(winpty)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get immutable access to Winpty.
|
/// Get immutable access to Winpty.
|
||||||
pub fn winpty(&self) -> &Winpty<'a> {
|
pub fn winpty(&self) -> &Winpty {
|
||||||
unsafe { &*self.winpty }
|
unsafe { &*self.winpty }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ impl<'a> Agent<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for Agent<'a> {
|
impl Drop for Agent {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
Box::from_raw(self.winpty);
|
Box::from_raw(self.winpty);
|
||||||
|
@ -75,7 +75,7 @@ impl<'a> Drop for Agent<'a> {
|
||||||
/// This is a placeholder value until we see how often long responses happen
|
/// This is a placeholder value until we see how often long responses happen
|
||||||
const AGENT_TIMEOUT: u32 = 10000;
|
const AGENT_TIMEOUT: u32 = 10000;
|
||||||
|
|
||||||
pub fn new<'a, C>(config: &Config<C>, size: &SizeInfo, _window_id: Option<usize>) -> Pty<'a> {
|
pub fn new<C>(config: &Config<C>, size: &SizeInfo, _window_id: Option<usize>) -> Pty {
|
||||||
// Create config
|
// Create config
|
||||||
let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap();
|
let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap();
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ pub fn new<'a, C>(config: &Config<C>, size: &SizeInfo, _window_id: Option<usize>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> OnResize for Winpty<'a> {
|
impl OnResize for Winpty {
|
||||||
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
||||||
let (cols, lines) = (sizeinfo.cols().0, sizeinfo.lines().0);
|
let (cols, lines) = (sizeinfo.cols().0, sizeinfo.lines().0);
|
||||||
if cols > 0 && cols <= u16::MAX as usize && lines > 0 && lines <= u16::MAX as usize {
|
if cols > 0 && cols <= u16::MAX as usize && lines > 0 && lines <= u16::MAX as usize {
|
||||||
|
|
|
@ -20,17 +20,20 @@ pub enum ErrorCodes {
|
||||||
AgentTimeout,
|
AgentTimeout,
|
||||||
AgentCreationFailed,
|
AgentCreationFailed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MouseMode {
|
pub enum MouseMode {
|
||||||
None,
|
None,
|
||||||
Auto,
|
Auto,
|
||||||
Force,
|
Force,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags!(
|
bitflags!(
|
||||||
pub struct SpawnFlags: u64 {
|
pub struct SpawnFlags: u64 {
|
||||||
const AUTO_SHUTDOWN = 0x1;
|
const AUTO_SHUTDOWN = 0x1;
|
||||||
const EXIT_AFTER_SHUTDOWN = 0x2;
|
const EXIT_AFTER_SHUTDOWN = 0x2;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
bitflags!(
|
bitflags!(
|
||||||
pub struct ConfigFlags: u64 {
|
pub struct ConfigFlags: u64 {
|
||||||
const CONERR = 0x1;
|
const CONERR = 0x1;
|
||||||
|
@ -40,42 +43,32 @@ bitflags!(
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Err<'a> {
|
pub struct Err {
|
||||||
ptr: &'a mut winpty_error_t,
|
|
||||||
code: u32,
|
code: u32,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see whether winpty gave us an error
|
// Check to see whether winpty gave us an error, and perform the necessary memory freeing
|
||||||
fn check_err<'a>(e: *mut winpty_error_t) -> Option<Err<'a>> {
|
fn check_err(e: *mut winpty_error_t) -> Option<Err> {
|
||||||
let err = unsafe {
|
unsafe {
|
||||||
|
let code = winpty_error_code(e);
|
||||||
let raw = winpty_error_msg(e);
|
let raw = winpty_error_msg(e);
|
||||||
Err {
|
let message = String::from_utf16_lossy(std::slice::from_raw_parts(raw, wcslen(raw)));
|
||||||
ptr: &mut *e,
|
winpty_error_free(e);
|
||||||
code: winpty_error_code(e),
|
match code {
|
||||||
message: String::from_utf16_lossy(std::slice::from_raw_parts(raw, wcslen(raw))),
|
0 => None,
|
||||||
|
_ => Some(Err { code, message }),
|
||||||
}
|
}
|
||||||
};
|
|
||||||
if err.code == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for Err<'a> {
|
impl Display for Err {
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
winpty_error_free(self.ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> Display for Err<'a> {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
write!(f, "Code: {}, Message: {}", self.code, self.message)
|
write!(f, "Code: {}, Message: {}", self.code, self.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> Error for Err<'a> {
|
|
||||||
|
impl Error for Err {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
&self.message
|
&self.message
|
||||||
}
|
}
|
||||||
|
@ -83,18 +76,13 @@ impl<'a> Error for Err<'a> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Winpty agent config
|
/// Winpty agent config
|
||||||
pub struct Config<'a>(&'a mut winpty_config_t);
|
pub struct Config(*mut winpty_config_t);
|
||||||
|
|
||||||
impl<'a, 'b> Config<'a> {
|
impl Config {
|
||||||
pub fn new(flags: ConfigFlags) -> Result<Self, Err<'b>> {
|
pub fn new(flags: ConfigFlags) -> Result<Self, Err> {
|
||||||
let mut err = null_mut() as *mut winpty_error_t;
|
let mut err = null_mut() as *mut winpty_error_t;
|
||||||
let config = unsafe { winpty_config_new(flags.bits(), &mut err) };
|
let config = unsafe { winpty_config_new(flags.bits(), &mut err) };
|
||||||
|
check_err(err).map_or(Ok(Self(config)), Result::Err)
|
||||||
if let Some(err) = check_err(err) {
|
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
unsafe { Ok(Config(&mut *config)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the initial size of the console window
|
/// Set the initial size of the console window
|
||||||
|
@ -127,7 +115,7 @@ impl<'a, 'b> Config<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for Config<'a> {
|
impl Drop for Config {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
winpty_config_free(self.0);
|
winpty_config_free(self.0);
|
||||||
|
@ -137,23 +125,16 @@ impl<'a> Drop for Config<'a> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// A struct representing the winpty agent process
|
/// A struct representing the winpty agent process
|
||||||
pub struct Winpty<'a>(&'a mut winpty_t);
|
pub struct Winpty(*mut winpty_t);
|
||||||
|
|
||||||
impl<'a, 'b> Winpty<'a> {
|
impl Winpty {
|
||||||
/// Starts the agent. This process will connect to the agent
|
/// Starts the agent. This process will connect to the agent
|
||||||
/// over a control pipe, and the agent will open data pipes
|
/// over a control pipe, and the agent will open data pipes
|
||||||
/// (e.g. CONIN and CONOUT).
|
/// (e.g. CONIN and CONOUT).
|
||||||
pub fn open(cfg: &Config) -> Result<Self, Err<'b>> {
|
pub fn open(cfg: &Config) -> Result<Self, Err> {
|
||||||
let mut err = null_mut() as *mut winpty_error_t;
|
let mut err = null_mut() as *mut winpty_error_t;
|
||||||
unsafe {
|
let winpty = unsafe { winpty_open(cfg.0, &mut err) };
|
||||||
let winpty = winpty_open(cfg.0, &mut err);
|
check_err(err).map_or(Ok(Self(winpty)), Result::Err)
|
||||||
let err = check_err(err);
|
|
||||||
if let Some(err) = err {
|
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
Ok(Winpty(&mut *winpty))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the handle to the winpty agent process
|
/// Returns the handle to the winpty agent process
|
||||||
|
@ -200,11 +181,7 @@ impl<'a, 'b> Winpty<'a> {
|
||||||
winpty_set_size(self.0, i32::from(cols), i32::from(rows), &mut err);
|
winpty_set_size(self.0, i32::from(cols), i32::from(rows), &mut err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(err) = check_err(err) {
|
check_err(err).map_or(Ok(()), Result::Err)
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the list of processes running in the winpty agent. Returns <= count processes
|
/// Get the list of processes running in the winpty agent. Returns <= count processes
|
||||||
|
@ -227,11 +204,7 @@ impl<'a, 'b> Winpty<'a> {
|
||||||
process_list.set_len(len);
|
process_list.set_len(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(err) = check_err(err) {
|
check_err(err).map_or(Ok(process_list), Result::Err)
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
Ok(process_list)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawns the new process.
|
/// Spawns the new process.
|
||||||
|
@ -259,19 +232,15 @@ impl<'a, 'b> Winpty<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(err) = check_err(err) {
|
check_err(err).map_or(Ok(()), Result::Err)
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// winpty_t is thread-safe
|
// winpty_t is thread-safe
|
||||||
unsafe impl<'a> Sync for Winpty<'a> {}
|
unsafe impl Sync for Winpty {}
|
||||||
unsafe impl<'a> Send for Winpty<'a> {}
|
unsafe impl Send for Winpty {}
|
||||||
|
|
||||||
impl<'a> Drop for Winpty<'a> {
|
impl Drop for Winpty {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
winpty_free(self.0);
|
winpty_free(self.0);
|
||||||
|
@ -281,9 +250,9 @@ impl<'a> Drop for Winpty<'a> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Information about a process for winpty to spawn
|
/// Information about a process for winpty to spawn
|
||||||
pub struct SpawnConfig<'a>(&'a mut winpty_spawn_config_t);
|
pub struct SpawnConfig(*mut winpty_spawn_config_t);
|
||||||
|
|
||||||
impl<'a, 'b> SpawnConfig<'a> {
|
impl SpawnConfig {
|
||||||
/// Creates a new spawnconfig
|
/// Creates a new spawnconfig
|
||||||
pub fn new(
|
pub fn new(
|
||||||
spawnflags: SpawnFlags,
|
spawnflags: SpawnFlags,
|
||||||
|
@ -291,7 +260,7 @@ impl<'a, 'b> SpawnConfig<'a> {
|
||||||
cmdline: Option<&str>,
|
cmdline: Option<&str>,
|
||||||
cwd: Option<&str>,
|
cwd: Option<&str>,
|
||||||
end: Option<&str>,
|
end: Option<&str>,
|
||||||
) -> Result<Self, Err<'b>> {
|
) -> Result<Self, Err> {
|
||||||
let mut err = null_mut() as *mut winpty_error_t;
|
let mut err = null_mut() as *mut winpty_error_t;
|
||||||
let (appname, cmdline, cwd, end) = (
|
let (appname, cmdline, cwd, end) = (
|
||||||
appname.map_or(null(), |s| WideCString::from_str(s).unwrap().into_raw()),
|
appname.map_or(null(), |s| WideCString::from_str(s).unwrap().into_raw()),
|
||||||
|
@ -320,14 +289,11 @@ impl<'a, 'b> SpawnConfig<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(err) = check_err(err) {
|
check_err(err).map_or(Ok(Self(spawn_config)), Result::Err)
|
||||||
Result::Err(err)
|
|
||||||
} else {
|
|
||||||
unsafe { Ok(SpawnConfig(&mut *spawn_config)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> Drop for SpawnConfig<'a> {
|
|
||||||
|
impl Drop for SpawnConfig {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
winpty_spawn_config_free(self.0);
|
winpty_spawn_config_free(self.0);
|
||||||
|
@ -338,10 +304,8 @@ impl<'a> Drop for SpawnConfig<'a> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use named_pipe::PipeClient;
|
use named_pipe::PipeClient;
|
||||||
use winapi;
|
use winapi::um::processthreadsapi::OpenProcess;
|
||||||
|
use winapi::um::winnt::READ_CONTROL;
|
||||||
use self::winapi::um::processthreadsapi::OpenProcess;
|
|
||||||
use self::winapi::um::winnt::READ_CONTROL;
|
|
||||||
|
|
||||||
use crate::{Config, ConfigFlags, SpawnConfig, SpawnFlags, Winpty};
|
use crate::{Config, ConfigFlags, SpawnConfig, SpawnFlags, Winpty};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue