Skip to main content

ConPtyBackend

Struct ConPtyBackend 

Source
pub struct ConPtyBackend { /* private fields */ }
Expand description

A loaded ConPTY implementation.

Cloning is cheap: clones share one Arc, so resolving the entry points happens once per backend rather than once per pseudoconsole.

§Thread safety

ConPtyBackend is Send + Sync, and that is sound:

  • BackendInner holds a private backend-kind value — a unit variant or a PathBuf — a table of bare extern "system" function pointers, and a module guard. Function pointers are Send + Sync: they are immutable code addresses, not resources. The guard states its own argument.
  • The backend owns no HPCON, no OS handle, and no interior mutability, so a shared &ConPtyBackend exposes nothing mutable.
  • The module the addresses point into stays loaded for the lifetime of the backend: the system backend targets kernel32.dll, which is mapped into every Win32 process and never unloaded, and an external backend owns a LoadLibraryExW reference that is released only when the last clone is dropped.
  • Send is not merely convenient but required. ClosePseudoConsole must not be called from the thread reading the conout pipe, so the shutdown path necessarily runs on a different thread from the reader and both need the backend.

Implementations§

Source§

impl ConPtyBackend

Source

pub fn system() -> Result<Self, BackendError>

Loads the ConPTY API built into the operating system.

Resolves the entry points from the already-mapped kernel32.dll; no library is loaded and no reference count is taken, because kernel32.dll is present in every Win32 process for its entire lifetime.

§Errors

Returns crate::BackendErrorKind::Unsupported when CreatePseudoConsole, ResizePseudoConsole, or ClosePseudoConsole is missing, i.e. on Windows versions older than 10 1809 (build 17763).

Source

pub fn from_dir(dir: impl AsRef<Path>) -> Result<Self, BackendError>

Loads a bundled conpty.dll from dir, validating the bundle first.

A bundle is conpty.dll plus the OpenConsole.exe it launches, as shipped by the Microsoft.Windows.Console.ConPTY NuGet package. Both must come from the same package: the DLL and the console host share a private protocol with no compatibility promise across releases, and a bad ConPTY bundle crashes the client process rather than degrading — wezterm#7774 is PowerShell dying with a 0x8013_1623 FailFast until the bundle was replaced. This constructor therefore refuses a pair it cannot prove consistent; public callers cannot bypass this validation.

Note the check’s limit: it proves the pair matches, not that it is current. wezterm#7774’s actual configuration was a matched but outdated pair, which this validation accepts; keeping the bundled version up to date remains the application’s responsibility.

The console host is looked for exactly where conpty.dll itself will look: next to the DLL first, then in the single subdirectory named after the machine’s native architecture (x64, arm64, or x86). A host anywhere else — a cross-architecture subdirectory, say — does not count, because the DLL never searches there and would silently run every session against the operating system’s inbox conhost.exe instead of the file this constructor validated. Placing OpenConsole.exe next to the DLL, as the repository’s just fetch-conpty tooling does, is the recommended layout.

A relative dir is resolved against the current working directory once, here. The DLL is then loaded by absolute path with a search policy that excludes PATH, the current directory, the application directory, and the registry, so nothing but dir and System32 can satisfy the load. A drive-relative dir (C:dir) is rejected as crate::BackendErrorKind::DllNotFound: it names a path relative to that drive’s own current directory, which cannot be resolved once and pinned.

§Examples
use conpty_oxide::ConPtyBackend;

let backend = ConPtyBackend::from_dir("vendor/conpty")?;
println!("validated bundle: {backend:?}");
§Errors
Source

pub fn auto() -> Result<Self, BackendError>

Returns the best backend available to this process.

The search order is:

  1. A bundle next to the current executable. If conpty.dll sits in the executable’s directory it is loaded with Self::from_dir, with all of its validation.
  2. The operating system’s ConPTY (Self::system).

A bundle that fails to load is not an error: the process still has the system implementation, and falling back to it is what an application that merely may ship a bundle wants. The rejection is recorded with tracing::warn! when the tracing feature is enabled, so a bundle that is silently ignored — a version-mismatched pair, say — is still diagnosable.

§Errors

Returns crate::BackendErrorKind::Unsupported when neither a valid bundle nor the system ConPTY implementation is available.

Source

pub fn supports_clear(&self) -> bool

Returns whether this backend can clear the pseudoconsole’s buffer.

ClearPseudoConsole is not part of the public Windows SDK and kernel32.dll does not export it, so this is false on the system backend and true only for a bundled conpty.dll that exports ConptyClearPseudoConsole.

It is also false on 32-bit x86 regardless of the DLL: the export changed arity between releases (microsoft/terminal#18976) and __stdcall makes an arity mismatch corrupt the stack, so the call is not offered where it cannot be made safely.

Trait Implementations§

Source§

impl Clone for ConPtyBackend

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ConPtyBackend

Prints the backend’s identity rather than raw function addresses, which are noise and vary between runs.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more