[GB.NET.CURL]
* BUG: Fix memory leaks when asynchronous clients are pending when quitting the program. git-svn-id: svn://localhost/gambas/trunk@5392 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
parent
76709ee739
commit
4512fa0c1d
4 changed files with 79 additions and 40 deletions
|
@ -38,12 +38,41 @@
|
||||||
#include "CCurl.h"
|
#include "CCurl.h"
|
||||||
#include "CProxy.h"
|
#include "CProxy.h"
|
||||||
|
|
||||||
|
|
||||||
DECLARE_EVENT(EVENT_FINISHED);
|
DECLARE_EVENT(EVENT_FINISHED);
|
||||||
DECLARE_EVENT(EVENT_ERROR);
|
DECLARE_EVENT(EVENT_ERROR);
|
||||||
DECLARE_EVENT(EVENT_CONNECT);
|
DECLARE_EVENT(EVENT_CONNECT);
|
||||||
DECLARE_EVENT(EVENT_READ);
|
DECLARE_EVENT(EVENT_READ);
|
||||||
|
|
||||||
|
static CCURL *_async_list = NULL;
|
||||||
|
|
||||||
|
static void add_to_async_list(CCURL *_object)
|
||||||
|
{
|
||||||
|
if (THIS->in_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "add_to_async_list: %p\n", THIS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GB.List.Add(&_async_list, THIS, &THIS->list);
|
||||||
|
THIS->in_list = TRUE;
|
||||||
|
GB.Ref(THIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_from_async_list(CCURL *_object)
|
||||||
|
{
|
||||||
|
if (!THIS->in_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "remove_from_async_list: %p\n", THIS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GB.List.Remove(&_async_list, THIS, &THIS->list);
|
||||||
|
THIS->in_list = FALSE;
|
||||||
|
GB.Unref(POINTER(&_object));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
CURLM : a pointer to use curl_multi interface,
|
CURLM : a pointer to use curl_multi interface,
|
||||||
allowing asynchrnous work without using threads
|
allowing asynchrnous work without using threads
|
||||||
|
@ -198,9 +227,6 @@ void CURL_manage_error(void *_object, int error)
|
||||||
THIS_STATUS = (- (1000 + error));
|
THIS_STATUS = (- (1000 + error));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (THIS->async)
|
|
||||||
GB.Unref(POINTER(&_object));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CURL_init_stream(void *_object)
|
void CURL_init_stream(void *_object)
|
||||||
|
@ -262,29 +288,34 @@ static void CCURL_post_curl(intptr_t data)
|
||||||
|
|
||||||
void CURL_stop(void *_object)
|
void CURL_stop(void *_object)
|
||||||
{
|
{
|
||||||
|
if (THIS_STATUS == NET_INACTIVE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (THIS_CURL)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
fprintf(stderr, "-- CURL_stop: [%p] curl_multi_remove_handle(%p)\n", THIS, THIS_CURL);
|
||||||
|
#endif
|
||||||
|
curl_multi_remove_handle(CCURL_multicurl,THIS_CURL);
|
||||||
|
#if DEBUG
|
||||||
|
fprintf(stderr, "-- CURL_stop: [%p] curl_easy_cleanup(%p)\n", THIS, THIS_CURL);
|
||||||
|
#endif
|
||||||
|
curl_easy_cleanup(THIS_CURL);
|
||||||
|
THIS_CURL = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (THIS_FILE)
|
if (THIS_FILE)
|
||||||
{
|
{
|
||||||
fclose(THIS_FILE);
|
fclose(THIS_FILE);
|
||||||
THIS_FILE = NULL;
|
THIS_FILE = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (THIS_CURL)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
fprintf(stderr, "-- [%p] curl_multi_remove_handle(%p)\n", THIS, THIS_CURL);
|
|
||||||
#endif
|
|
||||||
curl_multi_remove_handle(CCURL_multicurl,THIS_CURL);
|
|
||||||
#if DEBUG
|
|
||||||
fprintf(stderr, "-- [%p] curl_easycleanup(%p)\n", THIS, THIS_CURL);
|
|
||||||
#endif
|
|
||||||
curl_easy_cleanup(THIS_CURL);
|
|
||||||
THIS_CURL = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
THIS_STATUS = NET_INACTIVE;
|
THIS_STATUS = NET_INACTIVE;
|
||||||
|
|
||||||
|
remove_from_async_list(THIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Curl_init_post(void)
|
static void init_post(void)
|
||||||
{
|
{
|
||||||
if (CCURL_pipe[0]!=-1) return;
|
if (CCURL_pipe[0]!=-1) return;
|
||||||
|
|
||||||
|
@ -301,9 +332,9 @@ static void Curl_init_post(void)
|
||||||
|
|
||||||
void CURL_start_post(void *_object)
|
void CURL_start_post(void *_object)
|
||||||
{
|
{
|
||||||
Curl_init_post();
|
init_post();
|
||||||
curl_multi_add_handle(CCURL_multicurl, THIS_CURL);
|
curl_multi_add_handle(CCURL_multicurl, THIS_CURL);
|
||||||
GB.Ref(THIS);
|
add_to_async_list(THIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CURL_check_active(void *_object)
|
bool CURL_check_active(void *_object)
|
||||||
|
@ -471,19 +502,10 @@ BEGIN_METHOD_VOID(Curl_free)
|
||||||
fprintf(stderr, "Curl_free: %p\n", THIS);
|
fprintf(stderr, "Curl_free: %p\n", THIS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CURL_stop(THIS);
|
||||||
|
|
||||||
GB.FreeString(&THIS_URL);
|
GB.FreeString(&THIS_URL);
|
||||||
|
|
||||||
if (THIS_FILE)
|
|
||||||
fclose(THIS_FILE);
|
|
||||||
|
|
||||||
if (THIS_CURL)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
fprintf(stderr, "-- [%p] curl_easy_cleanup(%p)\n", THIS, THIS_CURL);
|
|
||||||
#endif
|
|
||||||
curl_easy_cleanup(THIS_CURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CURL_user_clear(&THIS->user);
|
CURL_user_clear(&THIS->user);
|
||||||
CURL_proxy_clear(&THIS->proxy.proxy);
|
CURL_proxy_clear(&THIS->proxy.proxy);
|
||||||
|
|
||||||
|
@ -500,9 +522,24 @@ END_METHOD
|
||||||
|
|
||||||
BEGIN_METHOD_VOID(Curl_exit)
|
BEGIN_METHOD_VOID(Curl_exit)
|
||||||
|
|
||||||
|
CCURL *curl, *next;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
fprintf(stderr, "-- CURL_exit: clear async list\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
curl = _async_list;
|
||||||
|
while (curl)
|
||||||
|
{
|
||||||
|
next = curl->list.next;
|
||||||
|
remove_from_async_list(curl);
|
||||||
|
curl = next;
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
fprintf(stderr, "-- curl_multi_cleanup()\n");
|
fprintf(stderr, "-- curl_multi_cleanup()\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
curl_multi_cleanup(CCURL_multicurl);
|
curl_multi_cleanup(CCURL_multicurl);
|
||||||
|
|
||||||
END_METHOD
|
END_METHOD
|
||||||
|
|
|
@ -58,17 +58,19 @@ typedef
|
||||||
struct {
|
struct {
|
||||||
GB_BASE ob;
|
GB_BASE ob;
|
||||||
GB_STREAM stream;
|
GB_STREAM stream;
|
||||||
|
GB_LIST list; // List of async curl objects
|
||||||
int status;
|
int status;
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
char *url;
|
char *url;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
CPROXY proxy;
|
CPROXY proxy;
|
||||||
CURL_USER user;
|
CURL_USER user;
|
||||||
bool async;
|
|
||||||
int timeout;
|
int timeout;
|
||||||
int method; // 0->Get, 1->Put
|
int method; // 0->Get, 1->Put
|
||||||
bool debug;
|
|
||||||
char *data;
|
char *data;
|
||||||
|
unsigned async : 1;
|
||||||
|
unsigned in_list : 1;
|
||||||
|
unsigned debug : 1;
|
||||||
}
|
}
|
||||||
CCURL;
|
CCURL;
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ static void ftp_initialize_curl_handle(void *_object)
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_TIMEOUT,THIS->timeout);
|
curl_easy_setopt(THIS_CURL, CURLOPT_TIMEOUT,THIS->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_VERBOSE, THIS->debug);
|
curl_easy_setopt(THIS_CURL, CURLOPT_VERBOSE, (bool)THIS->debug);
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_PRIVATE,(char*)_object);
|
curl_easy_setopt(THIS_CURL, CURLOPT_PRIVATE,(char*)_object);
|
||||||
|
|
||||||
CURL_proxy_set(&THIS->proxy.proxy,THIS_CURL);
|
CURL_proxy_set(&THIS->proxy.proxy,THIS_CURL);
|
||||||
|
@ -280,7 +280,7 @@ END_METHOD
|
||||||
|
|
||||||
BEGIN_METHOD_VOID(FtpClient_free)
|
BEGIN_METHOD_VOID(FtpClient_free)
|
||||||
|
|
||||||
CURL_stop(_object);
|
//CURL_stop(_object);
|
||||||
ftp_reset(THIS_FTP);
|
ftp_reset(THIS_FTP);
|
||||||
|
|
||||||
END_METHOD
|
END_METHOD
|
||||||
|
|
|
@ -188,7 +188,7 @@ static void http_initialize_curl_handle(void *_object, GB_ARRAY custom_headers)
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_TIMEOUT,THIS->timeout);
|
curl_easy_setopt(THIS_CURL, CURLOPT_TIMEOUT,THIS->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_VERBOSE, THIS->debug);
|
curl_easy_setopt(THIS_CURL, CURLOPT_VERBOSE, (bool)THIS->debug);
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_PRIVATE,(char*)_object);
|
curl_easy_setopt(THIS_CURL, CURLOPT_PRIVATE,(char*)_object);
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_USERAGENT, THIS_HTTP->sUserAgent);
|
curl_easy_setopt(THIS_CURL, CURLOPT_USERAGENT, THIS_HTTP->sUserAgent);
|
||||||
curl_easy_setopt(THIS_CURL, CURLOPT_ENCODING, THIS_HTTP->encoding);
|
curl_easy_setopt(THIS_CURL, CURLOPT_ENCODING, THIS_HTTP->encoding);
|
||||||
|
@ -502,7 +502,7 @@ END_METHOD
|
||||||
|
|
||||||
BEGIN_METHOD_VOID(HttpClient_free)
|
BEGIN_METHOD_VOID(HttpClient_free)
|
||||||
|
|
||||||
CURL_stop(_object);
|
//CURL_stop(_object);
|
||||||
http_reset(THIS);
|
http_reset(THIS);
|
||||||
|
|
||||||
GB.FreeString(&THIS_HTTP->sUserAgent);
|
GB.FreeString(&THIS_HTTP->sUserAgent);
|
||||||
|
|
Loading…
Reference in a new issue