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.
This commit is contained in:
Daniel Stenberg 2005-01-10 10:07:07 +00:00
parent 83bab78bda
commit 21bb852750
8 changed files with 101 additions and 2 deletions

View File

@ -8,6 +8,11 @@
Daniel (10 January 2005) Daniel (10 January 2005)
- 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.
- Hzhijun reported a memory leak in the SSL certificate code, that leaked the - Hzhijun reported a memory leak in the SSL certificate code, that leaked the
remote certificate name when it didn't match the used host name. remote certificate name when it didn't match the used host name.

View File

@ -16,6 +16,7 @@ This release includes the following changes:
This release includes the following bugfixes: This release includes the following bugfixes:
o memory problem with cleaning up multi interface
o SSL certificate name memory leak o SSL certificate name memory leak
o -d with -G to multiple URLs crashed o -d with -G to multiple URLs crashed
o double va_list access crash fixed o double va_list access crash fixed
@ -33,6 +34,6 @@ advice from friends like these:
Dan Fandrich, Peter Pentchev, Marcin Konicki, Rune Kleveland, David Shaw, Dan Fandrich, Peter Pentchev, Marcin Konicki, Rune Kleveland, David Shaw,
Werner Koch, Gisle Vanem, Alex Neblett, Kai Sommerfeld, Marty Kuhrt, Werner Koch, Gisle Vanem, Alex Neblett, Kai Sommerfeld, Marty Kuhrt,
Hzhijun Hzhijun, Pavel Orehov
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@ -82,6 +82,7 @@
#include "share.h" #include "share.h"
#include "memory.h" #include "memory.h"
#include "progress.h" #include "progress.h"
#include "easy.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@ -403,6 +404,15 @@ void curl_easy_cleanup(CURL *curl)
Curl_close(data); 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 * curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar. * information from a performed transfer and similar.

31
lib/easy.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __EASY_H
#define __EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, 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 */

View File

@ -43,6 +43,7 @@
#include "connect.h" #include "connect.h"
#include "progress.h" #include "progress.h"
#include "memory.h" #include "memory.h"
#include "easy.h"
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
@ -174,6 +175,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
if(easy->next) if(easy->next)
easy->next->prev = easy; easy->next->prev = easy;
Curl_easy_addmulti(easy_handle, multi_handle);
/* increase the node-counter */ /* increase the node-counter */
multi->num_easy++; multi->num_easy++;
@ -584,6 +587,13 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
return result; 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) CURLMcode curl_multi_cleanup(CURLM *multi_handle)
{ {
struct Curl_multi *multi=(struct Curl_multi *)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; nexteasy=easy->next;
/* clear out the usage of the shared DNS cache */ /* clear out the usage of the shared DNS cache */
easy->easy_handle->hostcache = NULL; easy->easy_handle->hostcache = NULL;
easy->easy_handle->multi = NULL;
if (easy->msg) if (easy->msg)
free(easy->msg); free(easy->msg);

31
lib/multi.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __MULTI_H
#define __MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, 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 */

View File

@ -118,6 +118,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
#include "http_digest.h" #include "http_digest.h"
#include "http_negotiate.h" #include "http_negotiate.h"
#include "select.h" #include "select.h"
#include "multi.h"
/* And now for the protocols */ /* And now for the protocols */
#include "ftp.h" #include "ftp.h"
@ -196,6 +197,10 @@ void Curl_safefree(void *ptr)
CURLcode Curl_close(struct SessionHandle *data) 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 */ /* Loop through all open connections and kill them one by one */
while(-1 != ConnectionKillOne(data)) while(-1 != ConnectionKillOne(data))
; /* empty loop */ ; /* empty loop */
@ -1422,7 +1427,10 @@ CURLcode Curl_disconnect(struct connectdata *conn)
data = conn->data; 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 */ Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST) #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)

View File

@ -971,6 +971,8 @@ struct UserDefined {
struct SessionHandle { struct SessionHandle {
curl_hash *hostcache; 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 Curl_share *share; /* Share, handles global variable mutexing */
struct UserDefined set; /* values set by the libcurl user */ struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */ struct DynamicStatic change; /* possibly modified userdefined data */