From 2cae5c1dc3884deb35430cf6af4d192666ac01c4 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 15 Sep 2011 14:51:04 +1000 Subject: [PATCH] Restart longpoll under lock when we'll be reusing it on pool switch to prevent derefs. --- main.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 11d8b97e..9edc01db 100644 --- a/main.c +++ b/main.c @@ -2455,11 +2455,12 @@ static struct pool *priority_pool(int choice) return ret; } -static void restart_longpoll(void); +static void __restart_longpoll(void); static void switch_pools(struct pool *selected) { struct pool *pool, *last_pool; + bool new_pool = false; int i, pool_no; mutex_lock(&control_lock); @@ -2507,13 +2508,23 @@ static void switch_pools(struct pool *selected) currentpool = pools[pool_no]; pool = currentpool; - mutex_unlock(&control_lock); if (pool != last_pool) { - applog(LOG_WARNING, "Switching to %s", pool->rpc_url); + new_pool = true; /* Only switch longpoll if the new pool also supports LP */ if (pool->hdr_path) - restart_longpoll(); + __restart_longpoll(); + } + + mutex_unlock(&control_lock); + + if (new_pool) { + applog(LOG_WARNING, "Switching to %s", pool->rpc_url); + if (want_longpoll) { + if (opt_debug) + applog(LOG_DEBUG, "Pushing ping to longpoll thread"); + tq_push(thr_info[longpoll_thr_id].q, &ping); + } } /* Reset the queued amount to allow more to be queued for the new pool */ @@ -3003,6 +3014,8 @@ retry: opt_loginput = false; } +static void restart_longpoll(void); + static void set_options(void) { int selected; @@ -4472,6 +4485,23 @@ static void restart_longpoll(void) start_longpoll(); } +/* Version for when we are holding a lock, grabs no other locks to prevent + * deadlock */ +static void __restart_longpoll(void) +{ + struct thr_info *thr = &thr_info[longpoll_thr_id]; + + thr_info_cancel(thr); + have_longpoll = false; + + if (!want_longpoll) + return; + + tq_thaw(thr->q); + if (unlikely(thr_info_create(thr, NULL, longpoll_thread, thr))) + quit(1, "longpoll thread create failed"); +} + static void *reinit_cpu(void *userdata) { pthread_detach(pthread_self());