diff --git a/iceoryx2-bb/posix/src/signal.rs b/iceoryx2-bb/posix/src/signal.rs index aeb264d3b..f95c7414d 100644 --- a/iceoryx2-bb/posix/src/signal.rs +++ b/iceoryx2-bb/posix/src/signal.rs @@ -40,7 +40,7 @@ //! //! fn some_task() {} //! -//! while SignalHandler::last_signal() != Some(FetchableSignal::Terminate) { +//! while SignalHandler::last_signal() != Some(NonFatalFetchableSignal::Terminate) { //! some_task(); //! } //! ``` @@ -50,7 +50,7 @@ //! ```no_run //! use iceoryx2_bb_posix::signal::*; //! -//! SignalHandler::wait_for_signal(FetchableSignal::Terminate); +//! SignalHandler::wait_for_signal(NonFatalFetchableSignal::Terminate); //! ``` use std::{ fmt::{Debug, Display}, @@ -75,16 +75,36 @@ use tiny_fn::tiny_fn; macro_rules! define_signals { {fetchable: $($entry:ident = $nn:ident::$value:ident),* + fatal_fetchable: $($fatal_entry:ident = $fatal_nn:ident::$fatal_value:ident),* unknown_translates_to: $unknown_entry:ident = $unknown_nn:ident::$unknown_value:ident unfetchable: $($uentry:ident = $unn:ident::$uvalue:ident),* } => { /// Represents signals which cannot be fetched by a signal handler. - #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] + #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Sequence)] #[repr(i32)] pub enum UnfetchableSignal { $($uentry = $unn::$uvalue),*, } + enum_gen! { + /// Represents signals that can be fetched and are non-fatal, meaning that they do not + /// indicate that the process is somehow corrupted. For example: `SIGUSR1` or `SIGINT`. + #[derive(Sequence)] + NonFatalFetchableSignal + unknown_translates_to: + $unknown_entry = $unknown_nn::$unknown_value + entry: + $($entry = $nn::$value),* + } + + /// Represents signals that can be fetched and are fatal, meaning that they + /// indicate that the process is somehow corrupted and should terminate. + #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Sequence)] + #[repr(i32)] + pub enum FatalFetchableSignal { + $($fatal_entry = $fatal_nn::$value),*, + } + enum_gen! { /// Represents all signals which can be fetched by a signal handler. #[derive(Sequence)] @@ -92,15 +112,17 @@ macro_rules! define_signals { unknown_translates_to: $unknown_entry = $unknown_nn::$unknown_value entry: - $($entry = $nn::$value),* + $($entry = $nn::$value),*, + $($fatal_entry = $fatal_nn::$fatal_value),* } /// Represents all known POSIX signals - #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] + #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Sequence)] #[repr(i32)] pub enum Signal { $($entry = $nn::$value),*, $($uentry = $unn::$uvalue),*, + $($fatal_entry = $fatal_nn::$fatal_value),*, $unknown_entry = $unknown_nn::$unknown_value } @@ -112,10 +134,45 @@ macro_rules! define_signals { } } + impl From for FetchableSignal { + fn from(v: FatalFetchableSignal) -> Self { + match v { + $(FatalFetchableSignal::$fatal_entry => FetchableSignal::$fatal_entry),* + } + } + } + + impl From for Signal { + fn from(v: FatalFetchableSignal) -> Self { + match v { + $(FatalFetchableSignal::$fatal_entry => Signal::$fatal_entry),* + } + } + } + + impl From for FetchableSignal { + fn from(v: NonFatalFetchableSignal) -> Self { + match v { + $(NonFatalFetchableSignal::$entry => FetchableSignal::$entry),*, + NonFatalFetchableSignal::$unknown_entry => FetchableSignal::$unknown_entry, + } + } + } + + impl From for Signal { + fn from(v: NonFatalFetchableSignal) -> Self { + match v { + $(NonFatalFetchableSignal::$entry => Signal::$entry),*, + NonFatalFetchableSignal::$unknown_entry => Signal::$unknown_entry, + } + } + } + impl From for Signal { fn from(v: FetchableSignal) -> Self { match v { $(FetchableSignal::$entry => Signal::$entry),*, + $(FetchableSignal::$fatal_entry => Signal::$fatal_entry),*, FetchableSignal::$unknown_entry => Signal::$unknown_entry, } } @@ -125,20 +182,12 @@ macro_rules! define_signals { define_signals! { fetchable: - Abort = posix::SIGABRT, - Alarm = posix::SIGALRM, - Bus = posix::SIGBUS, - Child = posix::SIGCHLD, //TODO: https://github.com/eclipse-iceoryx/iceoryx2/issues/81 // comment in Continue again when the bindgen bug is fixed //Continue = posix::SIGCONT, - FloatingPointError = posix::SIGFPE, - Hangup = posix::SIGHUP, - IllegalInstruction = posix::SIGILL, + Abort = posix::SIGABRT, Interrupt = posix::SIGINT, - BrokenPipe = posix::SIGPIPE, TerminalQuit = posix::SIGQUIT, - SegmentationFault = posix::SIGSEGV, Terminate = posix::SIGTERM, TerminalStop = posix::SIGTSTP, BackgroundProcessReadAttempt = posix::SIGTTIN, @@ -146,12 +195,21 @@ define_signals! { UserDefined1 = posix::SIGUSR1, PollableEvent = posix::SIGPOLL, ProfilingTimerExpired = posix::SIGPROF, - BadSystemCall = posix::SIGSYS, - TraceTrap = posix::SIGTRAP, UrgentDataAvailableAtSocket = posix::SIGURG, - VirtualTimerExpired = posix::SIGVTALRM, + VirtualTimerExpired = posix::SIGVTALRM + fatal_fetchable: + Alarm = posix::SIGALRM, + BadSystemCall = posix::SIGSYS, + BrokenPipe = posix::SIGPIPE, + Bus = posix::SIGBUS, + Child = posix::SIGCHLD, CpuTimeLimitExceeded = posix::SIGXCPU, - FileSizeLimitExceeded = posix::SIGXFSZ + FileSizeLimitExceeded = posix::SIGXFSZ, + FloatingPointError = posix::SIGFPE, + Hangup = posix::SIGHUP, + IllegalInstruction = posix::SIGILL, + SegmentationFault = posix::SIGSEGV, + TraceTrap = posix::SIGTRAP unknown_translates_to: UserDefined2 = posix::SIGUSR2 unfetchable: @@ -322,8 +380,8 @@ impl SignalHandler { /// Calls a provided callable and fetches possible signals which where raised indirectly by /// the call. This is helpful for instance when a low level C call can fail by emitting a /// signal. On example is `memset` when it writes on a preallocated chunk but the actual - /// memory of the operating system does not suffice. - pub fn call_and_fetch(call: F) -> Option { + /// memory of the operating system does not suffice then it emits `SIGABRT` + pub fn call_and_fetch(call: F) -> Option { { let _sighandle = Self::instance(); LAST_SIGNAL.store(posix::MAX_SIGNAL_VALUE, Ordering::Relaxed); @@ -339,7 +397,7 @@ impl SignalHandler { /// Returns the last signal which was raised. After the call the last signal is reset and would /// return [`None`] on the next call when no new signal was raised again. - pub fn last_signal() -> Option { + pub fn last_signal() -> Option { Self::instance(); match LAST_SIGNAL.swap(posix::MAX_SIGNAL_VALUE, Ordering::Relaxed) { posix::MAX_SIGNAL_VALUE => None, @@ -347,27 +405,30 @@ impl SignalHandler { } } - /// Returns true if ([`FetchableSignal::Interrupt`] or [`FetchableSignal::Terminate`]) was emitted + /// Returns true if ([`NonFatalFetchableSignal::Interrupt`] or + /// [`NonFatalFetchableSignal::Terminate`]) was emitted /// for instance by pressing CTRL+c, otherwise false pub fn termination_requested() -> bool { let last_signal = Self::last_signal(); - last_signal == Some(FetchableSignal::Interrupt) - || last_signal == Some(FetchableSignal::Terminate) + last_signal == Some(NonFatalFetchableSignal::Interrupt) + || last_signal == Some(NonFatalFetchableSignal::Terminate) } /// Blocks until the provided signal was raised or an error occurred. /// ```no_run /// use iceoryx2_bb_posix::signal::*; /// - /// SignalHandler::wait_for_signal(FetchableSignal::Terminate); + /// SignalHandler::wait_for_signal(NonFatalFetchableSignal::Terminate); /// ``` - pub fn wait_for_signal(signal: FetchableSignal) -> Result<(), SignalWaitError> { + pub fn wait_for_signal(signal: NonFatalFetchableSignal) -> Result<(), SignalWaitError> { let s = vec![signal]; Self::wait_for_multiple_signals(&s) } /// Blocks until the provided vector signals was raised or an error occurred. - pub fn wait_for_multiple_signals(signals: &[FetchableSignal]) -> Result<(), SignalWaitError> { + pub fn wait_for_multiple_signals( + signals: &[NonFatalFetchableSignal], + ) -> Result<(), SignalWaitError> { Self::instance(); let origin = "Signal::wait_for_multiple_signals"; @@ -401,7 +462,7 @@ impl SignalHandler { /// } /// ``` pub fn timed_wait_for_signal( - signal: FetchableSignal, + signal: NonFatalFetchableSignal, timeout: Duration, ) -> Result { let signals = vec![signal]; @@ -411,9 +472,9 @@ impl SignalHandler { /// Blocks until one of the provided signals was raised or the timeout was reached. If one of the /// signals raised it returns its value, otherwise [`None`]. pub fn timed_wait_for_multiple_signals( - signals: &Vec, + signals: &Vec, timeout: Duration, - ) -> Result, SignalWaitError> { + ) -> Result, SignalWaitError> { Self::instance(); let origin = "Signal::timed_wait_for_multiple_signals"; @@ -474,8 +535,8 @@ impl SignalHandler { do_repeat_eintr_call: false, }; - for signal in all::().collect::>() { - sighandle.register_raw_signal(signal, capture_signal as posix::sighandler_t); + for signal in all::().collect::>() { + sighandle.register_raw_signal(signal.into(), capture_signal as posix::sighandler_t); } sighandle diff --git a/iceoryx2-bb/posix/tests/signal_tests.rs b/iceoryx2-bb/posix/tests/signal_tests.rs index fbc274ce4..b2092f6b0 100644 --- a/iceoryx2-bb/posix/tests/signal_tests.rs +++ b/iceoryx2-bb/posix/tests/signal_tests.rs @@ -50,7 +50,7 @@ impl TestFixture { COUNTER.fetch_add(1, Ordering::SeqCst); } - pub fn verify(&self, signal: FetchableSignal, counter_value: usize) { + pub fn verify(&self, signal: NonFatalFetchableSignal, counter_value: usize) { assert_that!( || { COUNTER.load(Ordering::SeqCst) }, block_until counter_value @@ -70,7 +70,7 @@ fn signal_register_single_handler_works() { SignalHandler::register(FetchableSignal::UserDefined1, &TestFixture::signal_callback); Process::from_self().send_signal(Signal::UserDefined1).ok(); - test.verify(FetchableSignal::UserDefined1, 1) + test.verify(NonFatalFetchableSignal::UserDefined1, 1) } #[test] @@ -85,10 +85,10 @@ fn signal_register_multiple_handler_works() { SignalHandler::register(FetchableSignal::UserDefined2, &TestFixture::signal_callback); Process::from_self().send_signal(Signal::UserDefined1).ok(); - test.verify(FetchableSignal::UserDefined1, 1); + test.verify(NonFatalFetchableSignal::UserDefined1, 1); Process::from_self().send_signal(Signal::UserDefined2).ok(); - test.verify(FetchableSignal::UserDefined2, 2); + test.verify(NonFatalFetchableSignal::UserDefined2, 2); } #[test] @@ -100,10 +100,10 @@ fn signal_register_handler_with_multiple_signals_works() { let _guard1 = SignalHandler::register_multiple_signals(&s, &TestFixture::signal_callback); Process::from_self().send_signal(Signal::UserDefined1).ok(); - test.verify(FetchableSignal::UserDefined1, 1); + test.verify(NonFatalFetchableSignal::UserDefined1, 1); Process::from_self().send_signal(Signal::UserDefined2).ok(); - test.verify(FetchableSignal::UserDefined2, 2); + test.verify(NonFatalFetchableSignal::UserDefined2, 2); } #[test] @@ -122,7 +122,7 @@ fn signal_guard_unregisters_on_drop() { }); Process::from_self().send_signal(Signal::UserDefined1).ok(); - test.verify(FetchableSignal::UserDefined1, 10); + test.verify(NonFatalFetchableSignal::UserDefined1, 10); } #[test] @@ -144,13 +144,12 @@ fn signal_call_and_fetch_works() { test_requires!(POSIX_SUPPORT_ADVANCED_SIGNAL_HANDLING); let _test = TestFixture::new(); - let result = SignalHandler::call_and_fetch(|| { Process::from_self().send_signal(Signal::Interrupt).ok(); nanosleep(TIMEOUT).ok(); }); - assert_that!(result, eq Some(FetchableSignal::Interrupt)); + assert_that!(result, eq Some(NonFatalFetchableSignal::Interrupt)); } #[test] @@ -167,8 +166,8 @@ fn signal_call_and_fetch_with_registered_handler_works() { nanosleep(TIMEOUT).ok(); }); - assert_that!(result, eq Some(FetchableSignal::UserDefined1)); - test.verify(FetchableSignal::UserDefined1, 1); + assert_that!(result, eq Some(NonFatalFetchableSignal::UserDefined1)); + test.verify(NonFatalFetchableSignal::UserDefined1, 1); } #[test] @@ -177,7 +176,10 @@ fn signal_wait_for_signal_blocks() { let _test = TestFixture::new(); - let signals = vec![FetchableSignal::UserDefined2, FetchableSignal::UserDefined1]; + let signals = vec![ + NonFatalFetchableSignal::UserDefined2, + NonFatalFetchableSignal::UserDefined1, + ]; let counter = AtomicI32::new(0); thread::scope(|s| { s.spawn(|| { @@ -206,7 +208,7 @@ fn signal_wait_twice_for_same_signal_blocks() { let counter = AtomicI32::new(0); thread::scope(|s| { s.spawn(|| { - SignalHandler::wait_for_signal(FetchableSignal::UserDefined2).unwrap(); + SignalHandler::wait_for_signal(NonFatalFetchableSignal::UserDefined2).unwrap(); counter.fetch_add(1, Ordering::Relaxed); }); @@ -215,7 +217,7 @@ fn signal_wait_twice_for_same_signal_blocks() { Process::from_self().send_signal(Signal::UserDefined2).ok(); s.spawn(|| { - SignalHandler::wait_for_signal(FetchableSignal::UserDefined2).unwrap(); + SignalHandler::wait_for_signal(NonFatalFetchableSignal::UserDefined2).unwrap(); counter.fetch_add(1, Ordering::Relaxed); }); @@ -239,7 +241,7 @@ fn signal_timed_wait_blocks_at_least_for_timeout() { let _test = TestFixture::new(); let start = Time::now_with_clock(ClockType::Monotonic).unwrap(); - SignalHandler::timed_wait_for_signal(FetchableSignal::UserDefined2, TIMEOUT).unwrap(); + SignalHandler::timed_wait_for_signal(NonFatalFetchableSignal::UserDefined2, TIMEOUT).unwrap(); assert_that!(start.elapsed().unwrap(), time_at_least TIMEOUT); } @@ -249,7 +251,10 @@ fn signal_timed_wait_blocks_until_signal() { let _test = TestFixture::new(); - let signals = vec![FetchableSignal::UserDefined2, FetchableSignal::UserDefined1]; + let signals = vec![ + NonFatalFetchableSignal::UserDefined2, + NonFatalFetchableSignal::UserDefined1, + ]; let counter = AtomicI32::new(0); thread::scope(|s| { s.spawn(|| {