Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
allocator_api,
breakpoint,
cold_path,
inherent_str_constructors,
let_chains,
linked_list_cursors,
maybe_uninit_fill,
Expand Down
40 changes: 28 additions & 12 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

use std::ffi::{CStr, c_int, c_void};
use std::fs::{self, File};
use std::mem::{self, MaybeUninit};
use std::mem::{self, ManuallyDrop, MaybeUninit};
use std::os::fd::{AsRawFd as _, FromRawFd as _};
use std::ptr::{self, NonNull, null, null_mut};
use std::ptr::{self, NonNull, null_mut};
use std::{thread, time};

use crate::arena::{Arena, ArenaString, scratch_arena};
Expand Down Expand Up @@ -195,11 +195,19 @@ pub fn read_stdin(arena: &Arena, mut timeout: time::Duration) -> Option<ArenaStr
let beg = time::Instant::now();

let mut pollfd = libc::pollfd { fd: STATE.stdin, events: libc::POLLIN, revents: 0 };
let ts = libc::timespec {
tv_sec: timeout.as_secs() as libc::time_t,
tv_nsec: timeout.subsec_nanos() as libc::c_long,
};
let ret = libc::ppoll(&mut pollfd, 1, &ts, null());
let ret;
#[cfg(target_os = "linux")]
{
let ts = libc::timespec {
tv_sec: timeout.as_secs() as libc::time_t,
tv_nsec: timeout.subsec_nanos() as libc::c_long,
};
ret = libc::ppoll(&mut pollfd, 1, &ts, ptr::null());
}
#[cfg(not(target_os = "linux"))]
{
ret = libc::poll(&mut pollfd, 1, timeout.as_millis() as libc::c_int);
}
if ret < 0 {
return None; // Error? Let's assume it's an EOF.
}
Expand All @@ -225,7 +233,7 @@ pub fn read_stdin(arena: &Arena, mut timeout: time::Duration) -> Option<ArenaStr
return None; // EOF
}
if ret < 0 {
match *libc::__errno_location() {
match errno() {
libc::EINTR if STATE.inject_resize => break,
libc::EAGAIN if timeout == time::Duration::ZERO => break,
libc::EINTR | libc::EAGAIN => {}
Expand Down Expand Up @@ -304,7 +312,7 @@ pub fn write_stdout(text: &str) {
continue;
}

let err = unsafe { *libc::__errno_location() };
let err = errno();
if err != libc::EINTR {
return;
}
Expand Down Expand Up @@ -407,7 +415,7 @@ pub unsafe fn virtual_commit(base: NonNull<u8>, size: usize) -> apperr::Result<(
unsafe fn load_library(name: &CStr) -> apperr::Result<NonNull<c_void>> {
unsafe {
NonNull::new(libc::dlopen(name.as_ptr(), libc::RTLD_LAZY))
.ok_or_else(|| errno_to_apperr(libc::ELIBACC))
.ok_or_else(|| errno_to_apperr(libc::ENOENT))
}
}

Expand All @@ -423,7 +431,7 @@ pub unsafe fn get_proc_address<T>(handle: NonNull<c_void>, name: &CStr) -> apper
unsafe {
let sym = libc::dlsym(handle.as_ptr(), name.as_ptr());
if sym.is_null() {
Err(errno_to_apperr(libc::ELIBACC))
Err(errno_to_apperr(libc::ENOENT))
} else {
Ok(mem::transmute_copy(&sym))
}
Expand Down Expand Up @@ -537,6 +545,14 @@ pub fn preferred_languages(arena: &Arena) -> Vec<ArenaString<'_>, &Arena> {
locales
}

#[inline]
fn errno() -> i32 {
// Under `-O -Copt-level=s` the 1.87 compiler fails to fully inline and
// remove the raw_os_error() call. This leaves us with the drop() call.
// ManuallyDrop fixes that and results in a direct `std::sys::os::errno` call.
ManuallyDrop::new(std::io::Error::last_os_error()).raw_os_error().unwrap_or(0)
}

#[inline]
pub(crate) fn io_error_to_apperr(err: std::io::Error) -> apperr::Error {
errno_to_apperr(err.raw_os_error().unwrap_or(0))
Expand Down Expand Up @@ -565,5 +581,5 @@ const fn errno_to_apperr(no: c_int) -> apperr::Error {
}

fn check_int_return(ret: libc::c_int) -> apperr::Result<libc::c_int> {
if ret < 0 { Err(errno_to_apperr(unsafe { *libc::__errno_location() })) } else { Ok(ret) }
if ret < 0 { Err(errno_to_apperr(errno())) } else { Ok(ret) }
}