Cleaned up crash catcher, fixed missing <math.h> include

Fri, 18 Nov 2016 02:56:53 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Fri, 18 Nov 2016 02:56:53 +0200
changeset 1058
695edd4f0411
parent 1057
3c7782ec3753
child 1059
7800dbb00632

Cleaned up crash catcher, fixed missing <math.h> include

src/basics.h file | annotate | diff | comparison | revisions
src/crashCatcher.cpp file | annotate | diff | comparison | revisions
src/crashCatcher.h file | annotate | diff | comparison | revisions
src/format.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
tools/linelength.py file | annotate | diff | comparison | revisions
--- a/src/basics.h	Thu Nov 17 14:12:59 2016 +0200
+++ b/src/basics.h	Fri Nov 18 02:56:53 2016 +0200
@@ -23,6 +23,7 @@
 #include <QMetaType>
 #include <QVector3D>
 #include <functional>
+#include <math.h>
 #include "macros.h"
 #include "transform.h"
 #include "types/matrix.h"
--- a/src/crashCatcher.cpp	Thu Nov 17 14:12:59 2016 +0200
+++ b/src/crashCatcher.cpp	Fri Nov 18 02:56:53 2016 +0200
@@ -21,8 +21,8 @@
 #ifdef Q_OS_UNIX
 # include <QProcess>
 # include <QTemporaryFile>
+# include <signal.h>
 # include <unistd.h>
-# include <signal.h>
 # include "crashCatcher.h"
 # include "dialogs.h"
 
@@ -30,74 +30,92 @@
 #  include <sys/prctl.h>
 # endif
 
-
-// Removes the signal handler from SIGABRT and then aborts.
+/*
+ * finalAbort
+ *
+ * Removes the signal handler from SIGABRT and then aborts.
+ * This really aborts instead of falling back into the crash handler.
+ */
+//
 static void finalAbort()
 {
 	struct sigaction sighandler;
 	sighandler.sa_handler = SIG_DFL;
 	sighandler.sa_flags = 0;
-	sigaction (SIGABRT, &sighandler, 0);
+	sigaction(SIGABRT, &sighandler, 0);
 	abort();
 }
 
-
-static void handleCrash (int sig)
+/*
+ * handleCrash
+ *
+ * Handles a crash signal. Launches gdb and gets debug info for a post-mortem.
+ */
+static void handleCrash(int signal)
 {
 	static bool isActive = false;
-	printf ("!! Caught signal %d, launching gdb\n", sig);
+	printf("!! Caught signal %d, launching gdb\n", signal);
 
 	if (isActive)
 	{
-		printf ("Caught signal while crash catcher is active! Execution cannot continue.\n");
+		printf("Caught signal while crash catcher is active! Execution cannot continue.\n");
 		finalAbort();
 	}
 
-	pid_t const pid (getpid());
-	QProcess proc;
 	QTemporaryFile commandsFile;
 	isActive = true;
 
 	if (commandsFile.open())
 	{
-		commandsFile.write (format ("attach %1\n", pid).toLocal8Bit());
-		commandsFile.write (QString ("backtrace full\n").toLocal8Bit());
-		commandsFile.write (QString ("detach\n").toLocal8Bit());
-		commandsFile.write (QString ("quit").toLocal8Bit());
+		commandsFile.write(format("attach %1\n", getpid()).toLocal8Bit());
+		commandsFile.write("backtrace full\n");
+		commandsFile.write("detach\n");
+		commandsFile.write("quit");
 		commandsFile.close();
+
+		QProcess process;
+		process.start("gdb", {"-x", commandsFile.fileName()});
+
+		// Linux doesn't allow ptrace to be used on anything but direct child processes, so we need to use prctl to register an exception
+		// to this to allow GDB attach to us.
+#ifdef Q_OS_LINUX
+		prctl(PR_SET_PTRACER, process.pid(), 0, 0, 0);
+#endif
+
+		process.waitForFinished(1000);
+		QString output = process.readAllStandardOutput();
+		QString errorOutput = process.readAllStandardError();
+		QFile file {UNIXNAME "-crash.log"};
+
+		if (file.open(QIODevice::WriteOnly))
+		{
+			fprint(file, format("=== Program crashed with signal %1 ===\n\n"
+			                    "GDB stdout:\n%3\nGDB stderr:\n%4\n", signal, output, errorOutput));
+			file.close();
+			printf("Backtrace written to " UNIXNAME "-crash.log. Aborting.\n");
+		}
+		else
+		{
+			printf("Unable to write a crashlog.\n");
+		}
+	}
+	else
+	{
+		printf("Unable to write commands to temporary file.");
 	}
 
-	proc.start ("gdb", {"-x", commandsFile.fileName()});
-
-	// Linux doesn't allow ptrace to be used on anything but direct child processes
-	// so we need to use prctl to register an exception to this to allow GDB attach to us.
-	// We need to do this now and no earlier because only now we actually know GDB's PID.
-#ifdef Q_OS_LINUX
-	prctl (PR_SET_PTRACER, proc.pid(), 0, 0, 0);
-#endif
-
-	proc.waitForFinished (1000);
-	QString output (proc.readAllStandardOutput());
-	QString err (proc.readAllStandardError());
-	QFile f (UNIXNAME "-crash.log");
-
-	if (f.open (QIODevice::WriteOnly))
-	{
-		fprint (f, format ("=== Program crashed with signal %1 ===\n\n"
-			"GDB stdout:\n%3\nGDB stderr:\n%4\n", sig,
-			output, err));
-		f.close();
-	}
-
-	printf ("Backtrace written to " UNIXNAME "-crash.log. Aborting.\n");
 	finalAbort();
 }
 
