Fix handling of SIGSEGV and SIGABRT in nano_node (#3502)
The handling of SIGSEGV and SIGABRT did not have the desired effect of generating stack traces of the source code that caused the signal. That's because the signals were handled by the signal manager, which first switches stack context to one that is safe to execute any code. However, for SIGSEGV and SIGABRT we want to print the stacktrace of the problem and therefore we cannot switch context. So, I am setting the handling of SIGSEGV and SIGABRT to use the classic signal function, like before the signal manager was introduced.
This commit is contained in:
parent
fb49976f02
commit
6063f5f011
3 changed files with 20 additions and 15 deletions
|
@ -49,14 +49,6 @@ void nano::signal_manager::register_signal_handler (int signum, std::function<vo
|
|||
log (boost::str (boost::format ("Registered signal handler for signal %d") % signum));
|
||||
}
|
||||
|
||||
std::function<void (int)> nano::signal_manager::get_debug_files_handler (void)
|
||||
{
|
||||
return [] (int) {
|
||||
nano::dump_crash_stacktrace ();
|
||||
nano::create_load_memory_address_files ();
|
||||
};
|
||||
}
|
||||
|
||||
void nano::signal_manager::base_handler (nano::signal_manager::signal_descriptor descriptor, const boost::system::error_code & error, int signum)
|
||||
{
|
||||
if (!error)
|
||||
|
|
|
@ -33,9 +33,6 @@ public:
|
|||
*/
|
||||
void register_signal_handler (int signum, std::function<void (int)> handler, bool repeat);
|
||||
|
||||
/** returns a signal handler that prints a stacktrace and creates some debug files */
|
||||
std::function<void (int)> get_debug_files_handler (void);
|
||||
|
||||
private:
|
||||
struct signal_descriptor final
|
||||
{
|
||||
|
|
|
@ -17,6 +17,16 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
void nano_abort_signal_handler (int signum)
|
||||
{
|
||||
// create some debugging log files
|
||||
nano::dump_crash_stacktrace ();
|
||||
nano::create_load_memory_address_files ();
|
||||
|
||||
// re-raise signal to call the default handler and exit
|
||||
raise (signum);
|
||||
}
|
||||
|
||||
volatile sig_atomic_t sig_int_or_term = 0;
|
||||
|
||||
constexpr std::size_t OPEN_FILE_DESCRIPTORS_LIMIT = 16384;
|
||||
|
@ -39,10 +49,14 @@ static void load_and_set_bandwidth_params (std::shared_ptr<nano::node> const & n
|
|||
|
||||
void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano::node_flags const & flags)
|
||||
{
|
||||
// Override segmentation fault and aborting.
|
||||
nano::signal_manager sigman;
|
||||
sigman.register_signal_handler (SIGSEGV, sigman.get_debug_files_handler (), false);
|
||||
sigman.register_signal_handler (SIGABRT, sigman.get_debug_files_handler (), false);
|
||||
// We catch signal SIGSEGV and SIGABRT not via the signal manager because we want these signal handlers
|
||||
// to be executed in the stack of the code that caused the signal, so we can dump the stacktrace.
|
||||
struct sigaction sa = {};
|
||||
sa.sa_handler = nano_abort_signal_handler;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESETHAND;
|
||||
sigaction (SIGSEGV, &sa, NULL);
|
||||
sigaction (SIGABRT, &sa, NULL);
|
||||
|
||||
boost::filesystem::create_directories (data_path);
|
||||
boost::system::error_code error_chmod;
|
||||
|
@ -155,6 +169,8 @@ void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano::
|
|||
sig_int_or_term = 1;
|
||||
};
|
||||
|
||||
nano::signal_manager sigman;
|
||||
|
||||
// keep trapping Ctrl-C to avoid a second Ctrl-C interrupting tasks started by the first
|
||||
sigman.register_signal_handler (SIGINT, &nano::signal_handler, true);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue