From 2257b5023a96c60c1adcdd89c8adbf60aa484ac5 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 27 Dec 2011 11:37:30 +1100 Subject: [PATCH] Simplify longpoll changeover to just check which pool it should grab its next longpoll from. This should prevent locking hangs and thread cancellation crashes. --- main.c | 62 ++++++++++++++++++++++++++------------------------------- miner.h | 1 - util.c | 5 ----- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/main.c b/main.c index 0da60785..14509dd1 100644 --- a/main.c +++ b/main.c @@ -2732,8 +2732,6 @@ static struct pool *priority_pool(int choice) return ret; } -static void restart_longpoll(void); - static void switch_pools(struct pool *selected) { struct pool *pool, *last_pool; @@ -2786,12 +2784,8 @@ static void switch_pools(struct pool *selected) pool = currentpool; mutex_unlock(&control_lock); - if (pool != last_pool) { + if (pool != last_pool) applog(LOG_WARNING, "Switching to %s", pool->rpc_url); - /* Only switch longpoll if the new pool also supports LP */ - if (pool->hdr_path) - restart_longpoll(); - } /* Reset the queued amount to allow more to be queued for the new pool */ mutex_lock(&qd_lock); @@ -3395,6 +3389,9 @@ retry: opt_loginput = false; } +static void start_longpoll(void); +static void stop_longpoll(void); + static void set_options(void) { int selected; @@ -3421,7 +3418,11 @@ retry: } else if (!strncasecmp(&input, "l", 1)) { want_longpoll ^= true; applog(LOG_WARNING, "Longpoll %s", want_longpoll ? "enabled" : "disabled"); - restart_longpoll(); + if (!want_longpoll) { + if (have_longpoll) + stop_longpoll(); + } else + start_longpoll(); goto retry; } else if (!strncasecmp(&input, "s", 1)) { selected = curses_int("Set scantime in seconds"); @@ -4898,12 +4899,15 @@ static struct pool *select_longpoll_pool(void) static void *longpoll_thread(void *userdata) { - struct thr_info *mythr = userdata; - CURL *curl = NULL; char *copy_start, *hdr_path, *lp_url = NULL; + struct thr_info *mythr = userdata; + struct timeval start, end; bool need_slash = false; + struct pool *sp, *pool; + CURL *curl = NULL; int failures = 0; - struct pool *pool; + bool rolltime; + json_t *val; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_detach(pthread_self()); @@ -4915,7 +4919,9 @@ static void *longpoll_thread(void *userdata) } tq_pop(mythr->q, NULL); + pool = select_longpoll_pool(); +new_longpoll: if (!pool->hdr_path) { applog(LOG_WARNING, "No long-poll found on any pool server"); goto out; @@ -4926,15 +4932,13 @@ static void *longpoll_thread(void *userdata) if (strstr(hdr_path, "://")) { lp_url = hdr_path; hdr_path = NULL; - } - - /* absolute path, on current server */ - else { + } else { + /* absolute path, on current server */ copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path; if (pool->rpc_url[strlen(pool->rpc_url) - 1] != '/') need_slash = true; - lp_url = alloca(strlen(pool->rpc_url) + strlen(copy_start) + 2); + lp_url = malloc(strlen(pool->rpc_url) + strlen(copy_start) + 2); if (!lp_url) goto out; @@ -4945,10 +4949,6 @@ static void *longpoll_thread(void *userdata) applog(LOG_WARNING, "Long-polling activated for %s", lp_url); while (1) { - struct timeval start, end; - bool rolltime; - json_t *val; - gettimeofday(&start, NULL); val = json_rpc_call(curl, lp_url, pool->rpc_userpass, rpc_req, false, true, &rolltime, pool); @@ -4965,26 +4965,28 @@ static void *longpoll_thread(void *userdata) if (end.tv_sec - start.tv_sec > 30) continue; if (opt_retries == -1 || failures++ < opt_retries) { - sleep(30); applog(LOG_WARNING, "longpoll failed for %s, sleeping for 30s", lp_url); + sleep(30); } else { applog(LOG_ERR, "longpoll failed for %s, ending thread", lp_url); goto out; } } + sp = select_longpoll_pool(); + if (sp != pool) { + if (likely(lp_url)) + free(lp_url); + pool = sp; + goto new_longpoll; + } } out: if (curl) curl_easy_cleanup(curl); - /* Wait indefinitely if longpoll is flagged as existing, thus making - * this thread only die if killed from elsewhere, usually in - * thr_info_cancel */ - if (have_longpoll) - tq_pop(mythr->q, NULL); tq_freeze(mythr->q); return NULL; } @@ -5010,14 +5012,6 @@ static void start_longpoll(void) tq_push(thr_info[longpoll_thr_id].q, &ping); } -static void restart_longpoll(void) -{ - if (have_longpoll) - stop_longpoll(); - if (want_longpoll) - start_longpoll(); -} - static void *reinit_cpu(void *userdata) { pthread_detach(pthread_self()); diff --git a/miner.h b/miner.h index 61010061..1a831588 100644 --- a/miner.h +++ b/miner.h @@ -453,7 +453,6 @@ extern int total_getworks, total_stale, total_discarded; extern unsigned int local_work; extern unsigned int total_go, total_ro; extern int opt_log_interval; -extern pthread_mutex_t control_lock; #ifdef HAVE_OPENCL typedef struct { diff --git a/util.c b/util.c index f3287bc3..3df1fb34 100644 --- a/util.c +++ b/util.c @@ -669,9 +669,7 @@ int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) ( { int ret; - mutex_lock(&control_lock); ret = pthread_create(&thr->pth, attr, start, arg); - mutex_unlock(&control_lock); return ret; } @@ -683,14 +681,11 @@ void thr_info_cancel(struct thr_info *thr) if (thr->q) tq_freeze(thr->q); - /* control_lock protects thr->pth */ - mutex_lock(&control_lock); if (thr->pth) { if (!pthread_cancel(thr->pth)) pthread_join(thr->pth, NULL); thr->pth = 0L; } - mutex_unlock(&control_lock); } bool get_dondata(char **url, char **userpass)