-
-void initCrashCatcher()
+/*
+ * initializeCrashHandler
+ *
+ * Creates handlers for crash signals, so that we can create backtraces for them.
+ */
+void initializeCrashHandler()
 {
 	// List of signals to catch and crash on
-	static const int signalsToCatch[] = {
+	QVector<int> signalsToCatch = {
 		SIGSEGV, // segmentation fault
 		SIGABRT, // abort() calls
 		SIGFPE, // floating point exceptions (e.g. division by zero)
@@ -109,13 +127,13 @@
 	sighandler.sa_flags = 0;
 	sigemptyset (&sighandler.sa_mask);
 
-	for (int sig : signalsToCatch)
+	for (int signal : signalsToCatch)
 	{
-		if (sigaction (sig, &sighandler, nullptr) == -1)
-			fprint (stderr, "Couldn't set signal handler %1: %2", sig, strerror (errno));
+		if (sigaction(signal, &sighandler, nullptr) == -1)
+			fprint(stderr, "Couldn't set signal handler %1: %2", signal, strerror(errno));
 	}
 
-	print ("Crash catcher hooked to signals: %1\n", signalsToCatch);
+	print("Crash catcher hooked to signals: %1\n", signalsToCatch);
 }
 
-#endif // Q_OS_UNIX
\ No newline at end of file
+#endif // Q_OS_UNIX
--- a/src/crashCatcher.h	Thu Nov 17 14:12:59 2016 +0200
+++ b/src/crashCatcher.h	Fri Nov 18 02:56:53 2016 +0200
@@ -20,7 +20,7 @@
 #include "main.h"
 
 #ifdef Q_OS_UNIX
-void initCrashCatcher();
+void initializeCrashHandler();
 #else
-void initCrashCatcher() {}
+void initializeCrashHandler() {}
 #endif
--- a/src/format.h	Thu Nov 17 14:12:59 2016 +0200
+++ b/src/format.h	Fri Nov 18 02:56:53 2016 +0200
@@ -46,7 +46,7 @@
 	}
 
 	template<typename T>
-	StringFormatArg (const QList<T>& a)
+	StringFormatArg (const QVector<T>& a)
 	{
 		m_text = "{";
 
--- a/src/main.cpp	Thu Nov 17 14:12:59 2016 +0200
+++ b/src/main.cpp	Fri Nov 18 02:56:53 2016 +0200
@@ -43,7 +43,7 @@
 	paths->checkPaths();
 	paths->deleteLater();
 
-	initCrashCatcher();
+	initializeCrashHandler();
 	initColors();
 	MainWindow* win = new MainWindow(configObject);
 	win->show();
--- a/tools/linelength.py	Thu Nov 17 14:12:59 2016 +0200
+++ b/tools/linelength.py	Fri Nov 18 02:56:53 2016 +0200
@@ -5,7 +5,7 @@
 for filename in argv[1:]:
 	with open(filename, 'r') as fp:
 		try:
-			exceeders = [(i + 1) for i, ln in enumerate(fp.read().splitlines()) if len(ln.replace('\t', '    ')) > 120]
+			exceeders = [(i + 1) for i, ln in enumerate(fp.read().splitlines()) if len(ln.replace('\t', '    ')) > 140]
 
 			for linenumber in exceeders:
 				stderr.write('%s:%d: warning: line length exceeds 120 characters\n' % (realpath(filename), linenumber))

mercurial