diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c4bcaf244..2a5ea4fd14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). - Added `IPV6_V6ONLY` sockopt. (#[1470](https://github.com/nix-rust/nix/pull/1470)) +- Added `pthread_kill`. + (#[1472](https://github.com/nix-rust/nix/pull/1472)) ### Changed diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 273b352165..e9b3706ad9 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -6,6 +6,8 @@ use crate::{Error, Result}; use crate::errno::Errno; use crate::unistd::Pid; +#[cfg(not(target_os = "redox"))] +use crate::sys::pthread::Pthread; use std::convert::TryFrom; use std::mem; use std::fmt; @@ -781,6 +783,22 @@ pub fn killpg>>(pgrp: Pid, signal: T) -> Result<()> { Errno::result(res).map(drop) } +/// Send a signal to a thread (see [`pthread_kill(3)`]). +/// +/// If `signal` is `None`, `pthread_kill` will only preform error checking and +/// won't send any signal. +/// +/// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html +#[cfg(not(target_os = "redox"))] +pub fn pthread_kill>>(thread: Pthread, signal: T) -> Result<()> { + let sig = match signal.into() { + Some(s) => s as libc::c_int, + None => 0, + }; + let res = unsafe { libc::pthread_kill(thread, sig) }; + Errno::result(res).map(drop) +} + pub fn raise(signal: Signal) -> Result<()> { let res = unsafe { libc::raise(signal as libc::c_int) }; diff --git a/test/sys/test_signal.rs b/test/sys/test_signal.rs index 1b89af5737..b6742657cb 100644 --- a/test/sys/test_signal.rs +++ b/test/sys/test_signal.rs @@ -1,5 +1,7 @@ #[cfg(not(target_os = "redox"))] use nix::errno::Errno; +#[cfg(not(target_os = "redox"))] +use nix::sys::pthread::pthread_self; use nix::sys::signal::*; use nix::unistd::*; use std::convert::TryFrom; @@ -17,6 +19,13 @@ fn test_killpg_none() { .expect("Should be able to send signal to my process group."); } +#[test] +#[cfg(not(target_os = "redox"))] +fn test_pthread_kill_none() { + pthread_kill(pthread_self(), None) + .expect("Should be able to send signal to my thread."); +} + #[test] fn test_old_sigaction_flags() { let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");