From 21bb852750d39a51d20e29652d29b0be5fdbef38 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 10 Jan 2005 10:07:07 +0000 Subject: Pavel Orehov reported memory problems with the multi interface in bug report #1098843. In short, a shared DNS cache was setup for a multi handle and when the shared cache was deleted before the individual easy handles, the latter cleanups caused read/writes to already freed memory. --- lib/easy.c | 10 ++++++++++ lib/easy.h | 31 +++++++++++++++++++++++++++++++ lib/multi.c | 11 +++++++++++ lib/multi.h | 31 +++++++++++++++++++++++++++++++ lib/url.c | 10 +++++++++- lib/urldata.h | 2 ++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 lib/easy.h create mode 100644 lib/multi.h (limited to 'lib') diff --git a/lib/easy.c b/lib/easy.c index 0b3774823..9310b843a 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -82,6 +82,7 @@ #include "share.h" #include "memory.h" #include "progress.h" +#include "easy.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -403,6 +404,15 @@ void curl_easy_cleanup(CURL *curl) Curl_close(data); } +/* + * Store a pointed to the multi handle within the easy handle's data struct. + */ +void Curl_easy_addmulti(struct SessionHandle *data, + void *multi) +{ + data->multi = multi; +} + /* * curl_easy_getinfo() is an external interface that allows an app to retrieve * information from a performed transfer and similar. diff --git a/lib/easy.h b/lib/easy.h new file mode 100644 index 000000000..1ef053c91 --- /dev/null +++ b/lib/easy.h @@ -0,0 +1,31 @@ +#ifndef __EASY_H +#define __EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by easy.c + */ +void Curl_easy_addmulti(struct SessionHandle *data, void *multi); + +#endif /* __EASY_H */ diff --git a/lib/multi.c b/lib/multi.c index 72e953eb1..63eb505f5 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -43,6 +43,7 @@ #include "connect.h" #include "progress.h" #include "memory.h" +#include "easy.h" /* The last #include file should be: */ #include "memdebug.h" @@ -174,6 +175,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, if(easy->next) easy->next->prev = easy; + Curl_easy_addmulti(easy_handle, multi_handle); + /* increase the node-counter */ multi->num_easy++; @@ -584,6 +587,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) return result; } +/* This is called when an easy handle is cleanup'ed that is part of a multi + handle */ +void Curl_multi_rmeasy(void *multi_handle, CURL *easy_handle) +{ + curl_multi_remove_handle(multi_handle, easy_handle); +} + CURLMcode curl_multi_cleanup(CURLM *multi_handle) { struct Curl_multi *multi=(struct Curl_multi *)multi_handle; @@ -600,6 +610,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle) nexteasy=easy->next; /* clear out the usage of the shared DNS cache */ easy->easy_handle->hostcache = NULL; + easy->easy_handle->multi = NULL; if (easy->msg) free(easy->msg); diff --git a/lib/multi.h b/lib/multi.h new file mode 100644 index 000000000..7c514e67d --- /dev/null +++ b/lib/multi.h @@ -0,0 +1,31 @@ +#ifndef __MULTI_H +#define __MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by multi.c + */ +void Curl_multi_rmeasy(void *multi, CURL *data); + +#endif /* __MULTI_H */ diff --git a/lib/url.c b/lib/url.c index bb4364302..29c35bf05 100644 --- a/lib/url.c +++ b/lib/url.c @@ -118,6 +118,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by #include "http_digest.h" #include "http_negotiate.h" #include "select.h" +#include "multi.h" /* And now for the protocols */ #include "ftp.h" @@ -196,6 +197,10 @@ void Curl_safefree(void *ptr) CURLcode Curl_close(struct SessionHandle *data) { + if(data->multi) { + /* this handle is still part of a multi handle, take care of this first */ + Curl_multi_rmeasy(data->multi, data); + } /* Loop through all open connections and kill them one by one */ while(-1 != ConnectionKillOne(data)) ; /* empty loop */ @@ -1422,7 +1427,10 @@ CURLcode Curl_disconnect(struct connectdata *conn) data = conn->data; - if(conn->dns_entry) + if(conn->dns_entry && data->hostcache) + /* if the DNS entry is still around, and the host cache is not blanked + (which it is for example when a shared one is killed by + curl_multi_cleanup() and similar stuff) */ Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST) diff --git a/lib/urldata.h b/lib/urldata.h index 1fdaac994..3936b1526 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -971,6 +971,8 @@ struct UserDefined { struct SessionHandle { curl_hash *hostcache; + void *multi; /* if non-NULL, points to the multi handle + struct of which this "belongs" */ struct Curl_share *share; /* Share, handles global variable mutexing */ struct UserDefined set; /* values set by the libcurl user */ struct DynamicStatic change; /* possibly modified userdefined data */ -- cgit v1.2.3