source: rrlib_crash_handler/crash_handler.cpp @ 3:d57230dc982a

Last change on this file since 3:d57230dc982a was 3:d57230dc982a, checked in by Tobias Föhst <foehst@…>, 6 years ago

Added and updated license information

File size: 5.7 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/crash_handler/crash_handler.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-06-20
27 *
28 */
29//----------------------------------------------------------------------
30
31//----------------------------------------------------------------------
32// External includes (system with <>, local with "")
33//----------------------------------------------------------------------
34#include <sys/prctl.h>
35#include <sys/wait.h>
36#include <sstream>
37
38//----------------------------------------------------------------------
39// Internal includes with ""
40//----------------------------------------------------------------------
41#include "rrlib/crash_handler/crash_handler.h"
42#include "rrlib/thread/tThread.h"
43
44//----------------------------------------------------------------------
45// Debugging
46//----------------------------------------------------------------------
47#include <cassert>
48
49//----------------------------------------------------------------------
50// Namespace usage
51//----------------------------------------------------------------------
52
53//----------------------------------------------------------------------
54// Namespace declaration
55//----------------------------------------------------------------------
56namespace rrlib
57{
58namespace crash_handler
59{
60
61//----------------------------------------------------------------------
62// Forward declarations / typedefs / enums
63//----------------------------------------------------------------------
64#ifndef PR_SET_PTRACER
65#define PR_SET_PTRACER 0x59616d61
66#endif
67//----------------------------------------------------------------------
68// Const values
69//----------------------------------------------------------------------
70
71//----------------------------------------------------------------------
72// Implementation
73//----------------------------------------------------------------------
74
75//----------------------------------------------------------------------
76// SomeFunction
77//----------------------------------------------------------------------
78static void HandleCrash(int signal)
79{
80  // We do not want to execute this function more than once in application life-time
81  static bool called = false;
82  if (called)
83  {
84    return;
85  }
86  called = true;
87
88  rrlib::thread::tThread& t = rrlib::thread::tThread::CurrentThread();
89  const char* signal_string = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
90  std::cout << std::endl << "\033[;1;31m************************************************************************" << std::endl;
91  if (&t) // Should always be the case. However, you never know if application has crashed.
92  {
93    std::cout << "Thread '" << t.GetName() << "' (" << (void*)t.GetNativeHandle() << ") just did something bad (" << signal_string << ") and crashed your program." << std::endl;
94  }
95  else
96  {
97    std::cout << "Something bad happened and crashed your program (" << signal_string << ")." << std::endl;
98  }
99  std::cout << "Would you like to start gdb to inquire what happened (y/n)?" << std::endl << std::endl;
100  std::cout << "Important gdb commands:" << std::endl;
101  std::cout << "  'info threads'      shows all running threads" << std::endl;
102  std::cout << "  'thread <threadno>' selects thread" << std::endl;
103  std::cout << "  'bt [full]'         prints stack trace" << std::endl << std::endl;
104  std::cout << "If you believe the error is not in your own code, we are always happy to receive bug reports. Please submit a full backtrace of the thread that crashed. Thanks!" << std::endl;
105  std::cout << "************************************************************************\033[;0m" << std::endl;
106  char answer;
107  std::cin >> answer;
108  if (answer == 'y' || answer == 'Y')
109  {
110    pid_t pid = getpid();
111    prctl(PR_SET_PTRACER, pid, 0, 0, 0); // Allows a gdb child process to attach
112    std::ostringstream pidstr;
113    pidstr << pid;
114    char binary_name[1024];
115    int chars = readlink("/proc/self/exe", binary_name, 1013);
116    binary_name[chars] = 0;
117    pid_t child = fork();
118    if (!child)
119    {
120      execlp("gdb", "gdb", binary_name, pidstr.str().c_str(), NULL);
121      abort(); // If we could not start gdb
122    }
123    else
124    {
125      waitpid(child, NULL, 0);
126    }
127  }
128}
129
130bool InstallCrashHandler()
131{
132  //rrlib::thread::tThread::CurrentThread().SetName("Main"); // Names process "Main", too
133
134  struct sigaction signal_action;
135  signal_action.sa_handler = HandleCrash;
136  sigemptyset(&signal_action.sa_mask);
137  signal_action.sa_flags = 0;
138
139  if (sigaction(SIGABRT, &signal_action, NULL) != 0)
140  {
141    perror("Could not install signal handler for SIGABRT");
142    return false;
143  }
144  if (sigaction(SIGSEGV, &signal_action, NULL) != 0)
145  {
146    perror("Could not install signal handler for SIGSEGV");
147    return false;
148  }
149
150  return true;
151}
152
153//----------------------------------------------------------------------
154// End of namespace declaration
155//----------------------------------------------------------------------
156}
157}
Note: See TracBrowser for help on using the repository browser.