From 46c8ba2c9fec77195091ddcf7ee0bb3d9a6e5f54 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Wed, 7 Aug 2024 10:14:31 +0200 Subject: [PATCH] Replace select with a 64-bit-time_t wrapper Part of #10634 --- src/fd_monitor.rs | 27 +++++++++++++-------------- src/fd_readable_set.rs | 11 ++++++----- src/libc.c | 30 ++++++++++++++++++++++++++++++ src/libc.rs | 28 +++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 20 deletions(-) diff --git a/src/fd_monitor.rs b/src/fd_monitor.rs index d7f86e5c0..067c7d755 100644 --- a/src/fd_monitor.rs +++ b/src/fd_monitor.rs @@ -7,6 +7,7 @@ use crate::common::exit_without_destructors; use crate::fd_readable_set::FdReadableSet; use crate::fds::AutoCloseFd; use crate::flog::FLOG; +use crate::libc::{select64, timeval64}; use crate::threads::assert_is_background_thread; use crate::wutil::perror; use errno::errno; @@ -142,26 +143,24 @@ impl FdEventSignaller { /// but guarantees that the next call to wait() will not block. /// Return true if readable, false if not readable, or not interrupted by a signal. pub fn poll(&self, wait: bool /* = false */) -> bool { - let mut timeout = libc::timeval { + let mut timeout = timeval64 { tv_sec: 0, tv_usec: 0, }; let mut fds: libc::fd_set = unsafe { std::mem::zeroed() }; unsafe { libc::FD_ZERO(&mut fds) }; unsafe { libc::FD_SET(self.read_fd(), &mut fds) }; - let res = unsafe { - libc::select( - self.read_fd() + 1, - &mut fds, - std::ptr::null_mut(), - std::ptr::null_mut(), - if wait { - std::ptr::null_mut() - } else { - &mut timeout - }, - ) - }; + let res = select64( + self.read_fd() + 1, + &mut fds, + std::ptr::null_mut(), + std::ptr::null_mut(), + if wait { + std::ptr::null_mut() + } else { + &mut timeout + }, + ); res > 0 } diff --git a/src/fd_readable_set.rs b/src/fd_readable_set.rs index 00f1a2308..c76c9d28f 100644 --- a/src/fd_readable_set.rs +++ b/src/fd_readable_set.rs @@ -68,9 +68,10 @@ impl FdReadableSet { /// destructively modifies the set. Returns the result of `select()` or `poll()`. pub fn check_readable(&mut self, timeout_usec: u64) -> c_int { let null = std::ptr::null_mut(); + use crate::libc::{select64, timeval64}; if timeout_usec == Self::kNoTimeout { unsafe { - return libc::select( + return select64( self.nfds_, &mut self.fdset_, null, @@ -79,12 +80,12 @@ impl FdReadableSet { ); } } else { - let mut tvs = libc::timeval { - tv_sec: (timeout_usec / kUsecPerSec) as libc::time_t, - tv_usec: (timeout_usec % kUsecPerSec) as libc::suseconds_t, + let mut tvs = timeval64 { + tv_sec: (timeout_usec / kUsecPerSec).try_into().unwrap(), + tv_usec: (timeout_usec % kUsecPerSec).try_into().unwrap(), }; unsafe { - return libc::select(self.nfds_, &mut self.fdset_, null, null, &mut tvs); + return select64(self.nfds_, &mut self.fdset_, null, null, &mut tvs); } } } diff --git a/src/libc.c b/src/libc.c index ba584c70e..b0188d622 100644 --- a/src/libc.c +++ b/src/libc.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +16,12 @@ #define UNUSED(x) (void)(x) +#define assert_or_die(x) \ + do { \ + assert((x)); \ + if (!(x)) abort(); \ + } while (false) + size_t C_MB_CUR_MAX() { return MB_CUR_MAX; } uint64_t C_ST_LOCAL() { @@ -219,3 +227,25 @@ bool C_localtime64_r(int64_t timep, struct tm* result) { time_t timep_ = timep; return localtime_r(&timep_, result); } + +struct timeval64 { + int64_t tv_sec; + int64_t tv_usec; +}; + +int C_select64(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, + struct timeval64* timeout64) { + struct timeval timeout; + if (timeout64) { + timeout.tv_sec = timeout64->tv_sec; + timeout.tv_usec = timeout64->tv_usec; + assert_or_die(timeout.tv_sec == timeout64->tv_sec); + assert_or_die(timeout.tv_usec == timeout64->tv_usec); + } + int result = select(nfds, readfds, writefds, errorfds, timeout64 ? &timeout : NULL); + if (timeout64) { + timeout64->tv_sec = timeout.tv_sec; + timeout64->tv_usec = timeout.tv_usec; + } + return result; +} diff --git a/src/libc.rs b/src/libc.rs index e960e4856..b8a33196d 100644 --- a/src/libc.rs +++ b/src/libc.rs @@ -1,6 +1,6 @@ use std::{ffi::CStr, sync::atomic::AtomicPtr}; -use libc::{c_char, c_int}; +use libc::{c_char, c_int, fd_set}; use once_cell::sync::Lazy; pub static _PATH_BSHELL: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); @@ -123,3 +123,29 @@ pub(crate) fn localtime64_r(timep: i64) -> Option { extern "C" { fn C_localtime64_r(timep: i64, result: *mut libc::tm) -> bool; } + +#[repr(C)] +#[derive(Clone, Copy)] +pub(crate) struct timeval64 { + pub tv_sec: i64, + pub tv_usec: i64, +} + +pub(crate) fn select64( + nfds: c_int, + readfds: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut timeval64, +) -> c_int { + unsafe { C_select64(nfds, readfds, writefds, errorfds, timeout) } +} +extern "C" { + fn C_select64( + nfds: c_int, + readfds: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut timeval64, + ) -> c_int; +}