Browse Source

Merge branch 'master' of git://github.com/ckolivas/cgminer.git

Paul Sheppard 13 years ago
parent
commit
dd2b7e5fe0
5 changed files with 178 additions and 76 deletions
  1. 30 0
      NEWS
  2. 21 4
      README
  3. 86 39
      cgminer.c
  4. 1 1
      configure.ac
  5. 40 32
      util.c

+ 30 - 0
NEWS

@@ -1,3 +1,33 @@
+Version 2.8.6 - October 29, 2012
+
+- Shorten the initiate stratum connect timeout to 30 seconds.
+- Shorten the stratum timeout on read to 90 seconds to detect unresponsive pool.
+- Display best share difficulty on exit.
+- 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.
+- Only add stratum share to database if we succeeded in submitting it, with a
+debug output saying it succeeded.
+- Use keepalive with stratum sockets to improve its ability to detect broken
+connections.
+- Show only the URL in the status bar to avoid long prefixes making for extra
+long lines.
+- Display compact status in menu and update README to reflect current menu
+entries.
+- Add a compact display mode that does not list per device statistics in the
+status window.
+- Add blank spaces after best share displayed.
+- Round a few static string arrays up to 4 byte boundaries for ARM.
+- Display best share diff for scrypt as well.
+- Show the best diff share as "best share" and add info to the README.
+- Display the best diff share submitted so far.
+- Redundant check.
+- The work struct pointer in struct pc_data in findnonce is never freed yet
+there is no need to allocate it separately so make struct work a static part of
+the struct pc_data. s
+
+
 Version 2.8.5 - October 23, 2012
 
 - Handle crash exceptions by trying to restart cgminer unless the --no-restart

+ 21 - 4
README

@@ -143,6 +143,7 @@ Options for both config file and command line:
 --auto-gpu          Automatically adjust all GPU engine clock speeds to maintain a target temperature
 --balance           Change multipool strategy from failover to even share balance
 --benchmark         Run cgminer in benchmark mode - produces no shares
+--compact           Use compact display without per device statistics
 --debug|-D          Enable debug output
 --expiry|-E <arg>   Upper bound on how many seconds after getting work we consider a share from it stale (default: 120)
 --failover-only     Don't leak work to backup pools when primary pool is lagging
@@ -341,6 +342,7 @@ The following options are available while running with a single keypress:
 P gives you:
 
 Current pool management strategy: Failover
+[F]ailover only disabled
 [A]dd pool [R]emove pool [D]isable pool [E]nable pool
 [C]hange management strategy [S]witch pool [I]nformation
 
@@ -350,15 +352,21 @@ S gives you:
 [Q]ueue: 1
 [S]cantime: 60
 [E]xpiry: 120
-[R]etries: -1
-[P]ause: 5
 [W]rite config file
+[C]gminer restart
 
 
 D gives you:
 
-Toggle: [D]ebug [N]ormal [S]ilent [V]erbose [R]PC debug
-[L]og interval [C]lear
+[N]ormal [C]lear [S]ilent mode (disable all output)
+[D]ebug:off
+[P]er-device:off
+[Q]uiet:off
+[V]erbose:off
+[R]PC debug:off
+[W]orkTime details:off
+co[M]pact: off
+[L]og interval:5
 
 
 Q quits the application.
@@ -441,6 +449,15 @@ diminish return performance even if the hash rate might appear better. A good
 starting baseline intensity to try on dedicated miners is 9. Higher values are
 there to cope with future improvements in hardware.
 
+
+The block display shows:
+Block: 0074c5e482e34a506d2a051a...  Started: [17:17:22]  Best share: 2.71K
+
+This shows a short stretch of the current block, when the new block started,
+and the all time best difficulty share you've submitted since starting cgminer
+this time.
+
+
 ---
 MULTIPOOL
 

+ 86 - 39
cgminer.c

@@ -92,6 +92,7 @@ bool use_syslog;
 bool opt_quiet;
 bool opt_realquiet;
 bool opt_loginput;
+bool opt_compact;
 const int opt_cutofftemp = 95;
 int opt_log_interval = 5;
 int opt_queue = 1;
@@ -213,15 +214,17 @@ const
 #endif
 bool curses_active;
 
-static char current_block[37];
+static char current_block[40];
 static char *current_hash;
 char *current_fullhash;
 static char datestamp[40];
 static char blocktime[30];
 struct timeval block_timeval;
+static char best_share[8] = "0";
+static uint64_t best_diff = 0;
 
 struct block {
-	char hash[37];
+	char hash[40];
 	UT_hash_handle hh;
 	int block_no;
 };
