src/crashcatcher.cc

Wed, 08 Jan 2014 13:57:10 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Wed, 08 Jan 2014 13:57:10 +0200
changeset 608
487db37f0bb3
parent 606
3dd6f343ec06
permissions
-rw-r--r--

- if loading another file to replace an explicitly loaded file, this file won't get closed automatically and thus needs to be manually closed. We also need to check that it's safe to close before doing this. Also fixed a rather argh problem with ::save not using the proper path...

567
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
1 /*
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
2 * LDForge: LDraw parts authoring CAD
600
209e3f1f7b2c - updated copyright year. Best wishes for 2014!
Santeri Piippo <crimsondusk64@gmail.com>
parents: 567
diff changeset
3 * Copyright (C) 2013, 2014 Santeri Piippo
567
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
4 *
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
5 * This program is free software: you can redistribute it and/or modify
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
6 * it under the terms of the GNU General Public License as published by
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
7 * the Free Software Foundation, either version 3 of the License, or
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
8 * (at your option) any later version.
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
9 *
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
10 * This program is distributed in the hope that it will be useful,
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
13 * GNU General Public License for more details.
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
14 *
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
15 * You should have received a copy of the GNU General Public License
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
17 */
82101a296f9e - added file headers to crashcatcher.cc and .h
Santeri Piippo <crimsondusk64@gmail.com>
parents: 557
diff changeset
18
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
19 #ifdef __unix__
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
20
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
21 #include <QString>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
22 #include <QProcess>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
23 #include <QTemporaryFile>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
24 #include <QMessageBox>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
25 #include <unistd.h>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
26 #include <signal.h>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
27 #include <sys/prctl.h>
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
28 #include "crashcatcher.h"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
29 #include "types.h"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
30 #include "dialogs.h"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
31
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
32 // Is the crash catcher active now?
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
33 static bool g_crashCatcherActive = false;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
34
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
35 // If an assertion failed, what was it?
606
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
36 static QString g_assertionFailure;
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
37
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
38 // List of signals to catch and crash on
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
39 static QList<int> g_signalsToCatch ({
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
40 SIGSEGV, // segmentation fault
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
41 SIGABRT, // abort() calls
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
42 SIGFPE, // floating point exceptions (e.g. division by zero)
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
43 SIGILL, // illegal instructions
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
44 });
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
45
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
46 // =============================================================================
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
47 // -----------------------------------------------------------------------------
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
48 static void handleCrash (int sig)
603
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
49 {
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
50 printf ("%s: crashed with signal %d, launching gdb\n", __func__, sig);
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
51
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
52 if (g_crashCatcherActive)
603
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
53 {
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
54 printf ("caught signal while crash catcher is active!\n");
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
55 exit (149);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
56 }
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
57
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
58 const pid_t pid = getpid();
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
59 QProcess proc;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
60 QTemporaryFile commandsFile;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
61
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
62 g_crashCatcherActive = true;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
63
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
64 if (commandsFile.open())
603
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
65 {
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
66 commandsFile.write (fmt ("attach %1\n", pid).toLocal8Bit());
606
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
67 commandsFile.write (QString ("backtrace full\n").toLocal8Bit());
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
68 commandsFile.write (QString ("detach\n").toLocal8Bit());
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
69 commandsFile.write (QString ("quit").toLocal8Bit());
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
70 commandsFile.flush();
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
71 commandsFile.close();
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
72 }
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
73
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
74 QStringList args ({"-x", commandsFile.fileName()});
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
75
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
76 proc.start ("gdb", args);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
77
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
78 // Linux doesn't allow ptrace to be used on anything but direct child processes
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
79 // so we need to use prctl to register an exception to this to allow GDB attach to us.
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
80 // We need to do this now and no earlier because only now we actually know GDB's PID.
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
81 prctl (PR_SET_PTRACER, proc.pid(), 0, 0, 0);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
82
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
83 proc.waitForFinished (1000);
606
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
84 QString output = QString (proc.readAllStandardOutput());
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
85 QString err = QString (proc.readAllStandardError());
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
86
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
87 bombBox (fmt ("<h3>Program crashed with signal %1</h3>\n\n"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
88 "%2"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
89 "<p><b>GDB <tt>stdout</tt>:</b></p><pre>%3</pre>\n"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
90 "<p><b>GDB <tt>stderr</tt>:</b></p><pre>%4</pre>",
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
91 sig, (!g_assertionFailure.isEmpty()) ? g_assertionFailure : "", output, err));
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
92 }
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
93
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
94 // =============================================================================
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
95 // -----------------------------------------------------------------------------
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
96 void initCrashCatcher()
603
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
97 {
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
98 struct sigaction sighandler;
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
99 sighandler.sa_handler = &handleCrash;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
100 sighandler.sa_flags = 0;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
101 sigemptyset (&sighandler.sa_mask);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
102
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
103 for (int sig : g_signalsToCatch)
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
104 sigaction (sig, &sighandler, null);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
105
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
106 log ("%1: crash catcher hooked to signals: %2\n", __func__, g_signalsToCatch);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
107 }
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
108 #endif // #ifdef __unix__
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
109
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
110 // =============================================================================
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
111 // This function must be readily available in both Windows and Linux. We display
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
112 // the bomb box straight in Windows while in Linux we let abort() trigger the
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
113 // signal handler, which will cause the usual bomb box with GDB diagnostics.
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
114 // Said prompt will embed the assertion failure information.
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
115 // -----------------------------------------------------------------------------
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
116 void assertionFailure (const char* file, int line, const char* funcname, const char* expr)
603
47e7773c7841 - reformatting
Santeri Piippo <crimsondusk64@gmail.com>
parents: 600
diff changeset
117 {
606
3dd6f343ec06 - removed the 'str' typedef, use QString directly
Santeri Piippo <crimsondusk64@gmail.com>
parents: 603
diff changeset
118 QString errmsg = fmt (
557
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
119 "<p><b>File</b>: <tt>%1</tt><br />"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
120 "<b>Line</b>: <tt>%2</tt><br />"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
121 "<b>Function:</b> <tt>%3</tt></p>"
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
122 "<p>Assertion <b><tt>`%4'</tt></b> failed.</p>",
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
123 file, line, funcname, expr);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
124
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
125 g_assertionFailure = errmsg;
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
126
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
127 #ifndef __unix__
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
128 bombBox (errmsg);
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
129 #endif
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
130
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
131 abort();
04e140bdeb0b - changed source file extension from .cpp to .cc
Santeri Piippo <crimsondusk64@gmail.com>
parents:
diff changeset
132 }

mercurial