← Back to team overview

kicad-developers team mailing list archive

[PATCH] Print stacktrace when SIGSEGV or SIGABRT appears

 

Hi,

I wrote some basic crash-handler based on signal handler code published
on the mailinglist some time ago:

* https://lists.launchpad.net/kicad-developers/msg27148.html

For now, it uses the glibc backtrace function to print a basic
stack-trace onto the console, and if possible a crash dump file in the
current working directory.

Unfortunately printing pretty stack-traces is not easy, which means at
the moment users need to manually prettify them when required. To do
this the tools addr2line and c++filt can be used to find the actual
location of the crash.

Nevertheless, it is better than nothing at all. And it could be
especially helpful to find rare crashes which are hard to reproduce.

Regards, Thomas
From 36b475a828e0587069a31ddddc4163908bcfefb7 Mon Sep 17 00:00:00 2001
From: Thomas Pointhuber <thomas.pointhuber@xxxxxx>
Date: Wed, 19 Sep 2018 17:45:27 +0200
Subject: [PATCH] Print stacktrace when SIGSEGV or SIGABRT appears

Based on the Signal Handler code of John Beard:
* https://lists.launchpad.net/kicad-developers/msg27148.html

To convert the addresses to actual lines "addr2line" can be used
To demangle the symbol names "c++filt" can be used
---
 common/CMakeLists.txt         |  1 +
 common/app_signal_handler.cpp | 95 +++++++++++++++++++++++++++++++++++
 common/single_top.cpp         |  5 ++
 include/app_signal_handler.h  | 67 ++++++++++++++++++++++++
 kicad/kicad.cpp               |  5 ++
 5 files changed, 173 insertions(+)
 create mode 100644 common/app_signal_handler.cpp
 create mode 100644 include/app_signal_handler.h

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index dadfad1ae..499baa635 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -241,6 +241,7 @@ set( COMMON_SRCS
     ${COMMON_PAGE_LAYOUT_SRCS}
     ${COMMON_PREVIEW_ITEMS_SRCS}
     ${PLOTTERS_CONTROL_SRCS}
+    app_signal_handler.cpp
     base_struct.cpp
     bezier_curves.cpp
     bin_mod.cpp
diff --git a/common/app_signal_handler.cpp b/common/app_signal_handler.cpp
new file mode 100644
index 000000000..3cf9dd6db
--- /dev/null
+++ b/common/app_signal_handler.cpp
@@ -0,0 +1,95 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <app_signal_handler.h>
+
+#include <csignal>
+
+#include <execinfo.h>
+#include <stdio.h>
+#include <time.h>
+
+#define BACKTRACE_ARRAY_SIZE 64
+#define TMP_BUFFER_SIZE 64
+
+
+void APP_SIGNAL_HANDLER::RegisterSignalHandler( int sig, SigHandler handler )
+{
+    signal( sig, handler );
+}
+
+void APP_SIGNAL_HANDLER::BacktraceSignalHandler( int sig )
+{
+    APP_SIGNAL_HANDLER::WriteBacktraceReport( STDERR_FILENO, sig );
+
+    time_t timer;
+    struct tm* tm_info;
+
+    time( &timer );
+    tm_info = localtime( &timer );
+
+    char tmp_buffer[TMP_BUFFER_SIZE];
+
+    // Write crashdump into the current working directory
+    strftime( tmp_buffer, TMP_BUFFER_SIZE, "kicad%Y%m%d_%H%M%S.crash", tm_info );
+    dprintf( STDERR_FILENO, "\nwrite crashdump to: \"%s\"\n", tmp_buffer );
+    int fd = open( tmp_buffer, O_CREAT|O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
+    if( fd >= 0 )
+    {
+        dprintf( fd, "=== KiCad Crashdump ===\n" );
+
+        strftime( tmp_buffer, TMP_BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", tm_info );
+        dprintf( fd, "Time: %s\n", tmp_buffer );
+
+        APP_SIGNAL_HANDLER::WriteBacktraceReport( fd, sig );
+
+        close( fd );
+    }
+    else
+    {
+        dprintf( STDERR_FILENO, "[unable to write report to disk]\n" );
+    }
+
+
+    quick_exit( EXIT_FAILURE );
+}
+
+
+void APP_SIGNAL_HANDLER::WriteBacktraceReport( int fd, int sig, int skip )
+{
+    dprintf( fd, "Error: signal %d (%s)\n", sig, strsignal( sig ) );
+
+    dprintf( fd, "Backtrace:\n" );
+
+    void *array[BACKTRACE_ARRAY_SIZE];
+    size_t size;
+
+    size = backtrace( array, BACKTRACE_ARRAY_SIZE );
+
+    backtrace_symbols_fd( array+skip, size-skip, fd );
+
+    if( size == BACKTRACE_ARRAY_SIZE )
+    {
+        dprintf( fd, "[truncated]\n" );
+    }
+}
diff --git a/common/single_top.cpp b/common/single_top.cpp
index 30e583892..8cddca26c 100644
--- a/common/single_top.cpp
+++ b/common/single_top.cpp
@@ -46,6 +46,7 @@
 #include <pgm_base.h>
 #include <kiway_player.h>
 #include <confirm.h>
+#include <app_signal_handler.h>
 
 
 // Only a single KIWAY is supported in this single_top top level component,
@@ -126,6 +127,10 @@ struct APP_SINGLE_TOP : public wxApp
 #if defined (__LINUX__)
     APP_SINGLE_TOP(): wxApp()
     {
+        // Register for signals
+        APP_SIGNAL_HANDLER::RegisterSignalHandler( SIGSEGV, APP_SIGNAL_HANDLER::BacktraceSignalHandler );
+        APP_SIGNAL_HANDLER::RegisterSignalHandler( SIGABRT, APP_SIGNAL_HANDLER::BacktraceSignalHandler );
+
         // Disable proxy menu in Unity window manager. Only usual menubar works with wxWidgets (at least <= 3.1)
         // When the proxy menu menubar is enable, some important things for us do not work: menuitems UI events and shortcuts.
         wxString wm;
diff --git a/include/app_signal_handler.h b/include/app_signal_handler.h
new file mode 100644
index 000000000..51fa0ac41
--- /dev/null
+++ b/include/app_signal_handler.h
@@ -0,0 +1,67 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef APP_SIGNAL_HANDLER_H_
+#define APP_SIGNAL_HANDLER_H_
+
+#include <wx/app.h>
+
+/**
+ * Class APP_SIGNAL_HANDLER
+ *
+ * Contains functions for registering signal handlers to run against
+ * a wxApp instance.
+ *
+ * There can only be one of these per program, as the signal handler
+ * callbacks have to be static. You can still register for signals
+ * elsewhere if you do not want to handle them here.
+ */
+class APP_SIGNAL_HANDLER
+{
+public:
+    /*!
+     * Function signature of a signal handler
+     */
+    typedef void ( * SigHandler )( int );
+
+    /*!
+     * Function registerSignalHandler
+     *
+     * Register a signal handler for a set of signals
+     *
+     * @param sig the signal number to registr against
+     * @param handler the handler to register for that signal
+     */
+    static void RegisterSignalHandler( int sig, SigHandler handler );
+
+    /*!
+     * Signal handler that print and saves a backtrace and then exits
+     */
+    static void BacktraceSignalHandler( int sig );
+
+private:
+
+    static void WriteBacktraceReport( int fd, int sig, int skip=2 );
+};
+
+#endif
diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp
index 6892de514..9013141e8 100644
--- a/kicad/kicad.cpp
+++ b/kicad/kicad.cpp
@@ -39,6 +39,7 @@
 #include <richio.h>
 #include <wildcards_and_files_ext.h>
 #include <systemdirsappend.h>
+#include <app_signal_handler.h>
 
 #include <stdexcept>
 
@@ -220,6 +221,10 @@ struct APP_KICAD : public wxApp
 #if defined (__LINUX__)
     APP_KICAD(): wxApp()
     {
+        // register for signals
+        APP_SIGNAL_HANDLER::RegisterSignalHandler( SIGSEGV, APP_SIGNAL_HANDLER::BacktraceSignalHandler );
+        APP_SIGNAL_HANDLER::RegisterSignalHandler( SIGABRT, APP_SIGNAL_HANDLER::BacktraceSignalHandler );
+
         // Disable proxy menu in Unity window manager. Only usual menubar works with
         // wxWidgets (at least <= 3.1).  When the proxy menu menubar is enable, some
         // important things for us do not work: menuitems UI events and shortcuts.
-- 
2.19.0

Attachment: signature.asc
Description: OpenPGP digital signature


Follow ups