From 20b3e07f63ef3b80e9817fb2d35573fc175a6d09 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 14 Jul 2011 11:03:14 +1000 Subject: [PATCH] Implement signal handler and clean up properly. --- main.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/main.c b/main.c index 7a923c66..52d75874 100644 --- a/main.c +++ b/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifndef WIN32 #include #endif @@ -153,6 +154,7 @@ struct thr_info *thr_info; static int work_thr_id; int longpoll_thr_id; static int stage_thr_id; +static int watchdog_thr_id; struct work_restart *work_restart = NULL; static pthread_mutex_t hash_lock; static pthread_mutex_t qd_lock; @@ -732,8 +734,29 @@ static void workio_cmd_free(struct workio_cmd *wc) static void kill_work(void) { struct workio_cmd *wc; + struct thr_info *thr; + unsigned int i; applog(LOG_INFO, "Received kill message"); + + /* Kill the watchdog thread */ + thr = &thr_info[watchdog_thr_id]; + pthread_cancel(thr->pth); + + /* Stop the mining threads*/ + for (i = 0; i < mining_threads; i++) { + thr = &thr_info[i]; + tq_freeze(thr->q); + /* No need to check if this succeeds or not */ + pthread_cancel(thr->pth); + } + + /* Stop the others */ + thr = &thr_info[stage_thr_id]; + pthread_cancel(thr->pth); + thr = &thr_info[longpoll_thr_id]; + pthread_cancel(thr->pth); + wc = calloc(1, sizeof(*wc)); if (unlikely(!wc)) { applog(LOG_ERR, "Failed to calloc wc in kill_work"); @@ -748,6 +771,34 @@ static void kill_work(void) applog(LOG_ERR, "Failed to tq_push work in kill_work"); exit (1); } + +} + +static void shutdown_cleanup(void) +{ + curl_global_cleanup(); + if (gpu_threads) { + gpu_threads = 0; + free(gpus); + } + if (opt_n_threads) { + opt_n_threads = 0; + free(cpus); + } + + if (curses_active) { + delwin(logwin); + delwin(statuswin); + delwin(mainwin); + endwin(); + refresh(); + curses_active = false; + } +} + +static void sighandler(int sig) +{ + kill_work(); } static void *get_work_thread(void *userdata) @@ -892,6 +943,8 @@ static void *stage_thread(void *userdata) struct thr_info *mythr = userdata; bool ok = true; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + while (ok) { struct work *work = NULL; char *hexstr; @@ -1658,6 +1711,8 @@ static void *longpoll_thread(void *userdata) bool need_slash = false; int failures = 0; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + hdr_path = tq_pop(mythr->q, NULL); if (!hdr_path) goto out; @@ -1831,6 +1886,8 @@ static void *watchdog_thread(void *userdata) const unsigned int interval = opt_log_interval / 2 ? : 1; struct timeval zero_tv; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + memset(&zero_tv, 0, sizeof(struct timeval)); while (1) { @@ -1880,8 +1937,9 @@ static void *watchdog_thread(void *userdata) int main (int argc, char *argv[]) { - struct thr_info *thr; unsigned int i, j = 0, x, y; + struct sigaction handler; + struct thr_info *thr; char name[256]; if (unlikely(pthread_mutex_init(&hash_lock, NULL))) @@ -1893,13 +1951,16 @@ int main (int argc, char *argv[]) if (unlikely(pthread_mutex_init(&curses_lock, NULL))) return 1; + handler.sa_handler = &sighandler; + sigaction(SIGTERM, &handler, 0); + sigaction(SIGINT, &handler, 0); + for (i = 0; i < 36; i++) { strcat(blank, "0"); strcat(current_block, "0"); strcat(longpoll_block, "0"); } - #ifdef WIN32 opt_n_threads = num_processors = 1; #else @@ -2122,7 +2183,8 @@ int main (int argc, char *argv[]) opt_n_threads, algo_names[opt_algo]); - thr = &thr_info[mining_threads + 2]; + watchdog_thr_id = mining_threads + 2; + thr = &thr_info[watchdog_thr_id]; /* start wakeup thread */ if (pthread_create(&thr->pth, NULL, watchdog_thread, NULL)) { applog(LOG_ERR, "wakeup thread create failed"); @@ -2161,20 +2223,9 @@ int main (int argc, char *argv[]) /* main loop - simply wait for workio thread to exit */ pthread_join(thr_info[work_thr_id].pth, NULL); - curl_global_cleanup(); - if (gpu_threads) - free(gpus); - if (opt_n_threads) - free(cpus); - applog(LOG_INFO, "workio thread dead, exiting."); - if (curses_active) { - delwin(logwin); - delwin(statuswin); - endwin(); - refresh(); - } + shutdown_cleanup(); return 0; }