From 3b1e4b0f14d50a7a2fc5257bce57d3ae29fbd36d Mon Sep 17 00:00:00 2001
From: Chris Maffeo <cmaffeo2@illinois.edu>
Date: Thu, 21 Mar 2019 17:18:26 -0500
Subject: [PATCH] Added signal manager from Han-Yi

---
 src/Makefile          |  2 +-
 src/SignalManager.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++
 src/SignalManager.h   | 36 +++++++++++++++++++++++++++++++
 src/arbd.cpp          |  4 ++++
 4 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 src/SignalManager.cpp
 create mode 100644 src/SignalManager.h

diff --git a/src/Makefile b/src/Makefile
index a5c9573..af07565 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -21,7 +21,7 @@ else
 	VERSION:=unknown (not compiled in a git repository)
 endif
 endif
-CC_FLAGS += -DVERSION="\"$(VERSION)\""
+CC_FLAGS += -DVERSION="\"$(VERSION)\"" -DSIGNAL
 
 
 CC_FLAGS += -I$(CUDA_PATH)/include
diff --git a/src/SignalManager.cpp b/src/SignalManager.cpp
new file mode 100644
index 0000000..30b3688
--- /dev/null
+++ b/src/SignalManager.cpp
@@ -0,0 +1,49 @@
+#include "SignalManager.h"
+#include <cstdio>
+#include <cstdlib>
+#ifdef SIGNAL
+#include "common.h"
+//#include "ARBDException.h"
+
+void SignalManager::segfault_handler(int sig, siginfo_t *info, void *secret) 
+{
+    //comment out for now
+    //if(sig != SIGSEGV) 
+        //throw ARBDException("segfault_handler should handle segmentation faults only, got %d", sig);
+    void *trace[16];
+    char **messages = (char **) NULL;
+    int i, trace_size = 0;
+    ucontext_t *uc = (ucontext_t *) secret;
+    //write to stdout for now
+    fprintf(stdout, "Segmentation fault identified, faulty address is %p, from %p", info->si_addr, uc->uc_mcontext.gregs[MY_REG_RIP]);
+
+    trace_size = backtrace(trace, 16);
+    /* overwrite sigaction with caller's address */
+    trace[1] = (void *) uc->uc_mcontext.gregs[MY_REG_RIP];
+
+    messages = backtrace_symbols(trace, trace_size);
+    /* skip first stack frame (points here) */
+    
+    fprintf(stdout, "Execution path:");
+    for (i = 1; i < trace_size; ++i) 
+        fprintf(stdout, "\t[bt] %s\n", messages[i]);
+    //throw here or just exit ?
+    exit(0);
+}
+
+void SignalManager::manage_segfault() 
+{
+	struct sigaction sa;
+
+	sa.sa_sigaction = segfault_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART | SA_SIGINFO;
+
+	sigaction(SIGSEGV, &sa, NULL);
+}
+
+#else
+void SignalManager::segfault_handler(int sig, siginfo_t *info, void *secret) {}
+void SignalManager::manage_segfault() {}
+
+#endif
diff --git a/src/SignalManager.h b/src/SignalManager.h
new file mode 100644
index 0000000..2276cae
--- /dev/null
+++ b/src/SignalManager.h
@@ -0,0 +1,36 @@
+/*
+ * Some function in namespace to handle the
+ * signal of segmentation fault.
+ */
+
+#ifndef SIGNALMANAGER_H_
+#define SIGNALMANAGER_H_
+
+// see http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l3.html
+#include <csignal>
+#include <execinfo.h>
+
+#ifdef SIGNAL
+/* get REG_EIP from ucontext.h */
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
+#include <ucontext.h>
+
+#if __WORDSIZE == 64
+#define MY_REG_RIP REG_RIP
+#else
+#define MY_REG_RIP REG_EIP
+#endif
+#endif
+
+
+
+namespace SignalManager 
+{
+
+    void segfault_handler(int sig, siginfo_t *info, void *secret);
+    void manage_segfault();
+}
+
+#endif /* SIGNALMANAGER_H_ */
diff --git a/src/arbd.cpp b/src/arbd.cpp
index a120640..56b62ae 100644
--- a/src/arbd.cpp
+++ b/src/arbd.cpp
@@ -9,12 +9,16 @@
 #include "Configuration.h"
 #include "GPUManager.h"
 
+#include "SignalManager.h"
+
 // using namespace std;
 using std::max;
 
 const unsigned int kIMDPort = 71992;
 
 int main(int argc, char* argv[]) {
+    SignalManager::manage_segfault();
+
 	if (argc == 2 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) {
 		// --help
 		printf("Usage: %s [OPTIONS [ARGS]] CONFIGFILE OUTPUT [SEED]\n", argv[0]);
-- 
GitLab