termios: use fcntl(F_GETPATH) for ttyname on Apple platforms#1605
Open
gdw2vs wants to merge 2 commits intobytecodealliance:mainfrom
Open
termios: use fcntl(F_GETPATH) for ttyname on Apple platforms#1605gdw2vs wants to merge 2 commits intobytecodealliance:mainfrom
gdw2vs wants to merge 2 commits intobytecodealliance:mainfrom
Conversation
macOS's ttyname_r works by walking /dev and calling stat on each entry to find one whose device and inode numbers match the given fd. This directory scan can take several seconds on a typical macOS system, causing significant latency for any Rust program that calls ttyname. On Apple platforms, use fcntl(F_GETPATH) instead. This is a Darwin-specific API that asks the kernel to fill a buffer with the filesystem path for any open file descriptor in a single kernel call, making it dramatically faster than the /dev scan. The linux_raw backend already uses an analogous approach for the same reason, reading the path from /proc/self/fd/<fd> instead of calling ttyname_r. This change brings the libc backend on Apple targets to parity with that design. The existing fs::getpath function in the libc backend already uses fcntl(F_GETPATH) for the same purpose on Apple targets, so this is consistent with established patterns in the codebase.
libc 0.2.183+ requires rustc 1.65, which breaks the ubuntu-1.63 test jobs. Pin libc to 0.2.182 in the 1.63 compatibility cargo update blocks, matching the pattern already used for other dependencies.
Contributor
|
CI / Check (1.63) (pull_request) failure tracked by #1607 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On macOS,
rustix::termios::ttynamecallslibc::ttyname_r, which works by walking/devand callingstaton each entry, comparing device and inode numbers until it finds a match. This directory scan can take several seconds on a typical macOS system, causing significant latency for any Rust program that callsttyname.This is a known macOS libc behavior. The slowness has been observed and reported in downstream crates (e.g. doy/rbw#11) that were forced to work around it by calling
fcntl(F_GETPATH)directly rather than going throughrustix::termios::ttyname.Solution
On Apple platforms, use
fcntl(F_GETPATH)instead ofttyname_r. This is a Darwin-specific API that asks the kernel to fill a buffer with the filesystem path for any open file descriptor in a single kernel call, making it dramatically faster than the/devscan.The change is in
src/backend/libc/termios/syscalls.rs, splitting thettynamefunction into two#[cfg]-guarded branches:#[cfg(apple)]: usesfcntl(F_GETPATH), with an explicitisattycheck beforehand to preserve POSIXENOTTYsemantics for non-terminal fds#[cfg(not(apple))]: the existingttyname_rpath, unchangedPrecedent in this codebase
This follows the same reasoning as the
linux_rawbackend, which already avoidsttyname_rentirely by reading the path from/proc/self/fd/<fd>. Thefcntl(F_GETPATH)approach on Apple is the direct analogue.Additionally,
fcntl(F_GETPATH)is already used within rustix itself insrc/backend/libc/fs/syscalls.rs(fs::getpath), so this is consistent with established patterns in the codebase.Testing
All existing
ttynametests pass:ttyname::test_ttyname_ok— verifies a tty fd returns a valid/dev/...pathttyname::test_ttyname_not_tty— verifies non-tty fds returnENOTTY