aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/unix/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ctr-std/src/sys/unix/mod.rs')
-rw-r--r--ctr-std/src/sys/unix/mod.rs78
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()
}