From 62a01637ef475a5b858469d8ef2d7d477523447a Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Thu, 16 May 2024 20:04:58 -0700 Subject: [PATCH] fix remaining libc issues - use rustix version of sigwinch signal - add a lifetime to FileDesc and replace FileDesc::Static to FileDesc::Borrowed. This made it necessary to either add a lifetime to the libc version of FileDesc or replace all the callers with multiple paths (libc, rustix). Changing FileDesc was more straightforward. There are no usages of FileDesc found in any repo on github, so this change should be reasonably safe. --- src/event/source/unix/mio.rs | 4 +-- src/event/source/unix/tty.rs | 14 +++++++++-- src/terminal/sys/file_descriptor.rs | 38 +++++++++++++++++------------ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/event/source/unix/mio.rs b/src/event/source/unix/mio.rs index 8372a1dd..0368e61b 100644 --- a/src/event/source/unix/mio.rs +++ b/src/event/source/unix/mio.rs @@ -26,7 +26,7 @@ pub(crate) struct UnixInternalEventSource { events: Events, parser: Parser, tty_buffer: [u8; TTY_BUFFER_SIZE], - tty_fd: FileDesc, + tty_fd: FileDesc<'static>, signals: Signals, #[cfg(feature = "event-stream")] waker: Waker, @@ -37,7 +37,7 @@ impl UnixInternalEventSource { UnixInternalEventSource::from_file_descriptor(tty_fd()?) } - pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result { + pub(crate) fn from_file_descriptor(input_fd: FileDesc<'static>) -> io::Result { let poll = Poll::new()?; let registry = poll.registry(); diff --git a/src/event/source/unix/tty.rs b/src/event/source/unix/tty.rs index b8cbfeff..03d76b40 100644 --- a/src/event/source/unix/tty.rs +++ b/src/event/source/unix/tty.rs @@ -1,6 +1,10 @@ +#[cfg(feature = "libc")] use std::os::unix::prelude::AsRawFd; use std::{collections::VecDeque, io, os::unix::net::UnixStream, time::Duration}; +#[cfg(not(feature = "libc"))] +use rustix::fd::{AsFd, AsRawFd}; + use signal_hook::low_level::pipe; use crate::event::timeout::PollTimeout; @@ -38,7 +42,7 @@ const TTY_BUFFER_SIZE: usize = 1_024; pub(crate) struct UnixInternalEventSource { parser: Parser, tty_buffer: [u8; TTY_BUFFER_SIZE], - tty: FileDesc, + tty: FileDesc<'static>, winch_signal_receiver: UnixStream, #[cfg(feature = "event-stream")] wake_pipe: WakePipe, @@ -56,7 +60,7 @@ impl UnixInternalEventSource { UnixInternalEventSource::from_file_descriptor(tty_fd()?) } - pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result { + pub(crate) fn from_file_descriptor(input_fd: FileDesc<'static>) -> io::Result { Ok(UnixInternalEventSource { parser: Parser::default(), tty_buffer: [0u8; TTY_BUFFER_SIZE], @@ -64,7 +68,10 @@ impl UnixInternalEventSource { winch_signal_receiver: { let (receiver, sender) = nonblocking_unix_pair()?; // Unregistering is unnecessary because EventSource is a singleton + #[cfg(feature = "libc")] pipe::register(libc::SIGWINCH, sender)?; + #[cfg(not(feature = "libc"))] + pipe::register(rustix::process::Signal::Winch as i32, sender)?; receiver }, #[cfg(feature = "event-stream")] @@ -157,7 +164,10 @@ impl EventSource for UnixInternalEventSource { } } if fds[1].revents & POLLIN != 0 { + #[cfg(feature = "libc")] let fd = FileDesc::new(self.winch_signal_receiver.as_raw_fd(), false); + #[cfg(not(feature = "libc"))] + let fd = FileDesc::Borrowed(self.winch_signal_receiver.as_fd()); // drain the pipe while read_complete(&fd, &mut [0; 1024])? != 0 {} // TODO Should we remove tput? diff --git a/src/terminal/sys/file_descriptor.rs b/src/terminal/sys/file_descriptor.rs index 3212c484..baff266c 100644 --- a/src/terminal/sys/file_descriptor.rs +++ b/src/terminal/sys/file_descriptor.rs @@ -7,6 +7,7 @@ use rustix::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}; #[cfg(feature = "libc")] use std::{ fs, + marker::PhantomData, os::unix::{ io::{IntoRawFd, RawFd}, prelude::AsRawFd, @@ -19,27 +20,32 @@ use std::{ /// mainly it closes the file descriptor once dropped. #[derive(Debug)] #[cfg(feature = "libc")] -pub struct FileDesc { +pub struct FileDesc<'a> { fd: RawFd, close_on_drop: bool, + phantom: PhantomData<&'a ()>, } #[cfg(not(feature = "libc"))] -pub enum FileDesc { +pub enum FileDesc<'a> { Owned(OwnedFd), - Static(BorrowedFd<'static>), + Borrowed(BorrowedFd<'a>), } #[cfg(feature = "libc")] -impl FileDesc { +impl FileDesc<'_> { /// Constructs a new `FileDesc` with the given `RawFd`. /// /// # Arguments /// /// * `fd` - raw file descriptor /// * `close_on_drop` - specify if the raw file descriptor should be closed once the `FileDesc` is dropped - pub fn new(fd: RawFd, close_on_drop: bool) -> FileDesc { - FileDesc { fd, close_on_drop } + pub fn new(fd: RawFd, close_on_drop: bool) -> FileDesc<'static> { + FileDesc { + fd, + close_on_drop, + phantom: PhantomData, + } } pub fn read(&self, buffer: &mut [u8]) -> io::Result { @@ -65,11 +71,11 @@ impl FileDesc { } #[cfg(not(feature = "libc"))] -impl FileDesc { +impl FileDesc<'_> { pub fn read(&self, buffer: &mut [u8]) -> io::Result { let fd = match self { FileDesc::Owned(fd) => fd.as_fd(), - FileDesc::Static(fd) => fd.as_fd(), + FileDesc::Borrowed(fd) => fd.as_fd(), }; let result = rustix::io::read(fd, buffer)?; Ok(result) @@ -78,13 +84,13 @@ impl FileDesc { pub fn raw_fd(&self) -> RawFd { match self { FileDesc::Owned(fd) => fd.as_raw_fd(), - FileDesc::Static(fd) => fd.as_raw_fd(), + FileDesc::Borrowed(fd) => fd.as_raw_fd(), } } } #[cfg(feature = "libc")] -impl Drop for FileDesc { +impl Drop for FileDesc<'_> { fn drop(&mut self) { if self.close_on_drop { // Note that errors are ignored when closing a file descriptor. The @@ -97,25 +103,25 @@ impl Drop for FileDesc { } } -impl AsRawFd for FileDesc { +impl AsRawFd for FileDesc<'_> { fn as_raw_fd(&self) -> RawFd { self.raw_fd() } } #[cfg(not(feature = "libc"))] -impl AsFd for FileDesc { +impl AsFd for FileDesc<'_> { fn as_fd(&self) -> BorrowedFd<'_> { match self { FileDesc::Owned(fd) => fd.as_fd(), - FileDesc::Static(fd) => fd.as_fd(), + FileDesc::Borrowed(fd) => fd.as_fd(), } } } #[cfg(feature = "libc")] /// Creates a file descriptor pointing to the standard input or `/dev/tty`. -pub fn tty_fd() -> io::Result { +pub fn tty_fd() -> io::Result> { let (fd, close_on_drop) = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } { (libc::STDIN_FILENO, false) } else { @@ -134,12 +140,12 @@ pub fn tty_fd() -> io::Result { #[cfg(not(feature = "libc"))] /// Creates a file descriptor pointing to the standard input or `/dev/tty`. -pub fn tty_fd() -> io::Result { +pub fn tty_fd() -> io::Result> { use std::fs::File; let stdin = rustix::stdio::stdin(); let fd = if rustix::termios::isatty(stdin) { - FileDesc::Static(stdin) + FileDesc::Borrowed(stdin) } else { let dev_tty = File::options().read(true).write(true).open("/dev/tty")?; FileDesc::Owned(dev_tty.into())