src/crashcatcher.cpp

changeset 514
d78fea0f664c
parent 513
29eb671b34f6
child 528
e38d199ef9aa
equal deleted inserted replaced
513:29eb671b34f6 514:d78fea0f664c
25 SIGILL, // illegal instructions 25 SIGILL, // illegal instructions
26 }); 26 });
27 27
28 // ============================================================================= 28 // =============================================================================
29 // ----------------------------------------------------------------------------- 29 // -----------------------------------------------------------------------------
30 static void handleSignal (int sig) 30 static void handleCrash (int sig)
31 { printf ("caught signal %d\n", sig); 31 { printf ("%s: crashed with signal %d, launching gdb\n", __func__, sig);
32 32
33 if (g_crashCatcherActive) 33 if (g_crashCatcherActive)
34 { printf ("caught signal while crash catcher is active!\n"); 34 { printf ("caught signal while crash catcher is active!\n");
35 return; 35 return;
36 } 36 }
37 37
38 if (g_signalsToCatch.indexOf (sig) != -1) 38 const pid_t pid = getpid();
39 { const pid_t pid = getpid(); 39 QProcess proc;
40 QProcess proc; 40 QTemporaryFile commandsFile;
41 QTemporaryFile commandsFile;
42 41
43 g_crashCatcherActive = true; 42 g_crashCatcherActive = true;
44 printf ("%s: crashed with signal %d, launching gdb\n", __func__, sig);
45 43
46 if (commandsFile.open()) 44 if (commandsFile.open())
47 { commandsFile.write (fmt ("attach %1\n", pid).toLocal8Bit()); 45 { commandsFile.write (fmt ("attach %1\n", pid).toLocal8Bit());
48 commandsFile.write (str ("backtrace full\n").toLocal8Bit()); 46 commandsFile.write (str ("backtrace full\n").toLocal8Bit());
49 commandsFile.write (str ("detach\n").toLocal8Bit()); 47 commandsFile.write (str ("detach\n").toLocal8Bit());
50 commandsFile.write (str ("quit").toLocal8Bit()); 48 commandsFile.write (str ("quit").toLocal8Bit());
51 commandsFile.flush(); 49 commandsFile.flush();
52 commandsFile.close(); 50 commandsFile.close();
53 } 51 }
54 52
55 QStringList args ({"-x", commandsFile.fileName()}); 53 QStringList args ({"-x", commandsFile.fileName()});
56 54
57 proc.start ("gdb", args); 55 proc.start ("gdb", args);
58 56
59 // Linux doesn't allow ptrace to be used on anything but direct child processes 57 // Linux doesn't allow ptrace to be used on anything but direct child processes
60 // so we need to use prctl to register an exception to this to allow GDB attach to us. 58 // so we need to use prctl to register an exception to this to allow GDB attach to us.
61 // We need to do this now and no earlier because only now we actually know GDB's PID. 59 // We need to do this now and no earlier because only now we actually know GDB's PID.
62 prctl (PR_SET_PTRACER, proc.pid(), 0, 0, 0); 60 prctl (PR_SET_PTRACER, proc.pid(), 0, 0, 0);
63 61
64 proc.waitForFinished (5000); 62 proc.waitForFinished (1000);
65 str output = QString (proc.readAllStandardOutput()); 63 str output = QString (proc.readAllStandardOutput());
66 str err = QString (proc.readAllStandardError()); 64 str err = QString (proc.readAllStandardError());
67 65
68 bombBox (fmt ("<h3>Program crashed with signal %1</h3>\n\n" 66 bombBox (fmt ("<h3>Program crashed with signal %1</h3>\n\n"
69 "%2" 67 "%2"
70 "<p><b>GDB <tt>stdout</tt>:</b></p><pre>%3</pre>\n" 68 "<p><b>GDB <tt>stdout</tt>:</b></p><pre>%3</pre>\n"
71 "<p><b>GDB <tt>stderr</tt>:</b></p><pre>%4</pre>", 69 "<p><b>GDB <tt>stderr</tt>:</b></p><pre>%4</pre>",
72 sig, (!g_assertionFailure.isEmpty()) ? g_assertionFailure : "", output, err)); 70 sig, (!g_assertionFailure.isEmpty()) ? g_assertionFailure : "", output, err));
73 exit (137);
74 }
75 } 71 }
76 72
77 // ============================================================================= 73 // =============================================================================
78 // ----------------------------------------------------------------------------- 74 // -----------------------------------------------------------------------------
79 void initCrashCatcher() 75 void initCrashCatcher()
80 { struct sigaction sighandler; 76 { struct sigaction sighandler;
81 sighandler.sa_handler = &handleSignal; 77 sighandler.sa_handler = &handleCrash;
82 sighandler.sa_flags = 0; 78 sighandler.sa_flags = 0;
83 sigemptyset (&sighandler.sa_mask); 79 sigemptyset (&sighandler.sa_mask);
84 80
85 for (int sig : g_signalsToCatch) 81 for (int sig : g_signalsToCatch)
86 sigaction (sig, &sighandler, null); 82 sigaction (sig, &sighandler, null);

mercurial