Commit 833e020dfd3aee579da4e0015ea3fa5a319477ff

Con Kolivas 2011-09-15T10:33:23

Standardise the way all non-mining threads are destroyed to make sure we can safely cancel them, freeing ram and NULLifying pointers.

diff --git a/main.c b/main.c
index c6abeaf..b840bce 100644
--- a/main.c
+++ b/main.c
@@ -85,7 +85,6 @@ static inline void affine_to_cpu(int id, int cpu)
 enum workio_commands {
 	WC_GET_WORK,
 	WC_SUBMIT_WORK,
-	WC_DIE,
 };
 
 struct workio_cmd {
@@ -2252,62 +2251,41 @@ static void print_summary(void);
 
 void kill_work(void)
 {
-	struct workio_cmd *wc;
 	struct thr_info *thr;
 	unsigned int i;
 
 	disable_curses();
 	applog(LOG_INFO, "Received kill message");
 
+	if (opt_debug)
+		applog(LOG_DEBUG, "Killing off watchdog thread");
 	/* Kill the watchdog thread */
 	thr = &thr_info[watchdog_thr_id];
-	if (thr && thr->pth)
-		pthread_cancel(*thr->pth);
+	thr_info_cancel(thr);
 
+	if (opt_debug)
+		applog(LOG_DEBUG, "Killing off mining threads");
 	/* Stop the mining threads*/
 	for (i = 0; i < mining_threads; i++) {
 		thr = &thr_info[i];
-		if (!thr)
-			continue;
-		if (!thr->pth)
-			continue;
-		if (thr->q)
-			tq_freeze(thr->q);
-		/* No need to check if this succeeds or not */
-		pthread_cancel(*thr->pth);
+		thr_info_cancel(thr);
 	}
 
+	if (opt_debug)
+		applog(LOG_DEBUG, "Killing off stage thread");
 	/* Stop the others */
 	thr = &thr_info[stage_thr_id];
-	if (thr && thr->pth)
-		pthread_cancel(*thr->pth);
-	thr = &thr_info[longpoll_thr_id];
-	if (thr && thr->pth)
-		pthread_cancel(*thr->pth);
-
-	wc = calloc(1, sizeof(*wc));
-	if (unlikely(!wc)) {
-		applog(LOG_ERR, "Failed to calloc wc in kill_work");
-		/* We're just trying to die anyway, so forget graceful */
-		exit (1);
-	}
-
-	wc->cmd = WC_DIE;
-	wc->thr = 0;
+	thr_info_cancel(thr);
 
 	if (opt_debug)
-		applog(LOG_DEBUG, "Pushing die request to work thread");
+		applog(LOG_DEBUG, "Killing off longpoll thread");
+	thr = &thr_info[longpoll_thr_id];
+	thr_info_cancel(thr);
 
+	if (opt_debug)
+		applog(LOG_DEBUG, "Killing off work thread");
 	thr = &thr_info[work_thr_id];
-	if (thr) {
-		if (unlikely(!tq_push(thr->q, wc))) {
-			applog(LOG_ERR, "Failed to tq_push work in kill_work");
-			exit (1);
-		}
-
-		if (thr->pth)
-			pthread_cancel(*thr->pth);
-	}
+	thr_info_cancel(thr);
 }
 
 void quit(int status, const char *format, ...);
@@ -3315,7 +3293,6 @@ static void *workio_thread(void *userdata)
 		case WC_SUBMIT_WORK:
 			ok = workio_submit_work(wc);
 			break;
-		case WC_DIE:
 		default:
 			ok = false;
 			break;
@@ -4472,9 +4449,7 @@ static void stop_longpoll(void)
 {
 	struct thr_info *thr = &thr_info[longpoll_thr_id];
 
-	tq_freeze(thr->q);
-	if (thr->pth)
-		pthread_cancel(*thr->pth);
+	thr_info_cancel(thr);
 	have_longpoll = false;
 }
 
@@ -4482,7 +4457,7 @@ static void start_longpoll(void)
 {
 	struct thr_info *thr = &thr_info[longpoll_thr_id];
 
-	tq_thaw(thr->q);		
+	tq_thaw(thr->q);
 	if (unlikely(thr_info_create(thr, NULL, longpoll_thread, thr)))
 		quit(1, "longpoll thread create failed");
 	if (opt_debug)
@@ -4566,10 +4541,15 @@ select_cgpu:
 			continue;
 
 		thr = &thr_info[thr_id];
+		if (!thr) {
+			applog(LOG_WARNING, "No reference to thread %d exists", thr_id);
+			continue;
+		}
+
 		thr->rolling = thr->cgpu->rolling = 0;
 		/* Reports the last time we tried to revive a sick GPU */
 		gettimeofday(&thr->sick, NULL);
-		if (!pthread_cancel(*thr->pth)) {
+		if (thr->pth && !pthread_cancel(*thr->pth)) {
 			applog(LOG_WARNING, "Thread %d still exists, killing it off", thr_id);
 		} else
 			applog(LOG_WARNING, "Thread %d no longer exists", thr_id);
diff --git a/miner.h b/miner.h
index ce2a6b6..75c53ce 100644
--- a/miner.h
+++ b/miner.h
@@ -236,7 +236,8 @@ struct thr_info {
 	double	rolling;
 };
 
-extern inline int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
+extern int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
+extern void thr_info_cancel(struct thr_info *thr);
 
 static inline uint32_t swab32(uint32_t v)
 {
diff --git a/util.c b/util.c
index 5344586..aca9e81 100644
--- a/util.c
+++ b/util.c
@@ -653,18 +653,37 @@ out:
 	return rval;
 }
 
-inline int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg)
+int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg)
 {
-	int ret = 0;
-	
+	int ret = -1;
+
 	thr->pth = malloc(sizeof(pthread_t));
+	if (unlikely(!thr->pth)) {
+		applog(LOG_ERR, "Failed to malloc in thr_info_create");
+		return ret;
+	}
+
 	ret = pthread_create(thr->pth, attr, start, arg);
-	
 	if (unlikely(ret)) {
+		applog(LOG_ERR, "Failed to pthread_create in thr_info_create");
 		free(thr->pth);
-		thr->pth = 0;
+		thr->pth = NULL;
 	}
-	
+
 	return ret;
 }
 
+void thr_info_cancel(struct thr_info *thr)
+{
+	if (!thr)
+		return;
+
+	if (thr->q)
+		tq_freeze(thr->q);
+	if (thr->pth) {
+		if (pthread_cancel(*thr->pth))
+			pthread_join(*thr->pth, NULL);
+		free(thr->pth);
+		thr->pth = NULL;
+	}
+}