diff --git a/src/backend/linux_raw/runtime/syscalls.rs b/src/backend/linux_raw/runtime/syscalls.rs index eac0da324..ac31a2ca4 100644 --- a/src/backend/linux_raw/runtime/syscalls.rs +++ b/src/backend/linux_raw/runtime/syscalls.rs @@ -174,6 +174,11 @@ pub(crate) unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { ret(syscall_readonly!(__NR_tkill, tid, sig)) } +#[inline] +pub(crate) unsafe fn tgkill(tid: Pid, sig: Signal) -> io::Result<()> { + ret(syscall_readonly!(__NR_tgkill, tid, sig)) +} + #[inline] pub(crate) unsafe fn sigprocmask(how: How, new: Option<&Sigset>) -> io::Result { let mut old = MaybeUninit::::uninit(); diff --git a/src/runtime.rs b/src/runtime.rs index a690dde7d..382e940df 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -434,6 +434,34 @@ pub unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { backend::runtime::syscalls::tkill(tid, sig) } +/// `tgkill(tid, sig)`—Send a signal to a thread group. +/// +/// # Safety +/// +/// You're on your own. And on top of all the troubles with signal handlers, +/// this implementation is highly experimental. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/tgkill.2.html +#[inline] +pub unsafe fn tgkill(tid: Pid, sig: Signal) -> io::Result<()> { + backend::runtime::syscalls::tgkill(tid, sig) +} + +/// `raise(sig)`—Send a signal to the current thread. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man3/raise.3.html +#[inline] +pub fn raise(sig: Signal) -> io::Result<()> { + // SAFETY: This sends a signal to the current thread, and our own thread ID can't be recycled. + unsafe { backend::runtime::syscalls::tkill(backend::thread::syscalls::gettid(), sig) } +} + /// `rt_sigprocmask(how, set, oldset)`—Adjust the process signal mask. /// /// # Safety