diff options
Diffstat (limited to 'ctr-std/src/sys/unix/mod.rs')
| -rw-r--r-- | ctr-std/src/sys/unix/mod.rs | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/ctr-std/src/sys/unix/mod.rs b/ctr-std/src/sys/unix/mod.rs index 13639eb..27c428d 100644 --- a/ctr-std/src/sys/unix/mod.rs +++ b/ctr-std/src/sys/unix/mod.rs @@ -10,6 +10,9 @@ #![allow(missing_docs, bad_style)] +use io::{self, ErrorKind}; +use libc; + pub mod ext; pub mod fast_thread_local; pub mod memchr; @@ -17,9 +20,45 @@ pub mod os; pub mod os_str; pub mod path; pub mod thread_local; +pub mod time; -use io::ErrorKind; -use libc; +#[cfg(not(test))] +pub fn init() { + use alloc::oom; + + // By default, some platforms will send a *signal* when an EPIPE error + // would otherwise be delivered. This runtime doesn't install a SIGPIPE + // handler, causing it to kill the program, which isn't exactly what we + // want! + // + // Hence, we set SIGPIPE to ignore when the program starts up in order + // to prevent this problem. + unsafe { + reset_sigpipe(); + } + + oom::set_oom_handler(oom_handler); + + // A nicer handler for out-of-memory situations than the default one. This + // one prints a message to stderr before aborting. It is critical that this + // code does not allocate any memory since we are in an OOM situation. Any + // errors are ignored while printing since there's nothing we can do about + // them and we are about to exit anyways. + fn oom_handler() -> ! { + use intrinsics; + let msg = "fatal runtime error: out of memory\n"; + unsafe { + libc::write(libc::STDERR_FILENO, + msg.as_ptr() as *const libc::c_void, + msg.len()); + intrinsics::abort(); + } + } + + // I don't think we have signal handling on the 3DS, so let's leave this + // blank for now + unsafe fn reset_sigpipe() {} +} pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as libc::c_int { @@ -47,6 +86,41 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} + +pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> + where T: IsMinusOne, + F: FnMut() -> T +{ + loop { + match cvt(f()) { + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + other => return other, + } + } +} + pub unsafe fn abort_internal() -> ! { ::libc::abort() } |