diff options
author | Daniel Stenberg <daniel@haxx.se> | 2010-03-23 13:18:30 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2010-03-23 13:18:30 +0100 |
commit | 2a94293efd3896eca067c4b53ccfdf362a042db2 (patch) | |
tree | 5381a0efea8bb9dd925e5c859ac4bc2f3666d35a /lib/multi.c | |
parent | b33ddd615aad0459a9022b1c932e1831a0dbc965 (diff) | |
download | curl-2a94293efd3896eca067c4b53ccfdf362a042db2.tar.gz |
delayed easy handle kill caused double Curl_close() call
Hauke Duden provided an example program that made the multi
interface crash. His example simply used the multi interface and
did first one FTP transfer and after completion it used a second
easy handle and did another FTP transfer on the same FTP server.
This triggered a bug in the "delayed easy handle kill" system
that curl uses: when an FTP connection is left alive it must keep
an easy handle around internally - only for the purpose of having
an easy handle when it later disconnects it. The code assumed
that when the easy handle was removed and an internal reference
was made, that version could be killed later on when a new easy
handle came using the same connection. This was wrong as Hauke's
example showed that the removed handle wasn't killed for real
until later. This caused a double close attempt => segfault.
Diffstat (limited to 'lib/multi.c')
-rw-r--r-- | lib/multi.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/lib/multi.c b/lib/multi.c index b24021280..d04fcf660 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -2416,10 +2416,16 @@ static CURLMcode add_closure(struct Curl_multi *multi, if(!inuse) { /* cl->easy_handle is now killable */ - infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle); + /* unmark it as not having a connection around that uses it anymore */ cl->easy_handle->state.shared_conn= NULL; - Curl_close(cl->easy_handle); + + if(cl->easy_handle->state.closed) { + infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle); + /* close handle only if curl_easy_cleanup() already has been called + for this easy handle */ + Curl_close(cl->easy_handle); + } if(p) p->next = n; else |