From ac5ac928f27d6a3a104b723d7d24c2a4fea30ceb Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Wed, 17 Jul 2024 17:41:10 +0200
Subject: [PATCH] Implement raise() using pthread_kill.

---
 fmt.sh                       |  2 +-
 redox-rt/src/sys.rs          | 24 ++++++++++++++++--------
 src/header/signal/mod.rs     |  2 +-
 src/platform/linux/signal.rs | 11 ++++-------
 src/platform/pal/signal.rs   |  2 +-
 src/platform/redox/mod.rs    |  3 +--
 src/platform/redox/signal.rs |  5 +++--
 7 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/fmt.sh b/fmt.sh
index be8636e2..8caff707 100755
--- a/fmt.sh
+++ b/fmt.sh
@@ -1,3 +1,3 @@
 #!/usr/bin/env bash
 
-cargo fmt --package relibc --package crt0 "$@"
+cargo fmt --package relibc --package crt0 --package redox-rt "$@"
diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs
index 77750a6a..99b877a9 100644
--- a/redox-rt/src/sys.rs
+++ b/redox-rt/src/sys.rs
@@ -3,10 +3,10 @@ use syscall::{
     TimeSpec,
 };
 
-use crate::{arch::manually_enter_trampoline, signal::tmp_disable_signals, Tcb};
+use crate::{arch::manually_enter_trampoline, proc::FdGuard, signal::tmp_disable_signals, Tcb};
 
 #[inline]
-fn wrapper<T>(mut f: impl FnMut() -> Result<T>) -> Result<T> {
+fn wrapper<T>(restart: bool, mut f: impl FnMut() -> Result<T>) -> Result<T> {
     loop {
         let _guard = tmp_disable_signals();
         let rt_sigarea = unsafe { &Tcb::current().unwrap().os_specific };
@@ -14,6 +14,7 @@ fn wrapper<T>(mut f: impl FnMut() -> Result<T>) -> Result<T> {
 
         if let Err(err) = res
             && err == Error::new(EINTR)
+            && restart
         {
             unsafe {
                 manually_enter_trampoline();
@@ -30,29 +31,29 @@ fn wrapper<T>(mut f: impl FnMut() -> Result<T>) -> Result<T> {
 // TODO: uninitialized memory?
 #[inline]
 pub fn posix_read(fd: usize, buf: &mut [u8]) -> Result<usize> {
-    wrapper(|| syscall::read(fd, buf))
+    wrapper(true, || syscall::read(fd, buf))
 }
 #[inline]
 pub fn posix_write(fd: usize, buf: &[u8]) -> Result<usize> {
-    wrapper(|| syscall::write(fd, buf))
+    wrapper(true, || syscall::write(fd, buf))
 }
 #[inline]
 pub fn posix_kill(pid: usize, sig: usize) -> Result<()> {
-    match wrapper(|| syscall::kill(pid, sig)) {
+    match wrapper(false, || syscall::kill(pid, sig)) {
         Ok(_) | Err(Error { errno: EINTR }) => Ok(()),
         Err(error) => Err(error),
     }
 }
 #[inline]
 pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> {
-    match wrapper(|| syscall::kill(usize::wrapping_neg(pgrp), sig)) {
+    match wrapper(false, || syscall::kill(usize::wrapping_neg(pgrp), sig)) {
         Ok(_) | Err(Error { errno: EINTR }) => Ok(()),
         Err(error) => Err(error),
     }
 }
 #[inline]
 pub unsafe fn sys_futex_wait(addr: *mut u32, val: u32, deadline: Option<&TimeSpec>) -> Result<()> {
-    wrapper(|| {
+    wrapper(true, || {
         syscall::syscall5(
             syscall::SYS_FUTEX,
             addr as usize,
@@ -77,7 +78,7 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result<u32> {
     .map(|awoken| awoken as u32)
 }
 pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result<usize> {
-    wrapper(|| {
+    wrapper(true, || {
         syscall::waitpid(
             pid,
             status,
@@ -85,3 +86,10 @@ pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result<usize
         )
     })
 }
+pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> {
+    let killfd = FdGuard::new(syscall::dup(thread_fd, b"signal")?);
+    match wrapper(false, || syscall::write(*killfd, &signal.to_ne_bytes())) {
+        Ok(_) | Err(Error { errno: EINTR }) => Ok(()),
+        Err(error) => Err(error),
+    }
+}
diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs
index 01cd57d7..4c2db6b9 100644
--- a/src/header/signal/mod.rs
+++ b/src/header/signal/mod.rs
@@ -104,7 +104,7 @@ pub unsafe extern "C" fn pthread_sigmask(
 
 #[no_mangle]
 pub extern "C" fn raise(sig: c_int) -> c_int {
-    Sys::raise(sig)
+    Sys::raise(sig).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs
index c92cd2ff..8055904c 100644
--- a/src/platform/linux/signal.rs
+++ b/src/platform/linux/signal.rs
@@ -26,13 +26,10 @@ impl PalSignal for Sys {
         e(unsafe { syscall!(KILL, -(pgrp as isize) as pid_t, sig) }) as c_int
     }
 
-    fn raise(sig: c_int) -> c_int {
-        let tid = e(unsafe { syscall!(GETTID) }) as pid_t;
-        if tid == !0 {
-            -1
-        } else {
-            e(unsafe { syscall!(TKILL, tid, sig) }) as c_int
-        }
+    fn raise(sig: c_int) -> Result<(), Errno> {
+        let tid = e_raw(unsafe { syscall!(GETTID) })? as pid_t;
+        e_raw(unsafe { syscall!(TKILL, tid, sig) })?;
+        Ok(())
     }
 
     unsafe fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs
index a802270f..cd9151a5 100644
--- a/src/platform/pal/signal.rs
+++ b/src/platform/pal/signal.rs
@@ -15,7 +15,7 @@ pub trait PalSignal: Pal {
 
     fn killpg(pgrp: pid_t, sig: c_int) -> c_int;
 
-    fn raise(sig: c_int) -> c_int;
+    fn raise(sig: c_int) -> Result<(), Errno>;
 
     unsafe fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int;
 
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 7e2e86b0..05378c34 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -802,8 +802,7 @@ impl Pal for Sys {
         os_tid: crate::pthread::OsTid,
         signal: usize,
     ) -> Result<(), crate::pthread::Errno> {
-        let killfd = FdGuard::new(syscall::dup(os_tid.thread_fd, b"signal")?);
-        syscall::write(*killfd, &(signal as u32).to_ne_bytes())?;
+        redox_rt::sys::posix_kill_thread(os_tid.thread_fd, signal as u32)?;
         Ok(())
     }
     fn current_os_tid() -> crate::pthread::OsTid {
diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs
index ce156d1d..e359c540 100644
--- a/src/platform/redox/signal.rs
+++ b/src/platform/redox/signal.rs
@@ -60,8 +60,9 @@ impl PalSignal for Sys {
         e(redox_rt::sys::posix_killpg(pgrp as usize, sig as usize).map(|()| 0)) as c_int
     }
 
-    fn raise(sig: c_int) -> c_int {
-        Self::kill(Self::getpid(), sig)
+    fn raise(sig: c_int) -> Result<(), Errno> {
+        // TODO: Bypass kernel?
+        unsafe { Self::rlct_kill(Self::current_os_tid(), sig as _) }
     }
 
     unsafe fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
-- 
GitLab