From a5d526a67d39f78758070b06a364d593535b5908 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 29 Jul 2016 11:37:17 +1000 Subject: [PATCH 01/10] Delete parent proxies once all their subproxies are dead --- src/stratifier.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index d3efb0f2..a737fae7 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2727,6 +2727,11 @@ static void reap_proxies(ckpool_t *ckp, sdata_t *sdata) proxy->subproxy_count--; free_proxy(subproxy); } + /* Should we reap the parent proxy too?*/ + if (!proxy->dead || proxy->subproxy_count > 1 || proxy->bound_clients) + continue; + HASH_DELETE(hh, sdata->proxies, proxy); + free_proxy(proxy); } mutex_unlock(&sdata->proxy_lock); @@ -3414,12 +3419,13 @@ static void reconnect_client(sdata_t *sdata, stratum_instance_t *client) stratum_add_send(sdata, json_msg, client->id, SM_RECONNECT); } -static void dead_proxy(sdata_t *sdata, const char *buf) +static void dead_proxy(ckpool_t *ckp, sdata_t *sdata, const char *buf) { int id = 0, subid = 0; sscanf(buf, "deadproxy=%d:%d", &id, &subid); dead_proxyid(sdata, id, subid, false); + reap_proxies(ckp, sdata); } static void reconnect_client_id(sdata_t *sdata, const int64_t client_id) @@ -4108,7 +4114,7 @@ retry: } else if (cmdmatch(buf, "reconnect")) { request_reconnect(sdata, buf); } else if (cmdmatch(buf, "deadproxy")) { - dead_proxy(sdata, buf); + dead_proxy(ckp, sdata, buf); } else if (cmdmatch(buf, "loglevel")) { sscanf(buf, "loglevel=%d", &ckp->loglevel); } else if (cmdmatch(buf, "ckdbflush")) { From 14c8a3a125c83873beadc7a2fe8d465ab7f60281 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 29 Jul 2016 11:45:46 +1000 Subject: [PATCH 02/10] Add quiet mode option which suppresses throbber --- src/ckpool.c | 7 ++++++- src/ckpool.h | 3 +++ src/stratifier.c | 31 ++++++++++++++++--------------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 6f3eb99e..5d43d96a 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -1542,6 +1542,7 @@ static struct option long_options[] = { {"node", no_argument, 0, 'N'}, {"passthrough", no_argument, 0, 'P'}, {"proxy", no_argument, 0, 'p'}, + {"quiet", no_argument, 0, 'q'}, {"redirector", no_argument, 0, 'R'}, {"ckdb-sockdir",required_argument, 0, 'S'}, {"sockdir", required_argument, 0, 's'}, @@ -1563,6 +1564,7 @@ static struct option long_options[] = { {"node", no_argument, 0, 'N'}, {"passthrough", no_argument, 0, 'P'}, {"proxy", no_argument, 0, 'p'}, + {"quiet", no_argument, 0, 'q'}, {"redirector", no_argument, 0, 'R'}, {"sockdir", required_argument, 0, 's'}, {"trusted", no_argument, 0, 't'}, @@ -1610,7 +1612,7 @@ int main(int argc, char **argv) ckp.initial_args[ckp.args] = strdup(argv[ckp.args]); ckp.initial_args[ckp.args] = NULL; - while ((c = getopt_long(argc, argv, "Ac:Dd:g:HhkLl:Nn:PpRS:s:tu", long_options, &i)) != -1) { + while ((c = getopt_long(argc, argv, "Ac:Dd:g:HhkLl:Nn:PpqRS:s:tu", long_options, &i)) != -1) { switch (c) { case 'A': ckp.standalone = true; @@ -1679,6 +1681,9 @@ int main(int argc, char **argv) quit(1, "Cannot set another proxy type or redirector and proxy mode"); ckp.proxy = true; break; + case 'q': + ckp.quiet = true; + break; case 'R': if (ckp.proxy || ckp.passthrough || ckp.userproxy || ckp.node) quit(1, "Cannot set a proxy type or passthrough and redirector modes"); diff --git a/src/ckpool.h b/src/ckpool.h index 8596c8ec..520c6eb3 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -209,6 +209,9 @@ struct ckpool_instance { /* Should we daemonise the ckpool process */ bool daemon; + /* Should we disable the throbber */ + bool quiet; + /* Have we given warnings about the inability to raise buf sizes */ bool wmem_warn; bool rmem_warn; diff --git a/src/stratifier.c b/src/stratifier.c index a737fae7..8a23fa8f 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -777,30 +777,31 @@ out: static void _ckdbq_add(ckpool_t *ckp, const int idtype, json_t *val, const char *file, const char *func, const int line) { - static time_t time_counter; sdata_t *sdata = ckp->sdata; + static time_t time_counter; static int counter = 0; char *json_msg; - time_t now_t; - char ch; if (unlikely(!val)) { LOGWARNING("Invalid json sent to ckdbq_add from %s %s:%d", file, func, line); return; } - now_t = time(NULL); - if (now_t != time_counter) { - pool_stats_t *stats = &sdata->stats; - char hashrate[16]; - - /* Rate limit to 1 update per second */ - time_counter = now_t; - suffix_string(stats->dsps1 * nonces, hashrate, 16, 3); - ch = status_chars[(counter++) & 0x3]; - fprintf(stdout, "\33[2K\r%c %sH/s %.1f SPS %d users %d workers", - ch, hashrate, stats->sps1, stats->users, stats->workers); - fflush(stdout); + if (!ckp->quiet) { + time_t now_t = time(NULL); + + if (now_t != time_counter) { + pool_stats_t *stats = &sdata->stats; + char hashrate[16], ch; + + /* Rate limit to 1 update per second */ + time_counter = now_t; + suffix_string(stats->dsps1 * nonces, hashrate, 16, 3); + ch = status_chars[(counter++) & 0x3]; + fprintf(stdout, "\33[2K\r%c %sH/s %.1f SPS %d users %d workers", + ch, hashrate, stats->sps1, stats->users, stats->workers); + fflush(stdout); + } } if (CKP_STANDALONE(ckp)) From a5cb5339249c0e8d31568e0dee06e06411ce76d5 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 19 Jul 2016 11:23:08 +1000 Subject: [PATCH 03/10] Fix crash with proxy that has no subproxies --- src/generator.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/generator.c b/src/generator.c index 5d21ed03..33100bc6 100644 --- a/src/generator.c +++ b/src/generator.c @@ -2446,9 +2446,11 @@ static void delete_proxy(ckpool_t *ckp, gdata_t *gdata, proxy_instance_t *proxy) HASH_DELETE(sh, proxy->subproxies, subproxy); mutex_unlock(&proxy->proxy_lock); - send_stratifier_deadproxy(ckp, subproxy->id, subproxy->subid); - if (subproxy && proxy != subproxy) - store_proxy(gdata, subproxy); + if (subproxy) { + send_stratifier_deadproxy(ckp, subproxy->id, subproxy->subid); + if (proxy != subproxy) + store_proxy(gdata, subproxy); + } } while (subproxy); /* Recycle the proxy itself */ From ee17b24b9b17295c6cfc0c834cac8f66bfe4f0dd Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 29 Jul 2016 12:01:51 +1000 Subject: [PATCH 04/10] Differentiate a dead proxy from a deleted one --- src/generator.c | 15 ++++++++++++++- src/stratifier.c | 21 +++++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/generator.c b/src/generator.c index 33100bc6..2908421d 100644 --- a/src/generator.c +++ b/src/generator.c @@ -969,6 +969,9 @@ static void store_proxy(gdata_t *gdata, proxy_instance_t *proxy) mutex_unlock(&gdata->lock); } +/* The difference between a dead proxy and a deleted one is the parent proxy entry + * is not removed from the stratifier as it assumes it is down whereas a deleted + * proxy has had its entry removed from the generator. */ static void send_stratifier_deadproxy(ckpool_t *ckp, const int id, const int subid) { char buf[256]; @@ -979,6 +982,16 @@ static void send_stratifier_deadproxy(ckpool_t *ckp, const int id, const int sub send_proc(ckp->stratifier, buf); } +static void send_stratifier_delproxy(ckpool_t *ckp, const int id, const int subid) +{ + char buf[256]; + + if (ckp->passthrough) + return; + sprintf(buf, "delproxy=%d:%d", id, subid); + send_proc(ckp->stratifier, buf); +} + /* Remove the subproxy from the proxi list and put it on the dead list. * Further use of the subproxy pointer may point to a new proxy but will not * dereference. This will only disable subproxies so parent proxies need to @@ -2447,7 +2460,7 @@ static void delete_proxy(ckpool_t *ckp, gdata_t *gdata, proxy_instance_t *proxy) mutex_unlock(&proxy->proxy_lock); if (subproxy) { - send_stratifier_deadproxy(ckp, subproxy->id, subproxy->subid); + send_stratifier_delproxy(ckp, subproxy->id, subproxy->subid); if (proxy != subproxy) store_proxy(gdata, subproxy); } diff --git a/src/stratifier.c b/src/stratifier.c index 8a23fa8f..ace5284b 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -366,6 +366,7 @@ struct proxy_base { proxy_t *subproxies; /* Hashlist of subproxies sorted by subid */ sdata_t *sdata; /* Unique stratifer data for each subproxy */ bool dead; + bool deleted; }; typedef struct session session_t; @@ -2283,7 +2284,7 @@ static void check_bestproxy(sdata_t *sdata) LOGNOTICE("Stratifier setting active proxy to %d", changed_id); } -static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bool replaced) +static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bool replaced, const bool deleted) { stratum_instance_t *client, *tmp; int reconnects = 0, proxyid = 0; @@ -2293,6 +2294,7 @@ static void dead_proxyid(sdata_t *sdata, const int id, const int subid, const bo proxy = existing_subproxy(sdata, id, subid); if (proxy) { proxy->dead = true; + proxy->deleted = deleted; if (!replaced && proxy->global) check_bestproxy(sdata); } @@ -2374,7 +2376,7 @@ static void update_subscribe(ckpool_t *ckp, const char *cmd) /* Is this a replacement for an existing proxy id? */ old = existing_subproxy(sdata, id, subid); if (old) { - dead_proxyid(sdata, id, subid, true); + dead_proxyid(sdata, id, subid, true, false); proxy = old; proxy->dead = false; } else @@ -2729,7 +2731,7 @@ static void reap_proxies(ckpool_t *ckp, sdata_t *sdata) free_proxy(subproxy); } /* Should we reap the parent proxy too?*/ - if (!proxy->dead || proxy->subproxy_count > 1 || proxy->bound_clients) + if (!proxy->deleted || proxy->subproxy_count > 1 || proxy->bound_clients) continue; HASH_DELETE(hh, sdata->proxies, proxy); free_proxy(proxy); @@ -3425,7 +3427,16 @@ static void dead_proxy(ckpool_t *ckp, sdata_t *sdata, const char *buf) int id = 0, subid = 0; sscanf(buf, "deadproxy=%d:%d", &id, &subid); - dead_proxyid(sdata, id, subid, false); + dead_proxyid(sdata, id, subid, false, false); + reap_proxies(ckp, sdata); +} + +static void del_proxy(ckpool_t *ckp, sdata_t *sdata, const char *buf) +{ + int id = 0, subid = 0; + + sscanf(buf, "delproxy=%d:%d", &id, &subid); + dead_proxyid(sdata, id, subid, false, true); reap_proxies(ckp, sdata); } @@ -4116,6 +4127,8 @@ retry: request_reconnect(sdata, buf); } else if (cmdmatch(buf, "deadproxy")) { dead_proxy(ckp, sdata, buf); + } else if (cmdmatch(buf, "delproxy")) { + del_proxy(ckp, sdata, buf); } else if (cmdmatch(buf, "loglevel")) { sscanf(buf, "loglevel=%d", &ckp->loglevel); } else if (cmdmatch(buf, "ckdbflush")) { From aa4e2790e92cecc046e05457c6fae4b9e78a35c5 Mon Sep 17 00:00:00 2001 From: ckolivas Date: Mon, 1 Aug 2016 11:28:53 +1000 Subject: [PATCH 05/10] Drop and regain lock in statsupdate to minimise lock contention --- src/stratifier.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index ace5284b..9bfbadd7 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -7135,7 +7135,7 @@ static void *statsupdate(void *arg) tv_time(&now); timersub(&now, &stats->start_time, &diff); - /* Use this locking as an opportunity to test clients. */ + /* Test clients. */ ck_rlock(&sdata->instance_lock); HASH_ITER(hh, sdata->stratum_instances, client, tmp) { /* Look for clients that may have been dropped which the @@ -7172,7 +7172,10 @@ static void *statsupdate(void *arg) continue; } } + ck_runlock(&sdata->instance_lock); + /* Drop and regain lock to minimise lock hold time */ + ck_rlock(&sdata->instance_lock); HASH_ITER(hh, sdata->user_instances, user, tmpuser) { worker_instance_t *worker; bool idle = false; From c2be459e76a432a93fb6c3bd8bb5640a114c49a2 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Aug 2016 10:16:08 +1000 Subject: [PATCH 06/10] Inline ref_instance_by_id to be able to determine the caller of it for lock debugging --- src/stratifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index ace5284b..b72dab93 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2760,7 +2760,7 @@ static void __inc_instance_ref(stratum_instance_t *client) /* Find an __instance_by_id and increase its reference count allowing us to * use this instance outside of instance_lock without fear of it being * dereferenced. Does not return dropped clients still on the list. */ -static stratum_instance_t *ref_instance_by_id(sdata_t *sdata, const int64_t id) +static inline stratum_instance_t *ref_instance_by_id(sdata_t *sdata, const int64_t id) { stratum_instance_t *client; From 16efbaff3f104dabaa861d03c5c3dc1076483674 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Aug 2016 11:58:23 +1000 Subject: [PATCH 07/10] Examine clients outside of lock in statsupdate to minimise lock hold time --- src/stratifier.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 502545da..7013734e 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -2803,6 +2803,11 @@ static void __drop_client(sdata_t *sdata, stratum_instance_t *client, bool lazil __kill_instance(sdata, client); } +static int __dec_instance_ref(stratum_instance_t *client) +{ + return --client->ref; +} + /* Decrease the reference count of instance. */ static void _dec_instance_ref(sdata_t *sdata, stratum_instance_t *client, const char *file, const char *func, const int line) @@ -2813,7 +2818,7 @@ static void _dec_instance_ref(sdata_t *sdata, stratum_instance_t *client, const int ref; ck_wlock(&sdata->instance_lock); - ref = --client->ref; + ref = __dec_instance_ref(client); /* See if there are any instances that were dropped that could not be * moved due to holding a reference and drop them now. */ if (unlikely(client->dropped && !ref)) { @@ -7120,10 +7125,10 @@ static void *statsupdate(void *arg) double ghs, ghs1, ghs5, ghs15, ghs60, ghs360, ghs1440, ghs10080, per_tdiff; char suffix1[16], suffix5[16], suffix15[16], suffix60[16], cdfield[64]; char suffix360[16], suffix1440[16], suffix10080[16]; - stratum_instance_t *client, *tmp; log_entry_t *log_entries = NULL; user_instance_t *user, *tmpuser; char_entry_t *char_list = NULL; + stratum_instance_t *client; int idle_workers = 0; char *fname, *s, *sp; tv_t now, diff; @@ -7135,9 +7140,27 @@ static void *statsupdate(void *arg) tv_time(&now); timersub(&now, &stats->start_time, &diff); - /* Test clients. */ - ck_rlock(&sdata->instance_lock); - HASH_ITER(hh, sdata->stratum_instances, client, tmp) { + while (client) { + ck_wlock(&sdata->instance_lock); + if (unlikely(!client)) { + /* Grab the first entry */ + client = sdata->stratum_instances; + } else { + /* Drop the reference of the last entry we examined, + * then grab the next client. */ + __dec_instance_ref(client); + client = client->hh.next; + } + /* Grab a reference to this client allowing us to examine + * it without holding the lock */ + if (likely(client)) + __inc_instance_ref(client); + ck_wunlock(&sdata->instance_lock); + + /* Reached last entry */ + if (unlikely(!client)) + break; + /* Look for clients that may have been dropped which the * stratifier has not been informed about and ask the * connector if they still exist */ @@ -7172,7 +7195,6 @@ static void *statsupdate(void *arg) continue; } } - ck_runlock(&sdata->instance_lock); /* Drop and regain lock to minimise lock hold time */ ck_rlock(&sdata->instance_lock); From 44b03fcf29269cdec8581504317087c65a9cd1bb Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Aug 2016 14:39:47 +1000 Subject: [PATCH 08/10] Rework client examination loop in statsupdate --- src/stratifier.c | 78 ++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 7013734e..6936df87 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -7140,60 +7140,52 @@ static void *statsupdate(void *arg) tv_time(&now); timersub(&now, &stats->start_time, &diff); - while (client) { - ck_wlock(&sdata->instance_lock); - if (unlikely(!client)) { - /* Grab the first entry */ - client = sdata->stratum_instances; - } else { - /* Drop the reference of the last entry we examined, - * then grab the next client. */ - __dec_instance_ref(client); - client = client->hh.next; - } - /* Grab a reference to this client allowing us to examine - * it without holding the lock */ - if (likely(client)) - __inc_instance_ref(client); - ck_wunlock(&sdata->instance_lock); - - /* Reached last entry */ - if (unlikely(!client)) - break; + ck_wlock(&sdata->instance_lock); + /* Grab the first entry */ + client = sdata->stratum_instances; + if (likely(client)) + __inc_instance_ref(client); + ck_wunlock(&sdata->instance_lock); + while (client) { /* Look for clients that may have been dropped which the * stratifier has not been informed about and ask the * connector if they still exist */ - if (client->dropped) { + if (client->dropped) connector_test_client(ckp, client->id); - continue; - } - - if (client->node || client->remote) - continue; - - /* Test for clients that haven't authed in over a minute - * and drop them lazily */ - if (!client->authorised) { + else if (client->node || client->remote) { + /* Do nothing to these */ + } else if (!client->authorised) { + /* Test for clients that haven't authed in over a minute + * and drop them lazily */ if (now.tv_sec > client->start_time + 60) { client->dropped = true; connector_drop_client(ckp, client->id); } - continue; + } else { + per_tdiff = tvdiff(&now, &client->last_share); + /* Decay times per connected instance */ + if (per_tdiff > 60) { + /* No shares for over a minute, decay to 0 */ + decay_client(client, 0, &now); + idle_workers++; + if (per_tdiff > 600) + client->idle = true; + /* Test idle clients are still connected */ + connector_test_client(ckp, client->id); + } } - per_tdiff = tvdiff(&now, &client->last_share); - /* Decay times per connected instance */ - if (per_tdiff > 60) { - /* No shares for over a minute, decay to 0 */ - decay_client(client, 0, &now); - idle_workers++; - if (per_tdiff > 600) - client->idle = true; - /* Test idle clients are still connected */ - connector_test_client(ckp, client->id); - continue; - } + ck_wlock(&sdata->instance_lock); + /* Drop the reference of the last entry we examined, + * then grab the next client. */ + __dec_instance_ref(client); + client = client->hh.next; + /* Grab a reference to this client allowing us to examine + * it without holding the lock */ + if (likely(client)) + __inc_instance_ref(client); + ck_wunlock(&sdata->instance_lock); } /* Drop and regain lock to minimise lock hold time */ From ead718a5b51b04655ee76e83c806fd6c442bb87c Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Aug 2016 15:30:15 +1000 Subject: [PATCH 09/10] Rework the user and worker examining loops in statsupdate to not hold the instance lock --- src/stratifier.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index 6936df87..4b0266b9 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -7108,6 +7108,35 @@ static void upstream_workers(ckpool_t *ckp, user_instance_t *user) send_proc(ckp->connector, buf); } + +/* To iterate over all users, if user is initially NULL, this will return the first entry, + * otherwise it will return the entry after user, and NULL if there are no more entries. + * Allows us to grab and drop the lock on each iteration. */ +static user_instance_t *next_user(sdata_t *sdata, user_instance_t *user) +{ + ck_rlock(&sdata->instance_lock); + if (unlikely(!user)) + user = sdata->user_instances; + else + user = user->hh.next; + ck_runlock(&sdata->instance_lock); + + return user; +} + +/* Ditto for worker */ +static worker_instance_t *next_worker(sdata_t *sdata, user_instance_t *user, worker_instance_t *worker) +{ + ck_rlock(&sdata->instance_lock); + if (!worker) + worker = user->worker_instances; + else + worker = worker->next; + ck_runlock(&sdata->instance_lock); + + return worker; +} + static void *statsupdate(void *arg) { ckpool_t *ckp = (ckpool_t *)arg; @@ -7126,9 +7155,9 @@ static void *statsupdate(void *arg) char suffix1[16], suffix5[16], suffix15[16], suffix60[16], cdfield[64]; char suffix360[16], suffix1440[16], suffix10080[16]; log_entry_t *log_entries = NULL; - user_instance_t *user, *tmpuser; char_entry_t *char_list = NULL; stratum_instance_t *client; + user_instance_t *user; int idle_workers = 0; char *fname, *s, *sp; tv_t now, diff; @@ -7148,6 +7177,7 @@ static void *statsupdate(void *arg) ck_wunlock(&sdata->instance_lock); while (client) { + tv_time(&now); /* Look for clients that may have been dropped which the * stratifier has not been informed about and ask the * connector if they still exist */ @@ -7188,17 +7218,20 @@ static void *statsupdate(void *arg) ck_wunlock(&sdata->instance_lock); } - /* Drop and regain lock to minimise lock hold time */ - ck_rlock(&sdata->instance_lock); - HASH_ITER(hh, sdata->user_instances, user, tmpuser) { + user = NULL; + + while ((user = next_user(sdata, user)) != NULL) { worker_instance_t *worker; bool idle = false; if (!user->authorised) continue; + worker = NULL; + tv_time(&now); + /* Decay times per worker */ - DL_FOREACH(user->worker_instances, worker) { + while ((worker = next_worker(sdata, user, worker)) != NULL) { per_tdiff = tvdiff(&now, &worker->last_share); if (per_tdiff > 60) { decay_worker(worker, 0, &now); @@ -7287,7 +7320,6 @@ static void *statsupdate(void *arg) if (ckp->remote) upstream_workers(ckp, user); } - ck_runlock(&sdata->instance_lock); /* Dump log entries out of instance_lock */ dump_log_entries(&log_entries); From ded126d599cd914337661a0c4591ad6a34186cd3 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 4 Aug 2016 15:40:03 +1000 Subject: [PATCH 10/10] Relax the array size check in shares to at least large enough --- src/stratifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 4b0266b9..a037da91 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -5506,7 +5506,7 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, *err_val = JSON_ERR(err); goto out; } - if (unlikely(json_array_size(params_val) != 5)) { + if (unlikely(json_array_size(params_val) < 5)) { err = SE_INVALID_SIZE; *err_val = JSON_ERR(err); goto out;