Commit 68c881fde72f7aa92224cf4e4ba67a5af868dafc

Con Kolivas 2012-10-23T20:17:10

Handle crash exceptions by trying to restart cgminer unless the --no-restart option is used.

diff --git a/README b/README
index 5dc3369..5d9e93a 100644
--- a/README
+++ b/README
@@ -153,6 +153,7 @@ Options for both config file and command line:
 --monitor|-m <arg>  Use custom pipe cmd for output messages
 --net-delay         Impose small delays in networking to not overload slow routers
 --no-pool-disable   Do not automatically disable pools that continually reject shares
+--no-restart        Do not attempt to restart GPUs that hang or cgminer if it crashes
 --no-submit-stale   Don't submit shares if they are detected as stale
 --pass|-p <arg>     Password for bitcoin JSON-RPC server
 --per-device-stats  Force verbose mode and output per-device statistics
@@ -203,7 +204,6 @@ GPU only options:
 --intensity|-I <arg> Intensity of GPU scanning (d or -10 -> 10, default: d to maintain desktop interactivity)
 --kernel|-k <arg>   Override kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated
 --ndevs|-n          Enumerate number of detected GPUs and exit
---no-restart        Do not attempt to restart GPUs that hang
 --temp-hysteresis <arg> Set how much the temperature can fluctuate outside limits when automanaging speeds (default: 3)
 --temp-overheat <arg> Overheat temperature when automatically managing fan and GPU speeds (default: 85)
 --temp-target <arg> Target temperature when automatically managing fan and GPU speeds (default: 75)
diff --git a/cgminer.c b/cgminer.c
index dfe449c..2cd1955 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -261,7 +261,7 @@ static int include_count;
 
 bool ping = true;
 
-struct sigaction termhandler, inthandler;
+struct sigaction termhandler, inthandler, segvhandler, bushandler, illhandler;
 
 struct thread_q *getq;
 
@@ -975,7 +975,7 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--no-restart",
 			opt_set_invbool, &opt_restart,
 #ifdef HAVE_OPENCL
-			"Do not attempt to restart GPUs that hang"
+			"Do not attempt to restart GPUs that hang or cgminer if it crashes"
 #else
 			opt_hidden
 #endif
@@ -2438,13 +2438,8 @@ char **initial_args;
 
 static void clean_up(void);
 
-void app_restart(void)
+static inline void __app_restart(void)
 {
-	applog(LOG_WARNING, "Attempting to restart %s", packagename);
-
-	__kill_work();
-	clean_up();
-
 #if defined(unix)
 	if (forkpid > 0) {
 		kill(forkpid, SIGTERM);
@@ -2453,17 +2448,55 @@ void app_restart(void)
 #endif
 
 	execv(initial_args[0], initial_args);
+}
+
+void app_restart(void)
+{
+	applog(LOG_WARNING, "Attempting to restart %s", packagename);
+
+	__kill_work();
+	clean_up();
+
+	__app_restart();
+
+	/* We shouldn't reach here */
 	applog(LOG_WARNING, "Failed to restart application");
 }
 
-static void sighandler(int __maybe_unused sig)
+/* Returns all signal handlers to their defaults */
+static inline void __sighandler(void)
 {
 	/* Restore signal handlers so we can still quit if kill_work fails */
 	sigaction(SIGTERM, &termhandler, NULL);
 	sigaction(SIGINT, &inthandler, NULL);
+	if (opt_restart) {
+		sigaction(SIGSEGV, &segvhandler, NULL);
+		sigaction(SIGILL, &illhandler, NULL);
+#ifndef WIN32
+		sigaction(SIGBUS, &bushandler, NULL);
+#endif
+	}
+}
+
+static void sighandler(int __maybe_unused sig)
+{
+	__sighandler();
 	kill_work();
 }
 
+/* Handles segfaults and other crashes by attempting to restart cgminer. Try to
+ * do as little as possible since we are probably corrupted. */
+static void seghandler(int sig)
+{
+	__sighandler();
+	fprintf(stderr, "\nCrashed with signal %d! Will attempt to restart\n", sig);
+	__app_restart();
+	/* We shouldn't reach here */
+	fprintf(stderr, "Failed to restart, exiting now\n");
+
+	exit(1);
+}
+
 /* Called with pool_lock held. Recruit an extra curl if none are available for
  * this pool. */
 static void recruit_curl(struct pool *pool)
@@ -6084,6 +6117,18 @@ int main(int argc, char *argv[])
 	if (!config_loaded)
 		load_default_config();
 
+	if (opt_restart) {
+		struct sigaction shandler;
+
+		shandler.sa_handler = &seghandler;
+		shandler.sa_flags = 0;
+		sigemptyset(&shandler.sa_mask);
+		sigaction(SIGSEGV, &shandler, &segvhandler);
+		sigaction(SIGILL, &shandler, &illhandler);
+#ifndef WIN32
+		sigaction(SIGBUS, &shandler, &bushandler);
+#endif
+	}
 	if (opt_benchmark) {
 		struct pool *pool;