Browse Source

attempt to fix memory issues when doing curl calls

From curl CURLOPT_ERRORBUFFER docs: You must keep the associated storage available until libcurl no longer needs it. Failing to do so will cause very odd behavior or even crashes. libcurl will need it until you call curl_easy_cleanup(3) or you set the same option again to use a different pointer.
djm34
Jan Berdajs 11 years ago
parent
commit
ff05aacdc3
  1. 3
      miner.h
  2. 27
      sgminer.c
  3. 15
      util.c

3
miner.h

@ -966,7 +966,7 @@ extern pthread_rwlock_t netacc_lock;
extern const uint32_t sha256_init_state[]; extern const uint32_t sha256_init_state[];
#ifdef HAVE_LIBCURL #ifdef HAVE_LIBCURL
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, extern json_t *json_rpc_call(CURL *curl, char *curl_err_str, const char *url, const char *userpass,
const char *rpc_req, bool, bool, int *, const char *rpc_req, bool, bool, int *,
struct pool *pool, bool); struct pool *pool, bool);
#endif #endif
@ -1110,6 +1110,7 @@ typedef struct _dev_blk_ctx {
struct curl_ent { struct curl_ent {
CURL *curl; CURL *curl;
char curl_err_str[CURL_ERROR_SIZE];
struct list_head node; struct list_head node;
struct timeval tv; struct timeval tv;
}; };

27
sgminer.c

@ -1918,12 +1918,13 @@ static void update_gbt(struct pool *pool)
int rolltime; int rolltime;
json_t *val; json_t *val;
CURL *curl; CURL *curl;
char curl_err_str[CURL_ERROR_SIZE];
curl = curl_easy_init(); curl = curl_easy_init();
if (unlikely(!curl)) if (unlikely(!curl))
quit (1, "CURL initialisation failed in update_gbt"); quit (1, "CURL initialisation failed in update_gbt");
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, val = json_rpc_call(curl, curl_err_str, pool->rpc_url, pool->rpc_userpass,
pool->rpc_req, true, false, &rolltime, pool, false); pool->rpc_req, true, false, &rolltime, pool, false);
if (val) { if (val) {
@ -2172,7 +2173,7 @@ out:
#else /* HAVE_LIBCURL */ #else /* HAVE_LIBCURL */
/* Always true with stratum */ /* Always true with stratum */
#define pool_localgen(pool) (true) #define pool_localgen(pool) (true)
#define json_rpc_call(curl, url, userpass, rpc_req, probe, longpoll, rolltime, pool, share) (NULL) #define json_rpc_call(curl, curl_err_str, url, userpass, rpc_req, probe, longpoll, rolltime, pool, share) (NULL)
#define work_decode(pool, work, val) (false) #define work_decode(pool, work, val) (false)
#define gen_gbt_work(pool, work) {} #define gen_gbt_work(pool, work) {}
#endif /* HAVE_LIBCURL */ #endif /* HAVE_LIBCURL */
@ -2844,7 +2845,7 @@ static void print_status(int thr_id)
text_print_status(thr_id); text_print_status(thr_id);
} }
static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) static bool submit_upstream_work(struct work *work, CURL *curl, char *curl_err_str, bool resubmit)
{ {
char *hexstr = NULL; char *hexstr = NULL;
json_t *val, *res, *err; json_t *val, *res, *err;
@ -2913,7 +2914,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
cgtime(&tv_submit); cgtime(&tv_submit);
/* issue JSON-RPC request */ /* issue JSON-RPC request */
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true); val = json_rpc_call(curl, curl_err_str, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true);
cgtime(&tv_submit_reply); cgtime(&tv_submit_reply);
free(s); free(s);
@ -3015,7 +3016,7 @@ out:
return rc; return rc;
} }
static bool get_upstream_work(struct work *work, CURL *curl) static bool get_upstream_work(struct work *work, CURL *curl, char *curl_err_str)
{ {
struct pool *pool = work->pool; struct pool *pool = work->pool;
struct sgminer_pool_stats *pool_stats = &(pool->sgminer_pool_stats); struct sgminer_pool_stats *pool_stats = &(pool->sgminer_pool_stats);
@ -3030,7 +3031,7 @@ static bool get_upstream_work(struct work *work, CURL *curl)
cgtime(&work->tv_getwork); cgtime(&work->tv_getwork);
val = json_rpc_call(curl, url, pool->rpc_userpass, pool->rpc_req, false, val = json_rpc_call(curl, curl_err_str, url, pool->rpc_userpass, pool->rpc_req, false,
false, &work->rolltime, pool, false); false, &work->rolltime, pool, false);
pool_stats->getwork_attempts++; pool_stats->getwork_attempts++;
@ -3571,7 +3572,7 @@ static void *submit_work_thread(void *userdata)
ce = pop_curl_entry(pool); ce = pop_curl_entry(pool);
/* submit solution to bitcoin via JSON-RPC */ /* submit solution to bitcoin via JSON-RPC */
while (!submit_upstream_work(work, ce->curl, resubmit)) { while (!submit_upstream_work(work, ce->curl, ce->curl_err_str, resubmit)) {
if (opt_lowmem) { if (opt_lowmem) {
applog(LOG_NOTICE, "%s share being discarded to minimise memory cache", get_pool_name(pool)); applog(LOG_NOTICE, "%s share being discarded to minimise memory cache", get_pool_name(pool));
break; break;
@ -5779,6 +5780,7 @@ static bool pool_active(struct pool *pool, bool pinging)
bool ret = false; bool ret = false;
json_t *val; json_t *val;
CURL *curl; CURL *curl;
char curl_err_str[CURL_ERROR_SIZE];
int rolltime = 0; int rolltime = 0;
if (pool->has_gbt) if (pool->has_gbt)
@ -5816,7 +5818,7 @@ retry_stratum:
/* Probe for GBT support on first pass */ /* Probe for GBT support on first pass */
if (!pool->probed) { if (!pool->probed) {
applog(LOG_DEBUG, "Probing for GBT support"); applog(LOG_DEBUG, "Probing for GBT support");
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, val = json_rpc_call(curl, curl_err_str, pool->rpc_url, pool->rpc_userpass,
gbt_req, true, false, &rolltime, pool, false); gbt_req, true, false, &rolltime, pool, false);
if (val) { if (val) {
bool append = false, submit = false; bool append = false, submit = false;
@ -5861,7 +5863,7 @@ retry_stratum:
} }
cgtime(&tv_getwork); cgtime(&tv_getwork);
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, val = json_rpc_call(curl, curl_err_str, pool->rpc_url, pool->rpc_userpass,
pool->rpc_req, true, false, &rolltime, pool, false); pool->rpc_req, true, false, &rolltime, pool, false);
cgtime(&tv_getwork_reply); cgtime(&tv_getwork_reply);
@ -5927,7 +5929,7 @@ retry_stratum:
pool->lp_url = (char *)malloc(siz); pool->lp_url = (char *)malloc(siz);
if (!pool->lp_url) { if (!pool->lp_url) {
applog(LOG_ERR, "Malloc failure in pool_active"); applog(LOG_ERR, "Malloc failure in pool_active");
return false; goto out;
} }
snprintf(pool->lp_url, siz, "%s%s%s", pool->rpc_url, need_slash ? "/" : "", copy_start); snprintf(pool->lp_url, siz, "%s%s%s", pool->rpc_url, need_slash ? "/" : "", copy_start);
@ -6753,6 +6755,7 @@ static void *longpoll_thread(void *userdata)
struct pool *pool = NULL; struct pool *pool = NULL;
char threadname[16]; char threadname[16];
CURL *curl = NULL; CURL *curl = NULL;
char curl_err_str[CURL_ERROR_SIZE];
int failures = 0; int failures = 0;
char lpreq[1024]; char lpreq[1024];
char *lp_url; char *lp_url;
@ -6824,7 +6827,7 @@ retry_pool:
* so always establish a fresh connection instead of relying on * so always establish a fresh connection instead of relying on
* a persistent one. */ * a persistent one. */
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
val = json_rpc_call(curl, lp_url, pool->rpc_userpass, val = json_rpc_call(curl, curl_err_str, lp_url, pool->rpc_userpass,
lpreq, false, true, &rolltime, pool, false); lpreq, false, true, &rolltime, pool, false);
cgtime(&reply); cgtime(&reply);
@ -8326,7 +8329,7 @@ retry:
work->pool = pool; work->pool = pool;
ce = pop_curl_entry(pool); ce = pop_curl_entry(pool);
/* obtain new work from bitcoin via JSON-RPC */ /* obtain new work from bitcoin via JSON-RPC */
if (!get_upstream_work(work, ce->curl)) { if (!get_upstream_work(work, ce->curl, ce->curl_err_str)) {
applog(LOG_DEBUG, "%s json_rpc_call failed on get work, retrying in 5s", get_pool_name(pool)); applog(LOG_DEBUG, "%s json_rpc_call failed on get work, retrying in 5s", get_pool_name(pool));
/* Make sure the pool just hasn't stopped serving /* Make sure the pool just hasn't stopped serving
* requests but is up as we'll keep hammering it */ * requests but is up as we'll keep hammering it */

15
util.c

@ -113,13 +113,11 @@ struct header_info {
static void databuf_free(struct data_buffer *db) static void databuf_free(struct data_buffer *db)
{ {
if (!db) if (db) {
return; if (db->buf) free(db->buf);
free(db->buf);
memset(db, 0, sizeof(*db)); memset(db, 0, sizeof(*db));
} }
}
static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb, static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
void *user_data) void *user_data)
@ -130,6 +128,7 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
void *newmem; void *newmem;
static const unsigned char zero = 0; static const unsigned char zero = 0;
if (len > 0) {
oldlen = db->len; oldlen = db->len;
newlen = oldlen + len; newlen = oldlen + len;
@ -141,6 +140,7 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
db->len = newlen; db->len = newlen;
memcpy((uint8_t*)db->buf + oldlen, ptr, len); memcpy((uint8_t*)db->buf + oldlen, ptr, len);
memcpy((uint8_t*)db->buf + newlen, &zero, 1); /* null terminate */ memcpy((uint8_t*)db->buf + newlen, &zero, 1); /* null terminate */
}
return len; return len;
} }
@ -154,7 +154,7 @@ static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
if (len > ub->len) if (len > ub->len)
len = ub->len; len = ub->len;
if (len) { if (len > 0) {
memcpy(ptr, ub->buf, len); memcpy(ptr, ub->buf, len);
ub->buf = (uint8_t*)ub->buf + len; ub->buf = (uint8_t*)ub->buf + len;
ub->len -= len; ub->len -= len;
@ -298,7 +298,7 @@ static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
return 0; return 0;
} }
json_t *json_rpc_call(CURL *curl, const char *url, json_t *json_rpc_call(CURL *curl, char *curl_err_str, const char *url,
const char *userpass, const char *rpc_req, const char *userpass, const char *rpc_req,
bool probe, bool longpoll, int *rolltime, bool probe, bool longpoll, int *rolltime,
struct pool *pool, bool share) struct pool *pool, bool share)
@ -307,7 +307,6 @@ json_t *json_rpc_call(CURL *curl, const char *url,
struct data_buffer all_data = {NULL, 0}; struct data_buffer all_data = {NULL, 0};
struct header_info hi = {NULL, 0, NULL, NULL, false, false, false}; struct header_info hi = {NULL, 0, NULL, NULL, false, false, false};
char len_hdr[64], user_agent_hdr[128]; char len_hdr[64], user_agent_hdr[128];
char curl_err_str[CURL_ERROR_SIZE];
struct curl_slist *headers = NULL; struct curl_slist *headers = NULL;
struct upload_buffer upload_data; struct upload_buffer upload_data;
json_t *val, *err_val, *res_val; json_t *val, *err_val, *res_val;

Loading…
Cancel
Save