Commit ae13c93b authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Reported in #1561470 (http://curl.haxx.se/bug/view.cgi?id=1561470), libcurl

would crash if a bad function sequence was used when shutting down after
using the multi interface (i.e using easy_cleanup after multi_cleanup) so
precautions have been added to make sure it doesn't any more - test case 529
was added to verify.
parent b9f8a4a4
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -6,6 +6,18 @@

                                  Changelog

Daniel (28 September 2006)
- Reported in #1561470 (http://curl.haxx.se/bug/view.cgi?id=1561470), libcurl
  would crash if a bad function sequence was used when shutting down after
  using the multi interface (i.e using easy_cleanup after multi_cleanup) so
  precautions have been added to make sure it doesn't any more - test case 529
  was added to verify.

Daniel (27 September 2006)
- The URL in the cookie jar file is now changed since it was giving a 404.
  Reported by Timothy Stone. The new URL will take the visitor to a curl web
  site mirror with the document.

Daniel (24 September 2006)
- Bernard Leak fixed configure --with-gssapi-libs.

+6 −2
Original line number Diff line number Diff line
@@ -11,10 +11,11 @@ Curl and libcurl 7.16.0

This release includes the following changes:

 o curl_multi_socket() and family are suitable to start using
 o uses WSAPoll() on Windows Vista
 o (FTP) --ftp-ssl-control was added
 o CURLOPT_SSL_SESSIONID_CACHE and --no-sessionid added
 o CURLMOPT_PIPELINING added for enabling pipelined transfers
 o CURLMOPT_PIPELINING added for enabling HTTP pipelined transfers
 o multi handles now have a shared connection cache
 o Added support for other MS-DOS compilers (besides djgpp)
 o CURLOPT_SOCKOPTFUNCTION and CURLOPT_SOCKOPTDATA were added
@@ -23,6 +24,9 @@ This release includes the following changes:

This release includes the following bugfixes:

 o multi interface crash if bad function call order was used for cleanup
 o put a new URL in saved cookie jar files
 o configure --with-gssapi-libs
 o SOCKS proxy connection fixes
 o (FTP) a failed upload does not invalidate the control connection
 o proxy URL with user name and empty password or no password at all now work
@@ -55,6 +59,6 @@ advice from friends like these:
 Domenico Andreoli, Armel Asselin, Gisle Vanem, Yang Tse, Andrew Biggs,
 Peter Sylvester, David McCreedy, Dmitriy Sergeyev, Dmitry Rechkin,
 Jari Sundell, Ravi Pratap, Michele Bini, Jeff Pohlmeyer, Michael Wallner,
 Mike Protts, Cory Nelson
 Mike Protts, Cory Nelson, Bernard Leak

        Thanks! (and sorry if I forgot to mention someone)
+28 −10
Original line number Diff line number Diff line
@@ -172,6 +172,8 @@ static bool multi_conn_using(struct Curl_multi *multi,
                             struct SessionHandle *data);
static void singlesocket(struct Curl_multi *multi,
                         struct Curl_one_easy *easy);
static void add_closure(struct Curl_multi *multi,
                        struct SessionHandle *data);

/* always use this function to change state, to make debugging easier */
static void multistate(struct Curl_one_easy *easy, CURLMstate state)
@@ -539,18 +541,29 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
       we need to add this handle to the list of "easy handles kept around for
       nice connection closures".
     */
    if(multi_conn_using(multi, easy->easy_handle))
    if(multi_conn_using(multi, easy->easy_handle)) {
      /* There's at least one connection using this handle so we must keep
         this handle around. We also keep the connection cache pointer
         pointing to the shared one since that will be used on close as
         well. */
      easy->easy_handle->state.shared_conn = multi;
    else
      if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI)

      /* this handle is still being used by a shared connection cache and
         thus we leave it around for now */
      add_closure(multi, easy->easy_handle);
    }

    if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
      /* if this was using the shared connection cache we clear the pointer
           to that */
         to that since we're not part of that handle anymore */
      easy->easy_handle->state.connc = NULL;

      /* and modify the connectindex since this handle can't point to the
         connection cache anymore */
      if(easy->easy_conn)
        easy->easy_conn->connectindex = -1;
    }

    /* change state without using multistate(), only to make singlesocket() do
       what we want */
    easy->state = CURLM_STATE_COMPLETED;
@@ -1320,15 +1333,20 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
    /* go over all connections that have close actions */
    for(i=0; i< multi->connc->num; i++) {
      if(multi->connc->connects[i] &&
         multi->connc->connects[i]->protocol & PROT_CLOSEACTION)
         multi->connc->connects[i]->protocol & PROT_CLOSEACTION) {
        Curl_disconnect(multi->connc->connects[i]);
        multi->connc->connects[i] = NULL;
      }
    }
    /* now walk through the list of handles we kept around only to be
       able to close connections "properly" */
    cl = multi->closure;
    while(cl) {
      cl->easy_handle->state.shared_conn = NULL; /* no more shared */
      Curl_close(cl->easy_handle); /* close handle */
      if(cl->easy_handle->state.closed)
        /* close handle only if curl_easy_cleanup() already has been called
           for this easy handle */
        Curl_close(cl->easy_handle);
      n = cl->next;
      free(cl);
      cl= n;
@@ -1780,7 +1798,7 @@ static bool multi_conn_using(struct Curl_multi *multi,

/* add the given data pointer to the list of 'closure handles' that are
   kept around only to be able to close some connections nicely */
void Curl_multi_add_closure(struct Curl_multi *multi,
static void add_closure(struct Curl_multi *multi,
                        struct SessionHandle *data)
{
  int i;
+0 −3
Original line number Diff line number Diff line
@@ -32,9 +32,6 @@ void Curl_multi_rmeasy(void *multi, CURL *data);

bool Curl_multi_canPipeline(struct Curl_multi* multi);

void Curl_multi_add_closure(struct Curl_multi *multi,
                            struct SessionHandle *data);

/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16

+16 −14
Original line number Diff line number Diff line
@@ -269,7 +269,9 @@ CURLcode Curl_close(struct SessionHandle *data)
                      the multi handle, since that function uses the magic
                      field! */

  if(data->state.connc && (data->state.connc->type == CONNCACHE_PRIVATE)) {
  if(data->state.connc) {

    if(data->state.connc->type == CONNCACHE_PRIVATE) {
      /* close all connections still alive that are in the private connection
         cache, as we no longer have the pointer left to the shared one. */
      close_connections(data);
@@ -277,6 +279,14 @@ CURLcode Curl_close(struct SessionHandle *data)
      /* free the connection cache if allocated privately */
      Curl_rm_connc(data->state.connc);
    }
  }

  if(data->state.shared_conn) {
    /* marked to be used by a pending connection so we can't kill this handle
       just yet */
    data->state.closed = TRUE;
    return CURLE_OK;
  }

  if ( ! (data->share && data->share->hostcache) ) {
    if ( !Curl_global_host_cache_use(data)) {
@@ -284,14 +294,6 @@ CURLcode Curl_close(struct SessionHandle *data)
    }
  }

  if(data->state.shared_conn) {
    /* this handle is still being used by a shared connection cache and thus
       we leave it around for now */
    Curl_multi_add_closure(data->state.shared_conn, data);

    return CURLE_OK;
  }

  /* Free the pathbuffer */
  Curl_safefree(data->reqdata.pathbuffer);
  Curl_safefree(data->reqdata.proto.generic);
Loading