diff --git a/README b/README index 5dc33695..5d9e93ad 100644 --- a/README +++ b/README @@ -153,6 +153,7 @@ Options for both config file and command line: --monitor|-m 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 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 Intensity of GPU scanning (d or -10 -> 10, default: d to maintain desktop interactivity) --kernel|-k 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 Set how much the temperature can fluctuate outside limits when automanaging speeds (default: 3) --temp-overheat Overheat temperature when automatically managing fan and GPU speeds (default: 85) --temp-target Target temperature when automatically managing fan and GPU speeds (default: 75) diff --git a/cgminer.c b/cgminer.c index dfe449c5..2cd19555 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;