Replace select with a 64-bit-time_t wrapper

Part of #10634
This commit is contained in:
Johannes Altmanninger 2024-08-07 10:14:31 +02:00
parent 3a9b4149da
commit 46c8ba2c9f
4 changed files with 76 additions and 20 deletions

View file

@ -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
}

View file

@ -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);
}
}
}

View file

@ -1,3 +1,4 @@
#include <assert.h>
#include <dirent.h>
#include <fcntl.h>
#include <locale.h>
@ -7,6 +8,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@ -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;
}

View file

@ -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<c_char> = AtomicPtr::new(std::ptr::null_mut());
@ -123,3 +123,29 @@ pub(crate) fn localtime64_r(timep: i64) -> Option<libc::tm> {
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;
}