changed signal handling to consider sigaction
Specifically we must always use sa_sigaction and then when chaining to the original signal handler we must determine if it is a sa_sigaction or a sa_handler type function and call it accordingly.
This commit is contained in:
parent
7820b5380b
commit
7d8e60dd61
1 changed files with 50 additions and 4 deletions
|
@ -30,6 +30,11 @@
|
||||||
#include <ros_middleware_interface/functions.h>
|
#include <ros_middleware_interface/functions.h>
|
||||||
#include <ros_middleware_interface/handles.h>
|
#include <ros_middleware_interface/handles.h>
|
||||||
|
|
||||||
|
// Determine if sigaction is available
|
||||||
|
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
|
||||||
|
#define HAS_SIGACTION
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
volatile sig_atomic_t g_signal_status = 0;
|
volatile sig_atomic_t g_signal_status = 0;
|
||||||
|
@ -38,21 +43,48 @@ namespace
|
||||||
std::condition_variable g_interrupt_condition_variable;
|
std::condition_variable g_interrupt_condition_variable;
|
||||||
std::mutex g_interrupt_mutex;
|
std::mutex g_interrupt_mutex;
|
||||||
|
|
||||||
|
#ifdef HAS_SIGACTION
|
||||||
|
struct sigaction old_action;
|
||||||
|
#else
|
||||||
void (*old_signal_handler)(int) = 0;
|
void (*old_signal_handler)(int) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
|
#ifdef HAS_SIGACTION
|
||||||
|
signal_handler(int signal_value, siginfo_t *siginfo, void *context)
|
||||||
|
#else
|
||||||
signal_handler(int signal_value)
|
signal_handler(int signal_value)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
std::cout << "signal_handler(" << signal_value << ")" << std::endl;
|
std::cout << "signal_handler(" << signal_value << ")" << std::endl;
|
||||||
|
#ifdef HAS_SIGACTION
|
||||||
|
if (old_action.sa_flags & SA_SIGINFO)
|
||||||
|
{
|
||||||
|
if (old_action.sa_sigaction != NULL)
|
||||||
|
{
|
||||||
|
old_action.sa_sigaction(signal_value, siginfo, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (old_action.sa_handler != NULL && // Is set
|
||||||
|
old_action.sa_handler != SIG_DFL && // Is not default
|
||||||
|
old_action.sa_handler != SIG_IGN) // Is not ignored
|
||||||
|
{
|
||||||
|
old_action.sa_handler(signal_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (old_signal_handler)
|
||||||
|
{
|
||||||
|
old_signal_handler(signal_value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
g_signal_status = signal_value;
|
g_signal_status = signal_value;
|
||||||
using ros_middleware_interface::trigger_guard_condition;
|
using ros_middleware_interface::trigger_guard_condition;
|
||||||
trigger_guard_condition(g_sigint_guard_cond_handle);
|
trigger_guard_condition(g_sigint_guard_cond_handle);
|
||||||
g_interrupt_condition_variable.notify_all();
|
g_interrupt_condition_variable.notify_all();
|
||||||
if (old_signal_handler)
|
|
||||||
{
|
|
||||||
return old_signal_handler(signal_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +100,18 @@ void
|
||||||
init(int argc, char *argv[])
|
init(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ros_middleware_interface::init();
|
ros_middleware_interface::init();
|
||||||
|
#ifdef HAS_SIGACTION
|
||||||
|
struct sigaction action;
|
||||||
|
memset(&action, 0, sizeof(action));
|
||||||
|
sigemptyset(&action.sa_mask);
|
||||||
|
action.sa_sigaction = ::signal_handler;
|
||||||
|
action.sa_flags = SA_SIGINFO;
|
||||||
|
ssize_t ret = sigaction(SIGINT, &action, &old_action);
|
||||||
|
if (ret == -1)
|
||||||
|
#else
|
||||||
::old_signal_handler = std::signal(SIGINT, ::signal_handler);
|
::old_signal_handler = std::signal(SIGINT, ::signal_handler);
|
||||||
if (::old_signal_handler == SIG_ERR)
|
if (::old_signal_handler == SIG_ERR)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string("Failed to set SIGINT signal handler: (" +
|
std::string("Failed to set SIGINT signal handler: (" +
|
||||||
|
@ -103,4 +145,8 @@ sleep_for(const std::chrono::duration<Rep, Period>& sleep_duration)
|
||||||
} /* namespace utilities */
|
} /* namespace utilities */
|
||||||
} /* namespace rclcpp */
|
} /* namespace rclcpp */
|
||||||
|
|
||||||
|
#ifdef HAS_SIGACTION
|
||||||
|
#undef HAS_SIGACTION
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* RCLCPP_RCLCPP_UTILITIES_HPP_ */
|
#endif /* RCLCPP_RCLCPP_UTILITIES_HPP_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue