Commit 6f4c47ebd28c2363bcd801264ae58e70637e9c4b

Con Kolivas 2012-10-29T11:58:58

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.

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;
 }