From d2d5a5daaad5d6e2f969d8479b6752ef667e4b06 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 17 Dec 2015 23:26:40 +1100 Subject: [PATCH] Don't use persistent connections to bitcoind --- src/ckpool.c | 20 +++++--------------- src/generator.c | 41 +++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 256ae602..fd539a7e 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -594,7 +594,6 @@ out: if (ret < 0) { empty_buffer(cs); dealloc(cs->buf); - Close(cs->fd); } return ret; } @@ -741,6 +740,8 @@ static const char *rpc_method(const char *rpc_req) return rpc_req; } +/* All of these calls are made to bitcoind which prefers open/close instead + * of persistent connections so cs->fd is always invalid. */ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) { float timeout = RPC_TIMEOUT; @@ -753,8 +754,9 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) /* Serialise all calls in case we use cs from multiple threads */ cksem_wait(&cs->sem); + cs->fd = connect_socket(cs->url, cs->port); if (unlikely(cs->fd < 0)) { - LOGWARNING("FD %d invalid in %s", cs->fd, __func__); + LOGWARNING("Unable to connect socket to %s:%s in %s", cs->url, cs->port, __func__); goto out; } if (unlikely(!cs->url)) { @@ -837,20 +839,8 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) out_empty: empty_socket(cs->fd); empty_buffer(cs); - if (!val) { - /* Assume that a failed request means the socket will be closed - * and reopen it */ - Close(cs->fd); - } out: - if (cs->fd < 0) { - /* Attempt to reopen a socket that has been closed due to a - * failed request or if the socket was closed while trying to - * read/write to it. */ - cs->fd = connect_socket(cs->url, cs->port); - LOGWARNING("Attempt to reopen socket to %s:%s %ssuccessful", - cs->url, cs->port, cs->fd > 0 ? "" : "un"); - } + Close(cs->fd); free(http_req); dealloc(cs->buf); cksem_post(&cs->sem); diff --git a/src/generator.c b/src/generator.c index 600cc211..28e61d79 100644 --- a/src/generator.c +++ b/src/generator.c @@ -137,18 +137,18 @@ struct generator_data { typedef struct generator_data gdata_t; +/* Use a temporary fd when testing server_alive to avoid races on cs->fd */ static bool server_alive(ckpool_t *ckp, server_instance_t *si, bool pinging) { char *userpass = NULL; bool ret = false; connsock_t *cs; gbtbase_t *gbt; + int fd; - cs = &si->cs; - /* Has this server already been reconnected? */ - if (cs->fd > 0) + if (si->alive) return true; - si->alive = false; + cs = &si->cs; if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { LOGWARNING("Failed to extract address from %s", si->url); return ret; @@ -163,8 +163,8 @@ static bool server_alive(ckpool_t *ckp, server_instance_t *si, bool pinging) return ret; } - cs->fd = connect_socket(cs->url, cs->port); - if (cs->fd < 0) { + fd = connect_socket(cs->url, cs->port); + if (fd < 0) { if (!pinging) LOGWARNING("Failed to connect socket to %s:%s !", cs->url, cs->port); return ret; @@ -185,16 +185,11 @@ static bool server_alive(ckpool_t *ckp, server_instance_t *si, bool pinging) LOGWARNING("Invalid btcaddress: %s !", ckp->btcaddress); goto out; } - ret = true; + si->alive = ret = true; + LOGNOTICE("Server alive: %s:%s", cs->url, cs->port); out: - if (!ret) { - /* Close and invalidate the file handle */ - Close(cs->fd); - } else { - si->alive = true; - LOGNOTICE("Server alive: %s:%s", cs->url, cs->port); - keep_sockalive(cs->fd); - } + /* Close the file handle */ + close(fd); return ret; } @@ -216,7 +211,7 @@ retry: server_instance_t *si = ckp->servers[i]; cs = &si->cs; - if (si->alive && cs->fd > 0) { + if (si->alive) { alive = si; goto living; } @@ -301,11 +296,10 @@ retry: } } while (selret < 1); - if (unlikely(cs->fd < 0)) { + if (unlikely(!si->alive)) { LOGWARNING("%s:%s Bitcoind socket invalidated, will attempt failover", cs->url, cs->port); goto reconnect; } - sockd = accept(us->sockd, NULL, NULL); if (sockd < 0) { LOGEMERG("Failed to accept on generator socket"); @@ -329,6 +323,7 @@ retry: LOGWARNING("Failed to get block template from %s:%s", cs->url, cs->port); send_unix_msg(sockd, "Failed"); + si->alive = false; goto reconnect; } else { char *s = json_dumps(gbt->json, JSON_NO_UTF8); @@ -343,6 +338,7 @@ retry: else if (!get_bestblockhash(cs, hash)) { LOGINFO("No best block hash support from %s:%s", cs->url, cs->port); + si->alive = false; send_unix_msg(sockd, "failed"); } else { send_unix_msg(sockd, hash); @@ -353,11 +349,13 @@ retry: if (si->notify) send_unix_msg(sockd, "notify"); else if ((height = get_blockcount(cs)) == -1) { + si->alive = false; send_unix_msg(sockd, "failed"); goto reconnect; } else { LOGDEBUG("Height: %d", height); if (!get_blockhash(cs, height, hash)) { + si->alive = false; send_unix_msg(sockd, "failed"); goto reconnect; } else { @@ -1728,6 +1726,8 @@ static int server_mode(ckpool_t *ckp, proc_instance_t *pi) ckp->servers = ckalloc(sizeof(server_instance_t *) * ckp->btcds); for (i = 0; i < ckp->btcds; i++) { + connsock_t *cs; + ckp->servers[i] = ckzalloc(sizeof(server_instance_t)); si = ckp->servers[i]; si->url = ckp->btcdurl[i]; @@ -1735,8 +1735,9 @@ static int server_mode(ckpool_t *ckp, proc_instance_t *pi) si->pass = ckp->btcdpass[i]; si->notify = ckp->btcdnotify[i]; si->id = i; - cksem_init(&si->cs.sem); - cksem_post(&si->cs.sem); + cs = &si->cs; + cksem_init(&cs->sem); + cksem_post(&cs->sem); } create_pthread(&pth_watchdog, server_watchdog, ckp);