source: rrlib_crash_handler/crash_handler.cpp

17.03 tip
Last change on this file was 5:e151ea4bf5d9, checked in by Max Reichardt <mreichardt@…>, 7 years ago

Added missing include

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#include <unistd.h>
38
39//----------------------------------------------------------------------
40// Internal includes with ""
41//----------------------------------------------------------------------
42#include "rrlib/crash_handler/crash_handler.h"
43#include "rrlib/thread/tThread.h"
44
45//----------------------------------------------------------------------
46// Debugging
47//----------------------------------------------------------------------
48#include <cassert>
49
50//----------------------------------------------------------------------
51// Namespace usage
52//----------------------------------------------------------------------
53
54//----------------------------------------------------------------------
55// Namespace declaration
56//----------------------------------------------------------------------
57namespace rrlib
58{
59namespace crash_handler
60{
61
62//----------------------------------------------------------------------
63// Forward declarations / typedefs / enums
64//----------------------------------------------------------------------
65#ifndef PR_SET_PTRACER
66#define PR_SET_PTRACER 0x59616d61
67#endif
68//----------------------------------------------------------------------
69// Const values
70//----------------------------------------------------------------------
71
72//----------------------------------------------------------------------
73// Implementation
74//----------------------------------------------------------------------
75
76//----------------------------------------------------------------------
77// SomeFunction
78//----------------------------------------------------------------------
79static void HandleCrash(int signal)
80{
81  // We do not want to execute this function more than once in application life-time
82  static bool called = false;
83  if (called)
84  {
85    return;
86  }
87  called = true;
88
89  rrlib::thread::tThread& t = rrlib::thread::tThread::CurrentThread();
90  const char* signal_string = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
91  std::cout << std::endl << "\033[;1;31m************************************************************************" << std::endl;
92  if (&t) // Should always be the case. However, you never know if application has crashed.
93  {
94    std::cout << "Thread '" << t.GetName() << "' (" << (void*)t.GetNativeHandle() << ") just did something bad (" << signal_string << ") and crashed your program." << std::endl;
95  }
96  else
97  {
98    std::cout << "Something bad happened and crashed your program (" << signal_string << ")." << std::endl;
99  }
100  std::cout << "Would you like to start gdb to inquire what happened (y/n)?" << std::endl << std::endl;
101  std::cout << "Important gdb commands:" << std::endl;
102  std::cout << "  'info threads'      shows all running threads" << std::endl;
103  std::cout << "  'thread <threadno>' selects thread" << std::endl;
104  std::cout << "  'bt [full]'         prints stack trace" << std::endl << std::endl;
105  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;
106  std::cout << "************************************************************************\033[;0m" << std::endl;
107  char answer;
108  std::cin >> answer;
109  if (answer == 'y' || answer == 'Y')
110  {
111    pid_t pid = getpid();
112    prctl(PR_SET_PTRACER, pid, 0, 0, 0); // Allows a gdb child process to attach
113    std::ostringstream pidstr;
114    pidstr << pid;
115    char binary_name[1024];
116    int chars = readlink("/proc/self/exe", binary_name, 1013);
117    binary_name[chars] = 0;
118    pid_t child = fork();
119    if (!child)
120    {
121      execlp("gdb", "gdb", binary_name, pidstr.str().c_str(), NULL);
122      abort(); // If we could not start gdb
123    }
124    else
125    {
126      waitpid(child, NULL, 0);
127    }
128  }
129}
130
131bool InstallCrashHandler()
132{
133  //rrlib::thread::tThread::CurrentThread().SetName("Main"); // Names process "Main", too
134
135  struct sigaction signal_action;
136  signal_action.sa_handler = HandleCrash;
137  sigemptyset(&signal_action.sa_mask);
138  signal_action.sa_flags = 0;
139
140  if (sigaction(SIGABRT, &signal_action, NULL) != 0)
141  {
142    perror("Could not install signal handler for SIGABRT");
143    return false;
144  }
145  if (sigaction(SIGSEGV, &signal_action, NULL) != 0)
146  {
147    perror("Could not install signal handler for SIGSEGV");
148    return false;
149  }
150
151  return true;
152}
153
154//----------------------------------------------------------------------
155// End of namespace declaration
156//----------------------------------------------------------------------
157}
158}
Note: See TracBrowser for help on using the repository browser.