@@ -549,10 +552,10 @@ static char *set_rr(enum pool_strategy *strategy)
  * stratum+tcp or by detecting a stratum server response */
 bool detect_stratum(struct pool *pool, char *url)
 {
-	if (opt_scrypt)
+	if (!extract_sockaddr(pool, url))
 		return false;
 
-	if (!extract_sockaddr(pool, url))
+	if (opt_scrypt)
 		return false;
 
 	if (!strncasecmp(url, "stratum+tcp://", 14)) {
@@ -852,6 +855,13 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--bench-algo|-b",
 		     set_int_0_to_9999, opt_show_intval, &opt_bench_algo,
 		     opt_hidden),
+#endif
+#ifdef HAVE_CURSES
+	OPT_WITHOUT_ARG("--compact",
+			opt_set_bool, &opt_compact,
+			"Use compact display without per device statistics"),
+#endif
+#ifdef WANT_CPUMINE
 	OPT_WITH_ARG("--cpu-threads|-t",
 		     force_nthreads_int, opt_show_intval, &opt_n_threads,
 		     "Number of miner CPU threads"),
@@ -1578,16 +1588,16 @@ static void curses_print_status(void)
 	wclrtoeol(statuswin);
 	if (pool->has_stratum) {
 		mvwprintw(statuswin, 4, 0, " Connected to %s with stratum as user %s",
-			pool->stratum_url, pool->rpc_user);
+			pool->sockaddr_url, pool->rpc_user);
 	} else if ((pool_strategy == POOL_LOADBALANCE  || pool_strategy == POOL_BALANCE) && total_pools > 1) {
 		mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP",
 			have_longpoll ? "": "out");
 	} else {
 		mvwprintw(statuswin, 4, 0, " Connected to %s with%s LP as user %s",
-			pool->rpc_url, have_longpoll ? "": "out", pool->rpc_user);
+			pool->sockaddr_url, have_longpoll ? "": "out", pool->rpc_user);
 	}
 	wclrtoeol(statuswin);
-	mvwprintw(statuswin, 5, 0, " Block: %s...  Started: %s", current_hash, blocktime);
+	mvwprintw(statuswin, 5, 0, " Block: %s...  Started: %s  Best share: %s   ", current_hash, blocktime, best_share);
 	mvwhline(statuswin, 6, 0, '-', 80);
 	mvwhline(statuswin, statusy - 1, 0, '-', 80);
 	mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit",
@@ -1610,7 +1620,7 @@ static void curses_print_devstatus(int thr_id)
 	char displayed_hashes[16], displayed_rolling[16];
 	uint64_t dh64, dr64;
 
-	if (devcursor + cgpu->cgminer_id > LINES - 2)
+	if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact)
 		return;
 
 	cgpu->utility = cgpu->accepted / total_secs * 60;
@@ -1670,14 +1680,13 @@ static void print_status(int thr_id)
 
 #ifdef HAVE_CURSES
 /* Check for window resize. Called with curses mutex locked */
-static inline bool change_logwinsize(void)
+static inline void change_logwinsize(void)
 {
 	int x, y, logx, logy;
-	bool ret = false;
 
 	getmaxyx(mainwin, y, x);
 	if (x < 80 || y < 25)
-		return ret;
+		return;
 
 	if (y > statusy + 2 && statusy < logstart) {
 		if (y - 2 < logstart)
@@ -1687,17 +1696,13 @@ static inline bool change_logwinsize(void)
 		logcursor = statusy + 1;
 		mvwin(logwin, logcursor, 0);
 		wresize(statuswin, statusy, x);
-		ret = true;
 	}
 
 	y -= logcursor;
 	getmaxyx(logwin, logy, logx);
 	/* Detect screen size change */
-	if (x != logx || y != logy) {
+	if (x != logx || y != logy)
 		wresize(logwin, y, x);
-		ret = true;
-	}
-	return ret;
 }
 
 static void check_winsizes(void)
@@ -1707,6 +1712,7 @@ static void check_winsizes(void)
 	if (curses_active_locked()) {
 		int y, x;
 
+		erase();
 		x = getmaxx(statuswin);
 		if (logstart > LINES - 2)
 			statusy = LINES - 2;
@@ -1722,6 +1728,18 @@ static void check_winsizes(void)
 	}
 }
 
