Browse Source

Simplify longpoll changeover to just check which pool it should grab its next longpoll from. This should prevent locking hangs and thread cancellation

crashes.
nfactor-troky
Con Kolivas 13 years ago
parent
commit
2257b5023a
  1. 62
      main.c
  2. 1
      miner.h
  3. 5
      util.c

62
main.c

@ -2732,8 +2732,6 @@ static struct pool *priority_pool(int choice)
return ret; return ret;
} }
static void restart_longpoll(void);
static void switch_pools(struct pool *selected) static void switch_pools(struct pool *selected)
{ {
struct pool *pool, *last_pool; struct pool *pool, *last_pool;
@ -2786,12 +2784,8 @@ static void switch_pools(struct pool *selected)
pool = currentpool; pool = currentpool;
mutex_unlock(&control_lock); mutex_unlock(&control_lock);
if (pool != last_pool) { if (pool != last_pool)
applog(LOG_WARNING, "Switching to %s", pool->rpc_url); 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 */ /* Reset the queued amount to allow more to be queued for the new pool */
mutex_lock(&qd_lock); mutex_lock(&qd_lock);
@ -3395,6 +3389,9 @@ retry:
opt_loginput = false; opt_loginput = false;
} }
static void start_longpoll(void);
static void stop_longpoll(void);
static void set_options(void) static void set_options(void)
{ {
int selected; int selected;
@ -3421,7 +3418,11 @@ retry:
} else if (!strncasecmp(&input, "l", 1)) { } else if (!strncasecmp(&input, "l", 1)) {
want_longpoll ^= true; want_longpoll ^= true;
applog(LOG_WARNING, "Longpoll %s", want_longpoll ? "enabled" : "disabled"); applog(LOG_WARNING, "Longpoll %s", want_longpoll ? "enabled" : "disabled");
restart_longpoll(); if (!want_longpoll) {
if (have_longpoll)
stop_longpoll();
} else
start_longpoll();
goto retry; goto retry;
} else if (!strncasecmp(&input, "s", 1)) { } else if (!strncasecmp(&input, "s", 1)) {
selected = curses_int("Set scantime in seconds"); selected = curses_int("Set scantime in seconds");
@ -4898,12 +4899,15 @@ static struct pool *select_longpoll_pool(void)
static void *longpoll_thread(void *userdata) static void *longpoll_thread(void *userdata)
{ {
struct thr_info *mythr = userdata;
CURL *curl = NULL;
char *copy_start, *hdr_path, *lp_url = NULL; char *copy_start, *hdr_path, *lp_url = NULL;
struct thr_info *mythr = userdata;
struct timeval start, end;
bool need_slash = false; bool need_slash = false;
struct pool *sp, *pool;
CURL *curl = NULL;
int failures = 0; int failures = 0;
struct pool *pool; bool rolltime;
json_t *val;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_detach(pthread_self()); pthread_detach(pthread_self());
@ -4915,7 +4919,9 @@ static void *longpoll_thread(void *userdata)
} }
tq_pop(mythr->q, NULL); tq_pop(mythr->q, NULL);
pool = select_longpoll_pool(); pool = select_longpoll_pool();
new_longpoll:
if (!pool->hdr_path) { if (!pool->hdr_path) {
applog(LOG_WARNING, "No long-poll found on any pool server"); applog(LOG_WARNING, "No long-poll found on any pool server");
goto out; goto out;
@ -4926,15 +4932,13 @@ static void *longpoll_thread(void *userdata)
if (strstr(hdr_path, "://")) { if (strstr(hdr_path, "://")) {
lp_url = hdr_path; lp_url = hdr_path;
hdr_path = NULL; hdr_path = NULL;
} } else {
/* absolute path, on current server */
/* absolute path, on current server */
else {
copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path; copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path;
if (pool->rpc_url[strlen(pool->rpc_url) - 1] != '/') if (pool->rpc_url[strlen(pool->rpc_url) - 1] != '/')
need_slash = true; 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) if (!lp_url)
goto out; goto out;
@ -4945,10 +4949,6 @@ static void *longpoll_thread(void *userdata)
applog(LOG_WARNING, "Long-polling activated for %s", lp_url); applog(LOG_WARNING, "Long-polling activated for %s", lp_url);
while (1) { while (1) {
struct timeval start, end;
bool rolltime;
json_t *val;
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
val = json_rpc_call(curl, lp_url, pool->rpc_userpass, rpc_req, val = json_rpc_call(curl, lp_url, pool->rpc_userpass, rpc_req,
false, true, &rolltime, pool); false, true, &rolltime, pool);
@ -4965,26 +4965,28 @@ static void *longpoll_thread(void *userdata)
if (end.tv_sec - start.tv_sec > 30) if (end.tv_sec - start.tv_sec > 30)
continue; continue;
if (opt_retries == -1 || failures++ < opt_retries) { if (opt_retries == -1 || failures++ < opt_retries) {
sleep(30);
applog(LOG_WARNING, applog(LOG_WARNING,
"longpoll failed for %s, sleeping for 30s", lp_url); "longpoll failed for %s, sleeping for 30s", lp_url);
sleep(30);
} else { } else {
applog(LOG_ERR, applog(LOG_ERR,
"longpoll failed for %s, ending thread", lp_url); "longpoll failed for %s, ending thread", lp_url);
goto out; goto out;
} }
} }
sp = select_longpoll_pool();
if (sp != pool) {
if (likely(lp_url))
free(lp_url);
pool = sp;
goto new_longpoll;
}
} }
out: out:
if (curl) if (curl)
curl_easy_cleanup(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); tq_freeze(mythr->q);
return NULL; return NULL;
} }
@ -5010,14 +5012,6 @@ static void start_longpoll(void)
tq_push(thr_info[longpoll_thr_id].q, &ping); 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) static void *reinit_cpu(void *userdata)
{ {
pthread_detach(pthread_self()); pthread_detach(pthread_self());

1
miner.h

@ -453,7 +453,6 @@ extern int total_getworks, total_stale, total_discarded;
extern unsigned int local_work; extern unsigned int local_work;
extern unsigned int total_go, total_ro; extern unsigned int total_go, total_ro;
extern int opt_log_interval; extern int opt_log_interval;
extern pthread_mutex_t control_lock;
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
typedef struct { typedef struct {

5
util.c

@ -669,9 +669,7 @@ int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (
{ {
int ret; int ret;
mutex_lock(&control_lock);
ret = pthread_create(&thr->pth, attr, start, arg); ret = pthread_create(&thr->pth, attr, start, arg);
mutex_unlock(&control_lock);
return ret; return ret;
} }
@ -683,14 +681,11 @@ void thr_info_cancel(struct thr_info *thr)
if (thr->q) if (thr->q)
tq_freeze(thr->q); tq_freeze(thr->q);
/* control_lock protects thr->pth */
mutex_lock(&control_lock);
if (thr->pth) { if (thr->pth) {
if (!pthread_cancel(thr->pth)) if (!pthread_cancel(thr->pth))
pthread_join(thr->pth, NULL); pthread_join(thr->pth, NULL);
thr->pth = 0L; thr->pth = 0L;
} }
mutex_unlock(&control_lock);
} }
bool get_dondata(char **url, char **userpass) bool get_dondata(char **url, char **userpass)

Loading…
Cancel
Save