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)
- 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
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:
o memory problem with cleaning up multi interface
o SSL certificate name memory leak
o -d with -G to multiple URLs crashed
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,
Werner Koch, Gisle Vanem, Alex Neblett, Kai Sommerfeld, Marty Kuhrt,
Hzhijun
Hzhijun, Pavel Orehov
Thanks! (and sorry if I forgot to mention someone)

View File

@ -82,6 +82,7 @@
#include "share.h"
#include "memory.h"
#include "progress.h"
#include "easy.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -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.

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 "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);

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_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)

View File

@ -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 */