+static void switch_compact(void)
+{
+	if (opt_compact) {
+		logstart = devcursor + 1;
+		logcursor = logstart + 1;
+	} else {
+		logstart = devcursor + total_devices + 1;
+		logcursor = logstart + 1;
+	}
+	check_winsizes();
+}
+
 /* For mandatory printing when mutex is already locked */
 void wlog(const char *f, ...)
 {
@@ -1770,6 +1788,7 @@ bool log_curses_only(int prio, const char *f, va_list ap)
 void clear_logwin(void)
 {
 	if (curses_active_locked()) {
+		erase();
 		wclear(logwin);
 		unlock_curses();
 	}
@@ -1980,17 +1999,26 @@ static uint64_t share_diff(const struct work *work)
 	if (unlikely(!d64))
 		d64 = 1;
 	ret = diffone / d64;
+	if (ret > best_diff) {
+		best_diff = ret;
+		suffix_string(best_diff, best_share, 0);
+	}
 	return ret;
 }
 
 static uint32_t scrypt_diff(const struct work *work)
 {
 	const uint32_t scrypt_diffone = 0x0000fffful;
-	uint32_t d32 = work->outputhash;
+	uint32_t d32 = work->outputhash, ret;
 
 	if (unlikely(!d32))
 		d32 = 1;
-	return scrypt_diffone / d32;
+	ret = scrypt_diffone / d32;
+	if (ret > best_diff) {
+		best_diff = ret;
+		suffix_string(best_diff, best_share, 0);
+	}
+	return ret;
 }
 
 static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
@@ -2887,34 +2915,41 @@ static void *submit_work_thread(void *userdata)
 	}
 
 	if (work->stratum) {
-		struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
 		uint32_t *hash32 = (uint32_t *)work->hash, nonce;
 		char *noncehex;
 		char s[1024];
 
-		memcpy(&sshare->work, work, sizeof(struct work));
-
 		/* Give the stratum share a unique id */
-		mutex_lock(&sshare_lock);
-		sshare->id = swork_id++;
-		HASH_ADD_INT(stratum_shares, id, sshare);
-		mutex_unlock(&sshare_lock);
-
+		swork_id++;
 		nonce = *((uint32_t *)(work->data + 76));
 		noncehex = bin2hex((const unsigned char *)&nonce, 4);
 
 		memset(s, 0, 1024);
 		sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
-			pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, sshare->id);
+			pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, swork_id);
 		free(noncehex);
 
 		applog(LOG_INFO, "Submitting share %08lx to pool %d", (unsigned long)(hash32[6]), pool->pool_no);
 
-		if (unlikely(!stratum_send(pool, s, strlen(s)))) {
+		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));
+
 			mutex_lock(&sshare_lock);
-			HASH_DEL(stratum_shares, sshare);
+			sshare->id = swork_id;
+			HASH_ADD_INT(stratum_shares, id, sshare);
 			mutex_unlock(&sshare_lock);
-			free(sshare);
+		} 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;
@@ -3143,14 +3178,14 @@ static void set_curblock(char *hexstr, unsigned char *hash)
 
 	strcpy(current_block, hexstr);
 	swap256(hash_swap, hash);
-	swap256(block_hash_swap, hash+4);
+	swap256(block_hash_swap, hash + 4);
 
 	/* Don't free current_hash directly to avoid dereferencing when read
 	 * elsewhere - and update block_timeval inside the same lock */
 	mutex_lock(&ch_lock);
 	gettimeofday(&block_timeval, NULL);
 	old_hash = current_hash;
-	current_hash = bin2hex(hash_swap, 16);
+	current_hash = bin2hex(hash_swap + 2, 12);
 	free(old_hash);
 	old_hash = current_fullhash;
 	current_fullhash = bin2hex(block_hash_swap, 32);
@@ -3793,13 +3828,16 @@ static void display_options(void)
 	clear_logwin();
 retry:
 	wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n");
-	wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[W]orkTime details:%s\n[L]og interval:%d\n",
+	wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n"
+		  "[R]PC debug:%s\n[W]orkTime details:%s\nco[M]pact: %s\n"
+		  "[L]og interval:%d\n",
 		opt_debug ? "on" : "off",
 	        want_per_device_stats? "on" : "off",
 		opt_quiet ? "on" : "off",
 		opt_log_output ? "on" : "off",
 		opt_protocol ? "on" : "off",
 		opt_worktime ? "on" : "off",
+		opt_compact ? "on" : "off",
 		opt_log_interval);
 	wlogprint("Select an option or any other key to return\n");
 	input = getch();
