Implement signal handler and clean up properly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
diff --git a/main.c b/main.c
index 7a923c6..52d7587 100644
--- a/main.c
+++ b/main.c
@@ -24,6 +24,7 @@
#include <math.h>
#include <stdarg.h>
#include <assert.h>
+#include <signal.h>
#ifndef WIN32
#include <sys/resource.h>
#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;
}