From 7d8417774f5afef2da5e377751ca57ab4d54e7ab Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 7 Jan 2017 09:13:39 +1100 Subject: [PATCH] Properly drop subclients when the parent dies by testing whether the parent exists instead of the masked subclient id. --- src/ckpool.h | 7 +++++++ src/connector.c | 20 ++++++++++++-------- src/stratifier.c | 21 +-------------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/ckpool.h b/src/ckpool.h index 32792308..c5f48158 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -390,4 +390,11 @@ static inline json_t *json_encode_errormsg(json_error_t __maybe_unused *err_val) static inline json_t *json_errormsg(const char __maybe_unused *fmt, ...) { return NULL; }; static inline void send_api_response(json_t __maybe_unused *val, const int __maybe_unused sockd) {}; +/* Subclients have client_ids in the high bits. Returns the value of the parent + * client if one exists. */ +static inline int64_t subclient(const int64_t client_id) +{ + return (client_id >> 32); +} + #endif /* CKPOOL_H */ diff --git a/src/connector.c b/src/connector.c index 8616f7b3..17683f8b 100644 --- a/src/connector.c +++ b/src/connector.c @@ -958,6 +958,7 @@ static void send_client(ckpool_t *ckp, cdata_t *cdata, const int64_t id, char *b sender_send_t *sender_send; client_instance_t *client; bool redirect = false; + int64_t pass_id; int len; if (unlikely(!buf)) { @@ -980,11 +981,9 @@ static void send_client(ckpool_t *ckp, cdata_t *cdata, const int64_t id, char *b /* Grab a reference to this client until the sender_send has * completed processing. Is this a passthrough subclient ? */ - if (id > 0xffffffffll) { - int64_t client_id, pass_id; + if ((pass_id = subclient(id))) { + int64_t client_id = id & 0xffffffffll; - client_id = id & 0xffffffffll; - pass_id = id >> 32; /* Make sure the passthrough exists for passthrough subclients */ client = ref_client_by_id(cdata, pass_id); if (unlikely(!client)) { @@ -1057,10 +1056,16 @@ static void send_client_json(ckpool_t *ckp, cdata_t *cdata, int64_t client_id, j json_decref(json_msg); } -static bool client_exists(cdata_t *cdata, const int64_t id) +/* When testing if a client exists, passthrough clients don't exist when their + * parent no longer exists. */ +static bool client_exists(cdata_t *cdata, int64_t id) { + int64_t parent_id = subclient(id); client_instance_t *client; + if (parent_id) + id = parent_id; + ck_rlock(&cdata->lock); HASH_FIND_I64(cdata->clients, &id, client); ck_runlock(&cdata->lock); @@ -1300,7 +1305,7 @@ static void client_message_processor(ckpool_t *ckp, json_t *json_msg) json_object_del(json_msg, "client_id"); /* Put client_id back in for a passthrough subclient, passing its * upstream client_id instead of the passthrough's. */ - if (client_id > 0xffffffffll) + if (subclient(client_id)) json_object_set_new_nocheck(json_msg, "client_id", json_integer(client_id & 0xffffffffll)); /* Flag redirector clients once they've been authorised */ @@ -1455,7 +1460,7 @@ retry: goto retry; } /* A passthrough client */ - if (client_id > 0xffffffffll) { + if (subclient(client_id)) { drop_passthrough_client(ckp, cdata, client_id); goto retry; } @@ -1474,7 +1479,6 @@ retry: LOGDEBUG("Connector failed to parse testclient command: %s", buf); goto retry; } - client_id &= 0xffffffffll; if (client_exists(cdata, client_id)) goto retry; LOGINFO("Connector detected non-existent client id: %"PRId64, client_id); diff --git a/src/stratifier.c b/src/stratifier.c index 997e8fc3..f108f178 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -1938,13 +1938,6 @@ share_diff(char *coinbase, const uchar *enonce1bin, const workbase_t *wb, const return diff_from_target(hash); } -/* Subclients have client_ids in the high bits. Returns the value of the parent - * client if one exists. */ -static inline int64_t subclient(const int64_t client_id) -{ - return (client_id >> 32); -} - /* Note recursive lock here - entered with workbase lock held, grabs instance lock */ static void send_node_block(sdata_t *sdata, const char *enonce1, const char *nonce, const char *nonce2, const uint32_t ntime32, const int64_t jobid, @@ -3160,18 +3153,6 @@ static void __drop_client(sdata_t *sdata, stratum_instance_t *client, bool lazil } else if (unlikely(client->passthrough)) parent = true; - /* Tag any subclients of this parent to be dropped lazily */ - if (parent) { - stratum_instance_t *tmp; - - for (tmp = sdata->stratum_instances; tmp; tmp = tmp->hh.next) { - int64_t subid = subclient(tmp->id); - - if (subid && subid == client->id) - tmp->dropped = true; - } - } - if (client->workername) { if (user) { ASPRINTF(msg, "Dropped client %s %s %suser %s worker %s %s", @@ -3183,7 +3164,7 @@ static void __drop_client(sdata_t *sdata, stratum_instance_t *client, bool lazil lazily ? "lazily" : ""); } } else { - ASPRINTF(msg, "Dropped workerless client %s %s %s", + ASPRINTF(msg, "Dropped %sworkerless client %s %s %s", parent ? "parent " : "", client->identity, client->address, lazily ? "lazily" : ""); } __del_client(sdata, client);