@@ -3818,8 +3856,10 @@ retry:
 		opt_debug = false;
 		opt_quiet = false;
 		opt_protocol = false;
+		opt_compact = false;
 		want_per_device_stats = false;
 		wlogprint("Output mode reset to normal\n");
+		switch_compact();
 		goto retry;
 	} else if (!strncasecmp(&input, "d", 1)) {
 		opt_debug ^= true;
@@ -3828,6 +3868,11 @@ retry:
 			opt_quiet = false;
 		wlogprint("Debug mode %s\n", opt_debug ? "enabled" : "disabled");
 		goto retry;
+	} else if (!strncasecmp(&input, "m", 1)) {
+		opt_compact ^= true;
+		wlogprint("Compact mode %s\n", opt_compact ? "enabled" : "disabled");
+		switch_compact();
+		goto retry;
 	} else if (!strncasecmp(&input, "p", 1)) {
 		want_per_device_stats ^= true;
 		opt_log_output = want_per_device_stats;
@@ -4278,11 +4323,11 @@ static void *stratum_thread(void *userdata)
 
 		FD_ZERO(&rd);
 		FD_SET(pool->sock, &rd);
-		timeout.tv_sec = 120;
+		timeout.tv_sec = 90;
 		timeout.tv_usec = 0;
 
 		/* The protocol specifies that notify messages should be sent
-		 * every minute so if we fail to receive any for 2 minutes we
+		 * every minute so if we fail to receive any for 90 seconds we
 		 * assume the connection has been dropped and treat this pool
 		 * as dead */
 		select(pool->sock + 1, &rd, NULL, NULL, &timeout);
@@ -5646,6 +5691,7 @@ static void print_summary(void)
 
 	applog(LOG_WARNING, "Average hashrate: %.1f %shash/s", displayed_hashes, mhash_base? "Mega" : "Kilo");
 	applog(LOG_WARNING, "Solved blocks: %d", found_blocks);
+	applog(LOG_WARNING, "Best share difficulty: %s", best_share);
 	applog(LOG_WARNING, "Queued work requests: %d", total_getworks);
 	applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected);
 	applog(LOG_WARNING, "Accepted shares: %d", total_accepted);
@@ -6291,12 +6337,13 @@ int main(int argc, char *argv[])
 	for (i = 0; i < total_devices; ++i)
 		devices[i]->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 
-	logstart += total_devices;
-	logcursor = logstart + 1;
-
+	if (!opt_compact) {
+		logstart += total_devices;
+		logcursor = logstart + 1;
 #ifdef HAVE_CURSES
-	check_winsizes();
+		check_winsizes();
 #endif
+	}
 
 	if (!total_pools) {
 		applog(LOG_WARNING, "Need to specify at least one pool server.");

+ 1 - 1
configure.ac

@@ -2,7 +2,7 @@
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_maj], [2])
 m4_define([v_min], [8])
-m4_define([v_mic], [5])
+m4_define([v_mic], [6])
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_ver], [v_maj.v_min.v_mic])
 m4_define([lt_rev], m4_eval(v_maj + v_min))

+ 40 - 32
util.c

@@ -196,39 +196,41 @@ out:
 	return ptrlen;
 }
 
-int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd,
-			     curlsocktype __maybe_unused purpose)
+static int keep_sockalive(SOCKETTYPE fd)
 {
-	int tcp_keepidle = 120;
-	int tcp_keepintvl = 120;
+	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;
@@ -236,12 +238,26 @@ int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t 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,
+			     curlsocktype __maybe_unused purpose)
+{
+	return keep_sockalive(fd);
 }
 
 static void last_nettime(struct timeval *last)
@@ -823,6 +839,7 @@ bool extract_sockaddr(struct pool *pool, char *url)
 	struct addrinfo hints, *res;
 	int url_len, port_len = 0;
 
+	pool->sockaddr_url = url;
 	url_begin = strstr(url, "//");
 	if (!url_begin)
 		url_begin = url;
@@ -881,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);
@@ -891,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;
@@ -925,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, "");
 }
@@ -962,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");
@@ -973,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) {
@@ -1314,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))
@@ -1327,7 +1340,8 @@ 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_CONNECTTIMEOUT, 60);
+	curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
 	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
 	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 	curl_easy_setopt(curl, CURLOPT_URL, s);
@@ -1346,6 +1360,7 @@ bool initiate_stratum(struct pool *pool)
 		goto out;
 	}
 	curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock);
+	keep_sockalive(pool->sock);
 
 	sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);
 
@@ -1414,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;
 }