aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2005-01-10 10:07:07 +0000
committerDaniel Stenberg <daniel@haxx.se>2005-01-10 10:07:07 +0000
commit21bb852750d39a51d20e29652d29b0be5fdbef38 (patch)
tree5b38e412a90180dabacaaec4d17428171001de77 /lib
parent83bab78bdaeecc7fd5cae3c035d5239b0d38468f (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/easy.c10
-rw-r--r--lib/easy.h31
-rw-r--r--lib/multi.c11
-rw-r--r--lib/multi.h31
-rw-r--r--lib/url.c10
-rw-r--r--lib/urldata.h2
6 files changed, 94 insertions, 1 deletions
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 <curl/mprintf.h>
@@ -404,6 +405,15 @@ void curl_easy_cleanup(CURL *curl)
}
/*
+ * 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, <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 */
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, <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 */
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 */