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:
BackendInnerholds a private backend-kind value — a unit variant or aPathBuf— a table of bareextern "system"function pointers, and a module guard. Function pointers areSend + 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&ConPtyBackendexposes 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 aLoadLibraryExWreference that is released only when the last clone is dropped. Sendis not merely convenient but required.ClosePseudoConsolemust 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
impl ConPtyBackend
Sourcepub fn system() -> Result<Self, BackendError>
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).
Sourcepub fn from_dir(dir: impl AsRef<Path>) -> Result<Self, BackendError>
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
crate::BackendErrorKind::DllNotFoundifdir/conpty.dllis missing or cannot be loaded (the source carries the OS error, e.g.ERROR_BAD_EXE_FORMATfor a file that is not a DLL at all).crate::BackendErrorKind::OpenConsoleMissingif noOpenConsole.exeaccompanies the DLL.crate::BackendErrorKind::VersionMismatchif the two files report differentProductVersionresources, or if either version cannot be read.crate::BackendErrorKind::MissingExportif the DLL lacksCreatePseudoConsole,ResizePseudoConsole, orClosePseudoConsole.
Sourcepub fn auto() -> Result<Self, BackendError>
pub fn auto() -> Result<Self, BackendError>
Returns the best backend available to this process.
The search order is:
- A bundle next to the current executable. If
conpty.dllsits in the executable’s directory it is loaded withSelf::from_dir, with all of its validation. - 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.
Sourcepub fn supports_clear(&self) -> bool
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.