From 6f4c47ebd28c2363bcd801264ae58e70637e9c4b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 29 Oct 2012 11:58:58 +1100 Subject: [PATCH] Make stratum socket fail more robust on windows by disabling the send buffer. Reuse the same curl handle forcing a new connection instead of risking derefencing. Add information about submission failure to stratum send. --- cgminer.c | 9 +++++++++ util.c | 59 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/cgminer.c b/cgminer.c index 5de9aac3..95591f79 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2934,6 +2934,8 @@ static void *submit_work_thread(void *userdata) if (likely(stratum_send(pool, s, strlen(s)))) { struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1); + if (pool_tclear(pool, &pool->submit_fail)) + applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no); applog(LOG_DEBUG, "Successfully submitted, adding to stratum_shares db"); memcpy(&sshare->work, work, sizeof(struct work)); @@ -2941,6 +2943,13 @@ static void *submit_work_thread(void *userdata) sshare->id = swork_id; HASH_ADD_INT(stratum_shares, id, sshare); mutex_unlock(&sshare_lock); + } else { + applog(LOG_INFO, "Failed to submit stratum share"); + if (!pool_tset(pool, &pool->submit_fail)) { + total_ro++; + pool->remotefail_occasions++; + applog(LOG_WARNING, "Pool %d share submission failure", pool->pool_no); + } } goto out; diff --git a/util.c b/util.c index 115dfe02..58e65d32 100644 --- a/util.c +++ b/util.c @@ -198,36 +198,39 @@ out: static int keep_sockalive(SOCKETTYPE fd) { - int tcp_keepidle = 60; - int tcp_keepintvl = 60; + const int tcp_keepidle = 60; + const int tcp_keepintvl = 60; + const int keepalive = 1; + int ret = 0; + #ifndef WIN32 - int keepalive = 1; - int tcp_keepcnt = 5; + const int tcp_keepcnt = 5; if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) - return 1; + ret = 1; # ifdef __linux if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) - return 1; + ret = 1; if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))) - return 1; + ret = 1; if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))) - return 1; + ret = 1; # endif /* __linux */ # ifdef __APPLE_CC__ if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) - return 1; + ret = 1; # endif /* __APPLE_CC__ */ #else /* WIN32 */ + const int zero = 0; struct tcp_keepalive vals; vals.onoff = 1; vals.keepalivetime = tcp_keepidle * 1000; @@ -235,12 +238,20 @@ static int keep_sockalive(SOCKETTYPE fd) DWORD outputBytes; + if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&keepalive, sizeof(keepalive)))) + ret = 1; + if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) - return 1; + ret = 1; + /* Windows happily submits indefinitely to the send buffer blissfully + * unaware nothing is getting there without gracefully failing unless + * we disable the send buffer */ + if (unlikely(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&zero, sizeof(zero)))) + ret = 1; #endif /* WIN32 */ - return 0; + return ret; } int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd, @@ -887,8 +898,8 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len) while (len > 0 ) { struct timeval timeout = {0, 0}; - CURLcode rc = CURLE_SEND_ERROR; size_t sent = 0; + CURLcode rc; fd_set wd; FD_ZERO(&wd); @@ -897,8 +908,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len) applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no); return false; } - if (likely(pool->stratum_curl)) - rc = curl_easy_send(pool->stratum_curl, s + ssent, len, &sent); + rc = curl_easy_send(pool->stratum_curl, s + ssent, len, &sent); if (rc != CURLE_OK) { applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send"); return false; @@ -931,8 +941,7 @@ static void clear_sock(struct pool *pool) mutex_lock(&pool->stratum_lock); /* Ignore return code of curl_easy_recv since we're just clearing * anything in the socket if it's still alive */ - if (likely(pool->stratum_curl)) - curl_easy_recv(pool->stratum_curl, pool->sockbuf, RECVSIZE, &n); + curl_easy_recv(pool->stratum_curl, pool->sockbuf, RECVSIZE, &n); mutex_unlock(&pool->stratum_lock); strcpy(pool->sockbuf, ""); } @@ -968,9 +977,9 @@ char *recv_line(struct pool *pool) size_t n = 0; if (!strstr(pool->sockbuf, "\n")) { - CURLcode rc = CURLE_RECV_ERROR; char s[RBUFSIZE]; size_t sspace; + CURLcode rc; if (!sock_full(pool, true)) { applog(LOG_DEBUG, "Timed out waiting for data on sock_full"); @@ -979,8 +988,7 @@ char *recv_line(struct pool *pool) memset(s, 0, RBUFSIZE); mutex_lock(&pool->stratum_lock); - if (likely(pool->stratum_curl)) - rc = curl_easy_recv(pool->stratum_curl, s, RECVSIZE, &n); + rc = curl_easy_recv(pool->stratum_curl, s, RECVSIZE, &n); mutex_unlock(&pool->stratum_lock); if (rc != CURLE_OK) { @@ -1320,7 +1328,6 @@ bool initiate_stratum(struct pool *pool) mutex_lock(&pool->stratum_lock); pool->stratum_active = false; - if (!pool->stratum_curl) { pool->stratum_curl = curl_easy_init(); if (unlikely(!pool->stratum_curl)) @@ -1333,6 +1340,7 @@ bool initiate_stratum(struct pool *pool) memset(s, 0, RBUFSIZE); sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port); + curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); @@ -1421,15 +1429,8 @@ out: applog(LOG_DEBUG, "Pool %d confirmed mining.subscribe with extranonce1 %s extran2size %d", pool->pool_no, pool->nonce1, pool->n2size); } - } else { - applog(LOG_DEBUG, "Initiate stratum failed, disabling stratum_active"); - mutex_lock(&pool->stratum_lock); - if (curl) { - curl_easy_cleanup(curl); - pool->stratum_curl = NULL; - } - mutex_unlock(&pool->stratum_lock); - } + } else + applog(LOG_DEBUG, "Initiate stratum failed"); return ret; }