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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
diff --git a/cgminer.c b/cgminer.c
index 5de9aac..95591f7 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 115dfe0..58e65d3 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;
}