diff --git a/src/header/sys_ioctl/redox.rs b/src/header/sys_ioctl/redox.rs
index e475e681d266a795c868caba059b9ae8cfe6b1e9..b1b93382d8f4b9c85764af3b00857c1efd423f28 100644
--- a/src/header/sys_ioctl/redox.rs
+++ b/src/header/sys_ioctl/redox.rs
@@ -1,9 +1,14 @@
 use core::{mem, slice};
+use redox_rt::proc::FdGuard;
 use syscall;
 
 use crate::{
-    header::{errno, fcntl, termios},
-    platform::{self, e, types::*},
+    error::{Errno, Result, ResultExt},
+    header::{
+        errno::{self, EINVAL},
+        fcntl, termios,
+    },
+    platform::{self, types::*, Pal, Sys},
 };
 
 use super::winsize;
@@ -49,123 +54,85 @@ fn dup_read<T>(fd: c_int, name: &str, t: &mut T) -> syscall::Result<usize> {
     res.map(|bytes| bytes / size)
 }
 
-fn dup_write<T>(fd: c_int, name: &str, t: &T) -> syscall::Result<usize> {
-    let dup = syscall::dup(fd as usize, name.as_bytes())?;
+// FIXME: unsound
+fn dup_write<T>(fd: c_int, name: &str, t: &T) -> Result<usize> {
+    let dup = FdGuard::new(syscall::dup(fd as usize, name.as_bytes())?);
 
     let size = mem::size_of::<T>();
 
-    let res = syscall::write(dup, unsafe {
+    let bytes_written = syscall::write(*dup, unsafe {
         slice::from_raw_parts(t as *const T as *const u8, size)
-    });
+    })?;
 
-    let _ = syscall::close(dup);
-
-    res.map(|bytes| bytes / size)
+    Ok(bytes_written / size)
 }
 
-#[no_mangle]
-pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
+unsafe fn ioctl_inner(fd: c_int, request: c_ulong, out: *mut c_void) -> Result<c_int> {
     match request {
         FIONBIO => {
-            let mut flags = fcntl::fcntl(fd, fcntl::F_GETFL, 0);
-            if flags < 0 {
-                return -1;
-            }
+            let mut flags = Sys::fcntl(fd, fcntl::F_GETFL, 0)?;
             flags = if *(out as *mut c_int) == 0 {
                 flags & !fcntl::O_NONBLOCK
             } else {
                 flags | fcntl::O_NONBLOCK
             };
-            if fcntl::fcntl(fd, fcntl::F_SETFL, flags as c_ulonglong) < 0 {
-                -1
-            } else {
-                0
-            }
+            Sys::fcntl(fd, fcntl::F_SETFL, flags as c_ulonglong)?;
         }
         TCGETS => {
             let termios = &mut *(out as *mut termios::termios);
-            if e(dup_read(fd, "termios", termios)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_read(fd, "termios", termios)?;
         }
         // TODO: give these different behaviors
         TCSETS | TCSETSW | TCSETSF => {
             let termios = &*(out as *const termios::termios);
-            if e(dup_write(fd, "termios", termios)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_write(fd, "termios", termios)?;
         }
         TCFLSH => {
             let queue = out as c_int;
-            if e(dup_write(fd, "flush", &queue)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_write(fd, "flush", &queue)?;
         }
         TIOCSCTTY => {
             eprintln!("TODO: ioctl TIOCSCTTY");
-            0
         }
         TIOCGPGRP => {
             let pgrp = &mut *(out as *mut pid_t);
-            if e(dup_read(fd, "pgrp", pgrp)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_read(fd, "pgrp", pgrp)?;
         }
         TIOCSPGRP => {
             let pgrp = &*(out as *const pid_t);
-            if e(dup_write(fd, "pgrp", pgrp)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_write(fd, "pgrp", pgrp)?;
         }
         TIOCGWINSZ => {
             let winsize = &mut *(out as *mut winsize);
-            if e(dup_read(fd, "winsize", winsize)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_read(fd, "winsize", winsize)?;
         }
         TIOCSWINSZ => {
             let winsize = &*(out as *const winsize);
-            if e(dup_write(fd, "winsize", winsize)) == !0 {
-                -1
-            } else {
-                0
-            }
+            dup_write(fd, "winsize", winsize)?;
         }
         TIOCGPTLCK => {
             eprintln!("TODO: ioctl TIOCGPTLCK");
-            0
         }
         TIOCSPTLCK => {
             eprintln!("TODO: ioctl TIOCSPTLCK");
-            0
         }
         TCSBRK => {
             eprintln!("TODO: ioctl TCSBRK");
-            0
         }
         TCXONC => {
             eprintln!("TODO: ioctl TCXONC");
-            0
         }
         SIOCATMARK => {
             eprintln!("TODO: ioctl SIOCATMARK");
-            0
         }
         _ => {
-            platform::ERRNO.set(errno::EINVAL);
-            -1
+            return Err(Errno(EINVAL));
         }
     }
+    Ok(0)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
+    ioctl_inner(fd, request, out).or_minus_one_errno()
 }
diff --git a/src/header/sys_ptrace/mod.rs b/src/header/sys_ptrace/mod.rs
index 5982815198c1ed8fe06e429c6d2a866b25b2c79d..cc0958c2c50aca4a3ae56a717f4fcec8cdeb03cd 100644
--- a/src/header/sys_ptrace/mod.rs
+++ b/src/header/sys_ptrace/mod.rs
@@ -1,6 +1,9 @@
 //! ptrace compatibility layer for Redox OS
 
-use crate::platform::{types::*, PalPtrace, Sys};
+use crate::{
+    error::ResultExt,
+    platform::{types::*, PalPtrace, Sys},
+};
 use core::ffi::VaList;
 
 pub const PTRACE_TRACEME: c_int = 0;
@@ -25,5 +28,5 @@ pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32;
 #[no_mangle]
 pub unsafe extern "C" fn ptrace(request: c_int, mut __valist: ...) -> c_int {
     // Musl also just grabs the arguments from the varargs...
-    Sys::ptrace(request, __valist.arg(), __valist.arg(), __valist.arg())
+    Sys::ptrace(request, __valist.arg(), __valist.arg(), __valist.arg()).or_minus_one_errno()
 }
diff --git a/src/header/sys_socket/mod.rs b/src/header/sys_socket/mod.rs
index cdaeb606280aa2a827c14f00799cc43dcadc5bcb..576a8fb33d12141c30c5911640700e877e87e299 100644
--- a/src/header/sys_socket/mod.rs
+++ b/src/header/sys_socket/mod.rs
@@ -3,6 +3,7 @@
 use core::ptr;
 
 use crate::{
+    error::ResultExt,
     header::sys_uio::iovec,
     platform::{types::*, PalSocket, Sys},
 };
@@ -47,7 +48,7 @@ pub unsafe extern "C" fn accept(
     address_len: *mut socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::accept(socket, address, address_len),
+        Sys::accept(socket, address, address_len).or_minus_one_errno(),
         "accept({}, {:p}, {:p})",
         socket,
         address,
@@ -62,7 +63,9 @@ pub unsafe extern "C" fn bind(
     address_len: socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::bind(socket, address, address_len),
+        Sys::bind(socket, address, address_len)
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "bind({}, {:p}, {})",
         socket,
         address,
@@ -77,7 +80,7 @@ pub unsafe extern "C" fn connect(
     address_len: socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::connect(socket, address, address_len),
+        Sys::connect(socket, address, address_len).or_minus_one_errno(),
         "connect({}, {:p}, {})",
         socket,
         address,
@@ -92,7 +95,9 @@ pub unsafe extern "C" fn getpeername(
     address_len: *mut socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::getpeername(socket, address, address_len),
+        Sys::getpeername(socket, address, address_len)
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "getpeername({}, {:p}, {:p})",
         socket,
         address,
@@ -107,7 +112,9 @@ pub unsafe extern "C" fn getsockname(
     address_len: *mut socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::getsockname(socket, address, address_len),
+        Sys::getsockname(socket, address, address_len)
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "getsockname({}, {:p}, {:p})",
         socket,
         address,
@@ -124,7 +131,9 @@ pub unsafe extern "C" fn getsockopt(
     option_len: *mut socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::getsockopt(socket, level, option_name, option_value, option_len),
+        Sys::getsockopt(socket, level, option_name, option_value, option_len)
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "getsockopt({}, {}, {}, {:p}, {:p})",
         socket,
         level,
@@ -137,6 +146,8 @@ pub unsafe extern "C" fn getsockopt(
 #[no_mangle]
 pub unsafe extern "C" fn listen(socket: c_int, backlog: c_int) -> c_int {
     Sys::listen(socket, backlog)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -166,7 +177,9 @@ pub unsafe extern "C" fn recvfrom(
     address_len: *mut socklen_t,
 ) -> ssize_t {
     trace_expr!(
-        Sys::recvfrom(socket, buffer, length, flags, address, address_len),
+        Sys::recvfrom(socket, buffer, length, flags, address, address_len)
+            .map(|r| r as ssize_t)
+            .or_minus_one_errno(),
         "recvfrom({}, {:p}, {}, {:#x}, {:p}, {:p})",
         socket,
         buffer,
@@ -180,6 +193,8 @@ pub unsafe extern "C" fn recvfrom(
 #[no_mangle]
 pub unsafe extern "C" fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t {
     Sys::recvmsg(socket, msg, flags)
+        .map(|r| r as ssize_t)
+        .or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -195,6 +210,8 @@ pub unsafe extern "C" fn send(
 #[no_mangle]
 pub unsafe extern "C" fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t {
     Sys::sendmsg(socket, msg, flags)
+        .map(|w| w as ssize_t)
+        .or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -207,7 +224,9 @@ pub unsafe extern "C" fn sendto(
     dest_len: socklen_t,
 ) -> ssize_t {
     trace_expr!(
-        Sys::sendto(socket, message, length, flags, dest_addr, dest_len),
+        Sys::sendto(socket, message, length, flags, dest_addr, dest_len)
+            .map(|w| w as ssize_t)
+            .or_minus_one_errno(),
         "sendto({}, {:p}, {}, {:#x}, {:p}, {})",
         socket,
         message,
@@ -227,7 +246,9 @@ pub unsafe extern "C" fn setsockopt(
     option_len: socklen_t,
 ) -> c_int {
     trace_expr!(
-        Sys::setsockopt(socket, level, option_name, option_value, option_len),
+        Sys::setsockopt(socket, level, option_name, option_value, option_len)
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "setsockopt({}, {}, {}, {:p}, {})",
         socket,
         level,
@@ -239,13 +260,13 @@ pub unsafe extern "C" fn setsockopt(
 
 #[no_mangle]
 pub unsafe extern "C" fn shutdown(socket: c_int, how: c_int) -> c_int {
-    Sys::shutdown(socket, how)
+    Sys::shutdown(socket, how).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
     trace_expr!(
-        Sys::socket(domain, kind, protocol),
+        Sys::socket(domain, kind, protocol).or_minus_one_errno(),
         "socket({}, {}, {})",
         domain,
         kind,
@@ -261,7 +282,9 @@ pub unsafe extern "C" fn socketpair(
     sv: *mut c_int,
 ) -> c_int {
     trace_expr!(
-        Sys::socketpair(domain, kind, protocol, &mut *(sv as *mut [c_int; 2])),
+        Sys::socketpair(domain, kind, protocol, &mut *(sv as *mut [c_int; 2]))
+            .map(|()| 0)
+            .or_minus_one_errno(),
         "socketpair({}, {}, {}, {:p})",
         domain,
         kind,
diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs
index 039f5a4b5d12b777e433f4a2d7e1be22c607a5e4..4667f761de83d64fbaa5245d17faa18b4a42b404 100644
--- a/src/platform/linux/mod.rs
+++ b/src/platform/linux/mod.rs
@@ -64,15 +64,6 @@ pub fn e_raw(sys: usize) -> Result<usize> {
         Ok(sys)
     }
 }
-pub fn e(sys: usize) -> usize {
-    match e_raw(sys) {
-        Ok(value) => value,
-        Err(Errno(errcode)) => {
-            ERRNO.set(errcode as c_int);
-            !0
-        }
-    }
-}
 
 pub struct Sys;
 
diff --git a/src/platform/linux/ptrace.rs b/src/platform/linux/ptrace.rs
index c6dbaeeba12c63d8bd95220d478ccd0155dcfa7e..d05a1073b16d0af353373b11d467fbe60d0d220a 100644
--- a/src/platform/linux/ptrace.rs
+++ b/src/platform/linux/ptrace.rs
@@ -1,10 +1,16 @@
 use super::{
     super::{types::*, PalPtrace},
-    e, Sys,
+    e_raw, Sys,
 };
+use crate::error::Result;
 
 impl PalPtrace for Sys {
-    fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int {
-        unsafe { e(syscall!(PTRACE, request, pid, addr, data)) as c_int }
+    unsafe fn ptrace(
+        request: c_int,
+        pid: pid_t,
+        addr: *mut c_void,
+        data: *mut c_void,
+    ) -> Result<c_int> {
+        Ok(unsafe { e_raw(syscall!(PTRACE, request, pid, addr, data))? as c_int })
     }
 }
diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs
index 10cefc820000249e6c1309f338f65dd8bcd90c43..27e4dcf6309f50267fcf2a20c03679464f1bef52 100644
--- a/src/platform/linux/signal.rs
+++ b/src/platform/linux/signal.rs
@@ -3,7 +3,7 @@ use core::{mem, ptr::addr_of};
 
 use super::{
     super::{types::*, PalSignal},
-    e, e_raw, Sys,
+    e_raw, Sys,
 };
 use crate::{
     error::{Errno, Result},
diff --git a/src/platform/linux/socket.rs b/src/platform/linux/socket.rs
index ca9532f9ee34f27c049a37f04e9320ebbfb8bec8..3bc8a873419836061936e70a60c248500f00fd49 100644
--- a/src/platform/linux/socket.rs
+++ b/src/platform/linux/socket.rs
@@ -1,46 +1,58 @@
-use super::{
-    super::{types::*, PalSocket},
-    e, Sys,
+use super::{e_raw, Sys};
+use crate::{
+    error::Result,
+    header::sys_socket::{msghdr, sockaddr, socklen_t},
+    platform::{types::*, PalSocket},
 };
-use crate::header::sys_socket::{msghdr, sockaddr, socklen_t};
 
 impl PalSocket for Sys {
-    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
-        e(syscall!(ACCEPT, socket, address, address_len)) as c_int
+    unsafe fn accept(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> Result<c_int> {
+        Ok(e_raw(syscall!(ACCEPT, socket, address, address_len))? as c_int)
     }
 
-    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-        e(syscall!(BIND, socket, address, address_len)) as c_int
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()> {
+        e_raw(syscall!(BIND, socket, address, address_len))?;
+        Ok(())
     }
 
-    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-        e(syscall!(CONNECT, socket, address, address_len)) as c_int
+    unsafe fn connect(
+        socket: c_int,
+        address: *const sockaddr,
+        address_len: socklen_t,
+    ) -> Result<c_int> {
+        Ok(e_raw(syscall!(CONNECT, socket, address, address_len))? as c_int)
     }
 
     unsafe fn getpeername(
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int {
-        e(syscall!(GETPEERNAME, socket, address, address_len)) as c_int
+    ) -> Result<()> {
+        e_raw(syscall!(GETPEERNAME, socket, address, address_len))?;
+        Ok(())
     }
 
     unsafe fn getsockname(
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int {
-        e(syscall!(GETSOCKNAME, socket, address, address_len)) as c_int
+    ) -> Result<()> {
+        e_raw(syscall!(GETSOCKNAME, socket, address, address_len))?;
+        Ok(())
     }
 
-    fn getsockopt(
+    unsafe fn getsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *mut c_void,
         option_len: *mut socklen_t,
-    ) -> c_int {
-        e(unsafe {
+    ) -> Result<()> {
+        e_raw(unsafe {
             syscall!(
                 GETSOCKOPT,
                 socket,
@@ -49,11 +61,13 @@ impl PalSocket for Sys {
                 option_value,
                 option_len
             )
-        }) as c_int
+        })?;
+        Ok(())
     }
 
-    fn listen(socket: c_int, backlog: c_int) -> c_int {
-        e(unsafe { syscall!(LISTEN, socket, backlog) }) as c_int
+    fn listen(socket: c_int, backlog: c_int) -> Result<()> {
+        e_raw(unsafe { syscall!(LISTEN, socket, backlog) })?;
+        Ok(())
     }
 
     unsafe fn recvfrom(
@@ -63,8 +77,8 @@ impl PalSocket for Sys {
         flags: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> ssize_t {
-        e(syscall!(
+    ) -> Result<usize> {
+        e_raw(syscall!(
             RECVFROM,
             socket,
             buf,
@@ -72,15 +86,15 @@ impl PalSocket for Sys {
             flags,
             address,
             address_len
-        )) as ssize_t
+        ))
     }
 
-    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t {
-        e(syscall!(RECVMSG, socket, msg, flags)) as ssize_t
+    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> Result<usize> {
+        e_raw(syscall!(RECVMSG, socket, msg, flags))
     }
 
-    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t {
-        e(syscall!(SENDMSG, socket, msg, flags)) as ssize_t
+    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> Result<usize> {
+        e_raw(syscall!(SENDMSG, socket, msg, flags))
     }
 
     unsafe fn sendto(
@@ -90,20 +104,20 @@ impl PalSocket for Sys {
         flags: c_int,
         dest_addr: *const sockaddr,
         dest_len: socklen_t,
-    ) -> ssize_t {
-        e(syscall!(
+    ) -> Result<usize> {
+        e_raw(syscall!(
             SENDTO, socket, buf, len, flags, dest_addr, dest_len
-        )) as ssize_t
+        ))
     }
 
-    fn setsockopt(
+    unsafe fn setsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *const c_void,
         option_len: socklen_t,
-    ) -> c_int {
-        e(unsafe {
+    ) -> Result<()> {
+        e_raw(unsafe {
             syscall!(
                 SETSOCKOPT,
                 socket,
@@ -112,18 +126,21 @@ impl PalSocket for Sys {
                 option_value,
                 option_len
             )
-        }) as c_int
+        })?;
+        Ok(())
     }
 
-    fn shutdown(socket: c_int, how: c_int) -> c_int {
-        e(unsafe { syscall!(SHUTDOWN, socket, how) }) as c_int
+    fn shutdown(socket: c_int, how: c_int) -> Result<()> {
+        e_raw(unsafe { syscall!(SHUTDOWN, socket, how) })?;
+        Ok(())
     }
 
-    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
-        e(syscall!(SOCKET, domain, kind, protocol)) as c_int
+    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> Result<c_int> {
+        Ok(e_raw(syscall!(SOCKET, domain, kind, protocol))? as c_int)
     }
 
-    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
-        e(unsafe { syscall!(SOCKETPAIR, domain, kind, protocol, sv.as_mut_ptr()) }) as c_int
+    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> Result<()> {
+        e_raw(unsafe { syscall!(SOCKETPAIR, domain, kind, protocol, sv.as_mut_ptr()) })?;
+        Ok(())
     }
 }
diff --git a/src/platform/mod.rs b/src/platform/mod.rs
index d94cdb7e46df0f7d76913fe326fb54f2387aa5ef..e8bab124bee8aea6564c6449e087bbf24260bff0 100644
--- a/src/platform/mod.rs
+++ b/src/platform/mod.rs
@@ -13,7 +13,7 @@ pub use self::pal::{Pal, PalEpoll, PalPtrace, PalSignal, PalSocket};
 
 mod pal;
 
-pub use self::sys::{e, Sys};
+pub use self::sys::Sys;
 
 #[cfg(all(not(feature = "no_std"), target_os = "linux"))]
 #[path = "linux/mod.rs"]
diff --git a/src/platform/pal/ptrace.rs b/src/platform/pal/ptrace.rs
index cc13ebbb68b3d59aef5662052321aff79700fe21..7e68a81d45ef98f10dec95cdc8464b2031e28d8a 100644
--- a/src/platform/pal/ptrace.rs
+++ b/src/platform/pal/ptrace.rs
@@ -1,5 +1,13 @@
-use super::super::{types::*, Pal};
+use crate::{
+    error::Result,
+    platform::{types::*, Pal},
+};
 
 pub trait PalPtrace: Pal {
-    fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int;
+    unsafe fn ptrace(
+        request: c_int,
+        pid: pid_t,
+        addr: *mut c_void,
+        data: *mut c_void,
+    ) -> Result<c_int>;
 }
diff --git a/src/platform/pal/socket.rs b/src/platform/pal/socket.rs
index 737f37215000cab484edbd52cd20cb267c0a56bc..0080c6bedc8db5cc07164ef6c9807dcccbfeb478 100644
--- a/src/platform/pal/socket.rs
+++ b/src/platform/pal/socket.rs
@@ -1,34 +1,45 @@
-use super::super::{types::*, Pal};
-use crate::header::sys_socket::{msghdr, sockaddr, socklen_t};
+use crate::{
+    error::Result,
+    header::sys_socket::{msghdr, sockaddr, socklen_t},
+    platform::{types::*, Pal},
+};
 
 pub trait PalSocket: Pal {
-    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int;
+    unsafe fn accept(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> Result<c_int>;
 
-    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int;
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()>;
 
-    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int;
+    unsafe fn connect(
+        socket: c_int,
+        address: *const sockaddr,
+        address_len: socklen_t,
+    ) -> Result<c_int>;
 
     unsafe fn getpeername(
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int;
+    ) -> Result<()>;
 
     unsafe fn getsockname(
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int;
+    ) -> Result<()>;
 
-    fn getsockopt(
+    unsafe fn getsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *mut c_void,
         option_len: *mut socklen_t,
-    ) -> c_int;
+    ) -> Result<()>;
 
-    fn listen(socket: c_int, backlog: c_int) -> c_int;
+    fn listen(socket: c_int, backlog: c_int) -> Result<()>;
 
     unsafe fn recvfrom(
         socket: c_int,
@@ -37,11 +48,11 @@ pub trait PalSocket: Pal {
         flags: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> ssize_t;
+    ) -> Result<usize>;
 
-    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t;
+    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> Result<usize>;
 
-    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t;
+    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> Result<usize>;
 
     unsafe fn sendto(
         socket: c_int,
@@ -50,19 +61,19 @@ pub trait PalSocket: Pal {
         flags: c_int,
         dest_addr: *const sockaddr,
         dest_len: socklen_t,
-    ) -> ssize_t;
+    ) -> Result<usize>;
 
-    fn setsockopt(
+    unsafe fn setsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *const c_void,
         option_len: socklen_t,
-    ) -> c_int;
+    ) -> Result<()>;
 
-    fn shutdown(socket: c_int, how: c_int) -> c_int;
+    fn shutdown(socket: c_int, how: c_int) -> Result<()>;
 
-    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int;
+    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> Result<c_int>;
 
-    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int;
+    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> Result<()>;
 }
diff --git a/src/platform/redox/extra.rs b/src/platform/redox/extra.rs
index 235ca09dcf618429656ecf37460efdeb688edf8c..5f099750be6bad58bec6daf20b8347707b5052e3 100644
--- a/src/platform/redox/extra.rs
+++ b/src/platform/redox/extra.rs
@@ -1,16 +1,22 @@
 use core::{ptr, slice};
 
-use crate::platform::{sys::e, types::*};
+use crate::{
+    error::{Errno, ResultExt},
+    platform::types::*,
+};
 use syscall::{error::*, F_SETFD, F_SETFL};
 
 pub use redox_rt::proc::FdGuard;
 
 #[no_mangle]
 pub unsafe extern "C" fn redox_fpath(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t {
-    e(syscall::fpath(
+    syscall::fpath(
         fd as usize,
         slice::from_raw_parts_mut(buf as *mut u8, count),
-    )) as ssize_t
+    )
+    .map_err(Errno::from)
+    .map(|l| l as ssize_t)
+    .or_minus_one_errno()
 }
 
 pub fn pipe2(fds: &mut [c_int], flags: usize) -> syscall::error::Result<()> {
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 94fcfac5fb7b807049969cec1763b1276c01e7e7..bda1862753c7c14feb7d19b2908e0079dedd8da0 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -74,17 +74,6 @@ macro_rules! path_from_c_str {
 
 use self::{exec::Executable, path::canonicalize};
 
-// TODO: Remove
-pub fn e(sys: syscall::error::Result<usize>) -> usize {
-    match sys {
-        Ok(ok) => ok,
-        Err(err) => {
-            ERRNO.set(err.errno as c_int);
-            !0
-        }
-    }
-}
-
 pub struct Sys;
 
 impl Pal for Sys {
diff --git a/src/platform/redox/ptrace.rs b/src/platform/redox/ptrace.rs
index e35f24b7e1dc44df74ecd1ad57e2b8467649a086..1f0100af2fc2c9a097ed9c1584aa853d5366180b 100644
--- a/src/platform/redox/ptrace.rs
+++ b/src/platform/redox/ptrace.rs
@@ -11,8 +11,12 @@ use crate::header::arch_aarch64_user::user_regs_struct;
 use crate::header::arch_x64_user::user_regs_struct;
 use crate::{
     c_str::{CStr, CString},
+    error::Errno,
     fs::File,
-    header::{errno as errnoh, fcntl, signal, sys_ptrace},
+    header::{
+        errno::{self as errnoh, EIO},
+        fcntl, signal, sys_ptrace,
+    },
     io::{self, prelude::*},
     sync::Mutex,
 };
@@ -104,7 +108,7 @@ pub fn get_session(
 }
 
 #[cfg(target_arch = "aarch64")]
-fn inner_ptrace(
+unsafe fn inner_ptrace(
     request: c_int,
     pid: pid_t,
     addr: *mut c_void,
@@ -115,7 +119,7 @@ fn inner_ptrace(
 }
 
 #[cfg(target_arch = "x86")]
-fn inner_ptrace(
+unsafe fn inner_ptrace(
     request: c_int,
     pid: pid_t,
     addr: *mut c_void,
@@ -126,7 +130,7 @@ fn inner_ptrace(
 }
 
 #[cfg(target_arch = "x86_64")]
-fn inner_ptrace(
+unsafe fn inner_ptrace(
     request: c_int,
     pid: pid_t,
     addr: *mut c_void,
@@ -253,7 +257,13 @@ fn inner_ptrace(
 }
 
 impl PalPtrace for Sys {
-    fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int {
-        inner_ptrace(request, pid, addr, data).unwrap_or(-1)
+    unsafe fn ptrace(
+        request: c_int,
+        pid: pid_t,
+        addr: *mut c_void,
+        data: *mut c_void,
+    ) -> Result<c_int, Errno> {
+        inner_ptrace(request, pid, addr, data)
+            .map_err(|err| Errno(err.raw_os_error().unwrap_or(EIO)))
     }
 }
diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs
index e8104b18678c70f8a868c88174194b9c7890f67c..4c8500ee3689cdcd51c3cedc37d76aa5e205b94d 100644
--- a/src/platform/redox/signal.rs
+++ b/src/platform/redox/signal.rs
@@ -1,6 +1,6 @@
 use super::{
     super::{types::*, Pal, PalSignal},
-    e, Sys,
+    Sys,
 };
 use crate::{
     error::{Errno, Result},
diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs
index 4f5448005288af4777866d1a7d3a707038cdc6ea..033b53dbf15eebcb7c4f32374ae3567b7b3458ac 100644
--- a/src/platform/redox/socket.rs
+++ b/src/platform/redox/socket.rs
@@ -1,15 +1,17 @@
 use alloc::vec::Vec;
 use core::{cmp, mem, ptr, slice, str};
-use syscall::{self, flag::*, Result};
+use redox_rt::proc::FdGuard;
+use syscall::{self, flag::*};
 
 use super::{
     super::{types::*, Pal, PalSocket, ERRNO},
-    e, Sys,
+    Sys,
 };
 use crate::{
-    error::ResultExt,
+    error::{Errno, Result, ResultExt},
     header::{
         arpa_inet::inet_aton,
+        errno::{EAFNOSUPPORT, EFAULT, EINVAL, ENOSYS, EOPNOTSUPP, EPROTONOSUPPORT},
         netinet_in::{in_addr, in_port_t, sockaddr_in},
         string::strnlen,
         sys_socket::{constants::*, msghdr, sa_family_t, sockaddr, socklen_t},
@@ -26,26 +28,20 @@ macro_rules! bind_or_connect {
         $path
     };
     ($mode:ident into, $socket:expr, $address:expr, $address_len:expr) => {{
-        let fd = bind_or_connect!($mode copy, $socket, $address, $address_len);
+        let fd = bind_or_connect!($mode copy, $socket, $address, $address_len)?;
 
-        let result = syscall::dup2(fd, $socket as usize, &[]);
-        let _ = syscall::close(fd);
-        if (e(result) as c_int) < 0 {
-            return -1;
-        }
-        0
+        let _ = syscall::dup2(fd, $socket as usize, &[])?;
+        Result::<c_int, Errno>::Ok(0)
     }};
     ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
         if ($address_len as usize) < mem::size_of::<sa_family_t>() {
-            ERRNO.set(syscall::EINVAL);
-            return -1;
+            return Err(Errno(EINVAL));
         }
 
         let path = match (*$address).sa_family as c_int {
             AF_INET => {
                 if ($address_len as usize) != mem::size_of::<sockaddr_in>() {
-                    ERRNO.set(syscall::EINVAL);
-                    return -1;
+                    return Err(Errno(EINVAL));
                 }
                 let data = &*($address as *const sockaddr_in);
                 let addr = slice::from_raw_parts(
@@ -96,17 +92,12 @@ macro_rules! bind_or_connect {
                 path
             },
             _ => {
-                ERRNO.set(syscall::EAFNOSUPPORT);
-                return -1;
+                return Err(Errno(EAFNOSUPPORT));
             },
         };
 
         // Duplicate the socket, and then duplicate the copy back to the original fd
-        let fd = e(syscall::dup($socket as usize, path.as_bytes()));
-        if (fd as c_int) < 0 {
-            return -1;
-        }
-        fd
+        syscall::dup($socket as usize, path.as_bytes())
     }};
 }
 
@@ -175,7 +166,7 @@ unsafe fn inner_get_name(
     socket: c_int,
     address: *mut sockaddr,
     address_len: *mut socklen_t,
-) -> Result<usize> {
+) -> Result<()> {
     // Format: [udp|tcp:]remote/local, chan:path
     let mut buf = [0; 256];
     let len = syscall::fpath(socket as usize, &mut buf)?;
@@ -197,7 +188,7 @@ unsafe fn inner_get_name(
         );
     }
 
-    Ok(0)
+    Ok(())
 }
 
 fn socket_kind(mut kind: c_int) -> (c_int, usize) {
@@ -214,25 +205,28 @@ fn socket_kind(mut kind: c_int) -> (c_int, usize) {
 }
 
 impl PalSocket for Sys {
-    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
-        let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
-        if stream < 0 {
-            return -1;
-        }
-        if address != ptr::null_mut()
-            && address_len != ptr::null_mut()
-            && Self::getpeername(stream, address, address_len) < 0
-        {
-            return -1;
+    unsafe fn accept(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> Result<c_int> {
+        let stream = syscall::dup(socket as usize, b"listen")? as c_int;
+        if address != ptr::null_mut() && address_len != ptr::null_mut() {
+            let _ = Self::getpeername(stream, address, address_len)?;
         }
-        stream
+        Ok(stream)
     }
 
-    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-        bind_or_connect!(bind into, socket, address, address_len)
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()> {
+        bind_or_connect!(bind into, socket, address, address_len)?;
+        Ok(())
     }
 
-    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+    unsafe fn connect(
+        socket: c_int,
+        address: *const sockaddr,
+        address_len: socklen_t,
+    ) -> Result<c_int> {
         bind_or_connect!(connect into, socket, address, address_len)
     }
 
@@ -240,41 +234,41 @@ impl PalSocket for Sys {
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int {
-        e(inner_get_name(false, socket, address, address_len)) as c_int
+    ) -> Result<()> {
+        inner_get_name(false, socket, address, address_len)
     }
 
     unsafe fn getsockname(
         socket: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> c_int {
-        e(inner_get_name(true, socket, address, address_len)) as c_int
+    ) -> Result<()> {
+        inner_get_name(true, socket, address, address_len)
     }
 
-    fn getsockopt(
+    unsafe fn getsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *mut c_void,
         option_len: *mut socklen_t,
-    ) -> c_int {
+    ) -> Result<()> {
         match level {
             SOL_SOCKET => match option_name {
                 SO_ERROR => {
                     if option_value.is_null() {
-                        return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int;
+                        return Err(Errno(EFAULT));
                     }
 
                     if (option_len as usize) < mem::size_of::<c_int>() {
-                        return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int;
+                        return Err(Errno(EINVAL));
                     }
 
                     let error = unsafe { &mut *(option_value as *mut c_int) };
                     //TODO: Socket nonblock connection error
                     *error = 0;
 
-                    return 0;
+                    return Ok(());
                 }
                 _ => (),
             },
@@ -285,12 +279,12 @@ impl PalSocket for Sys {
             "getsockopt({}, {}, {}, {:p}, {:p})",
             socket, level, option_name, option_value, option_len
         );
-        e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
+        Err(Errno(ENOSYS))
     }
 
-    fn listen(socket: c_int, backlog: c_int) -> c_int {
+    fn listen(socket: c_int, backlog: c_int) -> Result<()> {
         // Redox has no need to listen
-        0
+        Ok(())
     }
 
     unsafe fn recvfrom(
@@ -300,45 +294,30 @@ impl PalSocket for Sys {
         flags: c_int,
         address: *mut sockaddr,
         address_len: *mut socklen_t,
-    ) -> ssize_t {
+    ) -> Result<usize> {
         if flags != 0 {
-            ERRNO.set(syscall::EOPNOTSUPP);
-            return -1;
+            return Err(Errno(EOPNOTSUPP));
         }
         if address == ptr::null_mut() || address_len == ptr::null_mut() {
             Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
-                .map(|u| u as ssize_t)
-                .or_minus_one_errno()
         } else {
-            let fd = e(syscall::dup(socket as usize, b"listen"));
-            if fd == !0 {
-                return -1;
-            }
-            if Self::getpeername(fd as c_int, address, address_len) < 0 {
-                let _ = syscall::close(fd);
-                return -1;
-            }
+            let fd = FdGuard::new(syscall::dup(socket as usize, b"listen")?);
+            Self::getpeername(*fd as c_int, address, address_len)?;
 
-            let ret = Self::read(fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len))
-                .map(|u| u as ssize_t)
-                .or_minus_one_errno();
-            let _ = syscall::close(fd);
-            ret
+            Self::read(*fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len))
         }
     }
 
-    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t {
+    unsafe fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> Result<usize> {
         //TODO: implement recvfrom with recvmsg
         eprintln!("recvmsg not implemented on redox");
-        ERRNO.set(syscall::ENOSYS);
-        return -1;
+        Err(Errno(ENOSYS))
     }
 
-    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t {
+    unsafe fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> Result<usize> {
         //TODO: implement sendto with sendmsg
         eprintln!("sendmsg not implemented on redox");
-        ERRNO.set(syscall::ENOSYS);
-        return -1;
+        Err(Errno(ENOSYS))
     }
 
     unsafe fn sendto(
@@ -348,64 +327,45 @@ impl PalSocket for Sys {
         flags: c_int,
         dest_addr: *const sockaddr,
         dest_len: socklen_t,
-    ) -> ssize_t {
+    ) -> Result<usize> {
         if flags != 0 {
-            ERRNO.set(syscall::EOPNOTSUPP);
-            return -1;
+            return Err(Errno(EOPNOTSUPP));
         }
         if dest_addr == ptr::null() || dest_len == 0 {
             Self::write(socket, slice::from_raw_parts(buf as *const u8, len))
-                .map(|u| u as ssize_t)
-                .or_minus_one_errno()
         } else {
-            let fd = bind_or_connect!(connect copy, socket, dest_addr, dest_len);
-            let ret = Self::write(fd as c_int, slice::from_raw_parts(buf as *const u8, len))
-                .map(|u| u as ssize_t)
-                .or_minus_one_errno();
-            let _ = syscall::close(fd);
-            ret
+            let fd = FdGuard::new(bind_or_connect!(connect copy, socket, dest_addr, dest_len)?);
+            Self::write(*fd as c_int, slice::from_raw_parts(buf as *const u8, len))
         }
     }
 
-    fn setsockopt(
+    unsafe fn setsockopt(
         socket: c_int,
         level: c_int,
         option_name: c_int,
         option_value: *const c_void,
         option_len: socklen_t,
-    ) -> c_int {
-        let set_timeout = |timeout_name: &[u8]| -> c_int {
+    ) -> Result<()> {
+        let set_timeout = |timeout_name: &[u8]| -> Result<()> {
             if option_value.is_null() {
-                return e(Err(syscall::Error::new(syscall::EFAULT))) as c_int;
+                return Err(Errno(EFAULT));
             }
 
             if (option_len as usize) < mem::size_of::<timeval>() {
-                return e(Err(syscall::Error::new(syscall::EINVAL))) as c_int;
+                return Err(Errno(EINVAL));
             }
 
             let timeval = unsafe { &*(option_value as *const timeval) };
 
-            let fd = e(syscall::dup(socket as usize, timeout_name));
-            if fd == !0 {
-                return -1;
-            }
+            let fd = FdGuard::new(syscall::dup(socket as usize, timeout_name)?);
 
             let timespec = syscall::TimeSpec {
                 tv_sec: timeval.tv_sec as i64,
                 tv_nsec: timeval.tv_usec * 1000,
             };
 
-            let ret = Self::write(fd as c_int, &timespec)
-                .map(|u| u as ssize_t)
-                .or_minus_one_errno();
-
-            let _ = syscall::close(fd);
-
-            if ret >= 0 {
-                0
-            } else {
-                -1
-            }
+            Self::write(*fd as c_int, &timespec)?;
+            Ok(())
         };
 
         match level {
@@ -421,18 +381,17 @@ impl PalSocket for Sys {
             "setsockopt({}, {}, {}, {:p}, {}) - unknown option",
             socket, level, option_name, option_value, option_len
         );
-        0
+        Ok(())
     }
 
-    fn shutdown(socket: c_int, how: c_int) -> c_int {
+    fn shutdown(socket: c_int, how: c_int) -> Result<()> {
         eprintln!("shutdown({}, {})", socket, how);
-        e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
+        Err(Errno(ENOSYS))
     }
 
-    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
+    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> Result<c_int> {
         if domain != AF_INET && domain != AF_UNIX {
-            ERRNO.set(syscall::EAFNOSUPPORT);
-            return -1;
+            return Err(Errno(EAFNOSUPPORT));
         }
         // if protocol != 0 {
         //     ERRNO.set(syscall::EPROTONOSUPPORT);
@@ -443,47 +402,32 @@ impl PalSocket for Sys {
 
         // The tcp: and udp: schemes allow using no path,
         // and later specifying one using `dup`.
-        match (domain, kind) {
-            (AF_INET, SOCK_STREAM) => e(syscall::open("/scheme/tcp", flags)) as c_int,
-            (AF_INET, SOCK_DGRAM) => e(syscall::open("/scheme/udp", flags)) as c_int,
-            (AF_UNIX, SOCK_STREAM) => e(syscall::open("/scheme/chan", flags | O_CREAT)) as c_int,
-            _ => {
-                ERRNO.set(syscall::EPROTONOSUPPORT);
-                -1
-            }
-        }
+        Ok(match (domain, kind) {
+            (AF_INET, SOCK_STREAM) => syscall::open("/scheme/tcp", flags)? as c_int,
+            (AF_INET, SOCK_DGRAM) => syscall::open("/scheme/udp", flags)? as c_int,
+            (AF_UNIX, SOCK_STREAM) => syscall::open("/scheme/chan", flags | O_CREAT)? as c_int,
+            _ => return Err(Errno(EPROTONOSUPPORT)),
+        })
     }
 
-    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
+    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> Result<()> {
         let (kind, flags) = socket_kind(kind);
 
         match (domain, kind) {
             (AF_UNIX, SOCK_STREAM) => {
-                let listener = e(syscall::open("/scheme/chan", flags | O_CREAT));
-                if listener == !0 {
-                    return -1;
-                }
+                let listener = FdGuard::new(syscall::open("/scheme/chan", flags | O_CREAT)?);
 
                 // For now, chan: lets connects be instant, and instead blocks
                 // on any I/O performed. So we don't need to mark this as
                 // nonblocking.
 
-                let fd0 = e(syscall::dup(listener, b"connect"));
-                if fd0 == !0 {
-                    let _ = syscall::close(listener);
-                    return -1;
-                }
+                let mut fd0 = FdGuard::new(syscall::dup(*listener, b"connect")?);
 
-                let fd1 = e(syscall::dup(listener, b"listen"));
-                if fd1 == !0 {
-                    let _ = syscall::close(fd0);
-                    let _ = syscall::close(listener);
-                    return -1;
-                }
+                let mut fd1 = FdGuard::new(syscall::dup(*listener, b"listen")?);
 
-                sv[0] = fd0 as c_int;
-                sv[1] = fd1 as c_int;
-                0
+                sv[0] = fd0.take() as c_int;
+                sv[1] = fd1.take() as c_int;
+                Ok(())
             }
             _ => unsafe {
                 eprintln!(
@@ -493,8 +437,7 @@ impl PalSocket for Sys {
                     protocol,
                     sv.as_mut_ptr()
                 );
-                ERRNO.set(syscall::EPROTONOSUPPORT);
-                -1
+                Err(Errno(EPROTONOSUPPORT))
             },
         }
     }