Browse Source

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.
nfactor-troky
Con Kolivas 12 years ago
parent
commit
6f4c47ebd2
  1. 9
      cgminer.c
  2. 53
      util.c

9
cgminer.c

@ -2934,6 +2934,8 @@ static void *submit_work_thread(void *userdata)
if (likely(stratum_send(pool, s, strlen(s)))) { if (likely(stratum_send(pool, s, strlen(s)))) {
struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1); 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"); applog(LOG_DEBUG, "Successfully submitted, adding to stratum_shares db");
memcpy(&sshare->work, work, sizeof(struct work)); memcpy(&sshare->work, work, sizeof(struct work));
@ -2941,6 +2943,13 @@ static void *submit_work_thread(void *userdata)
sshare->id = swork_id; sshare->id = swork_id;
HASH_ADD_INT(stratum_shares, id, sshare); HASH_ADD_INT(stratum_shares, id, sshare);
mutex_unlock(&sshare_lock); 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; goto out;

53
util.c

@ -198,36 +198,39 @@ out:
static int keep_sockalive(SOCKETTYPE fd) static int keep_sockalive(SOCKETTYPE fd)
{ {
int tcp_keepidle = 60; const int tcp_keepidle = 60;
int tcp_keepintvl = 60; const int tcp_keepintvl = 60;
const int keepalive = 1;
int ret = 0;
#ifndef WIN32 #ifndef WIN32
int keepalive = 1; const int tcp_keepcnt = 5;
int tcp_keepcnt = 5;
if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive))))
return 1; ret = 1;
# ifdef __linux # ifdef __linux
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) 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)))) 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)))) if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl))))
return 1; ret = 1;
# endif /* __linux */ # endif /* __linux */
# ifdef __APPLE_CC__ # ifdef __APPLE_CC__
if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl))))
return 1; ret = 1;
# endif /* __APPLE_CC__ */ # endif /* __APPLE_CC__ */
#else /* WIN32 */ #else /* WIN32 */
const int zero = 0;
struct tcp_keepalive vals; struct tcp_keepalive vals;
vals.onoff = 1; vals.onoff = 1;
vals.keepalivetime = tcp_keepidle * 1000; vals.keepalivetime = tcp_keepidle * 1000;
@ -235,12 +238,20 @@ static int keep_sockalive(SOCKETTYPE fd)
DWORD outputBytes; 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))) 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 */ #endif /* WIN32 */
return 0; return ret;
} }
int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd, 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 ) { while (len > 0 ) {
struct timeval timeout = {0, 0}; struct timeval timeout = {0, 0};
CURLcode rc = CURLE_SEND_ERROR;
size_t sent = 0; size_t sent = 0;
CURLcode rc;
fd_set wd; fd_set wd;
FD_ZERO(&wd); FD_ZERO(&wd);
@ -897,7 +908,6 @@ 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); applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no);
return false; 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) { if (rc != CURLE_OK) {
applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send"); applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send");
@ -931,7 +941,6 @@ static void clear_sock(struct pool *pool)
mutex_lock(&pool->stratum_lock); mutex_lock(&pool->stratum_lock);
/* Ignore return code of curl_easy_recv since we're just clearing /* Ignore return code of curl_easy_recv since we're just clearing
* anything in the socket if it's still alive */ * 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); mutex_unlock(&pool->stratum_lock);
strcpy(pool->sockbuf, ""); strcpy(pool->sockbuf, "");
@ -968,9 +977,9 @@ char *recv_line(struct pool *pool)
size_t n = 0; size_t n = 0;
if (!strstr(pool->sockbuf, "\n")) { if (!strstr(pool->sockbuf, "\n")) {
CURLcode rc = CURLE_RECV_ERROR;
char s[RBUFSIZE]; char s[RBUFSIZE];
size_t sspace; size_t sspace;
CURLcode rc;
if (!sock_full(pool, true)) { if (!sock_full(pool, true)) {
applog(LOG_DEBUG, "Timed out waiting for data on sock_full"); applog(LOG_DEBUG, "Timed out waiting for data on sock_full");
@ -979,7 +988,6 @@ char *recv_line(struct pool *pool)
memset(s, 0, RBUFSIZE); memset(s, 0, RBUFSIZE);
mutex_lock(&pool->stratum_lock); 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); mutex_unlock(&pool->stratum_lock);
@ -1320,7 +1328,6 @@ bool initiate_stratum(struct pool *pool)
mutex_lock(&pool->stratum_lock); mutex_lock(&pool->stratum_lock);
pool->stratum_active = false; pool->stratum_active = false;
if (!pool->stratum_curl) { if (!pool->stratum_curl) {
pool->stratum_curl = curl_easy_init(); pool->stratum_curl = curl_easy_init();
if (unlikely(!pool->stratum_curl)) if (unlikely(!pool->stratum_curl))
@ -1333,6 +1340,7 @@ bool initiate_stratum(struct pool *pool)
memset(s, 0, RBUFSIZE); memset(s, 0, RBUFSIZE);
sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port); 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_CONNECTTIMEOUT, 60);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 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", applog(LOG_DEBUG, "Pool %d confirmed mining.subscribe with extranonce1 %s extran2size %d",
pool->pool_no, pool->nonce1, pool->n2size); pool->pool_no, pool->nonce1, pool->n2size);
} }
} else { } else
applog(LOG_DEBUG, "Initiate stratum failed, disabling stratum_active"); applog(LOG_DEBUG, "Initiate stratum failed");
mutex_lock(&pool->stratum_lock);
if (curl) {
curl_easy_cleanup(curl);
pool->stratum_curl = NULL;
}
mutex_unlock(&pool->stratum_lock);
}
return ret; return ret;
} }

Loading…
Cancel
Save