Unverified Commit 84a30d0a authored by Brad Spencer's avatar Brad Spencer Committed by Daniel Stenberg
Browse files

curl_multi_remove_handle() don't block terminating c-ares requests

Added Curl_resolver_kill() for all three resolver modes, which only
blocks when necessary, along with test 1592 to confirm
curl_multi_remove_handle() doesn't block unless it must.

Closes #3428
Fixes #3371
parent ebe658c1
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2019, 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
@@ -198,6 +198,17 @@ void Curl_resolver_cancel(struct connectdata *conn)
  destroy_async_data(&conn->async);
}

/*
 * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
 * never block.
 */
void Curl_resolver_kill(struct connectdata *conn)
{
  /* We don't need to check the resolver state because we can be called safely
     at any time and we always do the same thing. */
  Curl_resolver_cancel(conn);
}

/*
 * destroy_async_data() cleans up async resolver data.
 */
@@ -361,13 +372,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
/*
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * Waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
+23 −2
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2019, 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
@@ -461,14 +461,34 @@ static CURLcode resolver_error(struct connectdata *conn)
  return result;
}

/*
 * Until we gain a way to signal the resolver threads to stop early, we must
 * simply wait for them and ignore their results.
 */
void Curl_resolver_kill(struct connectdata *conn)
{
  struct thread_data *td = (struct thread_data*) conn->async.os_specific;

  /* If we're still resolving, we must wait for the threads to fully clean up,
     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
     data. */
  if(td && td->thread_hnd != curl_thread_t_null)
    (void)Curl_resolver_wait_resolv(conn, NULL);
  else
    Curl_resolver_cancel(conn);
}

/*
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * Waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
@@ -478,6 +498,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
  CURLcode result = CURLE_OK;

  DEBUGASSERT(conn && td);
  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);

  /* wait for the thread to resolve the name */
  if(Curl_thread_join(&td->thread_hnd)) {
+21 −6
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2019, 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
@@ -87,10 +87,25 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
 *
 * It is called from inside other functions to cancel currently performing
 * resolver request. Should also free any temporary resources allocated to
 * perform a request.
 * perform a request.  This never waits for resolver threads to complete.
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_cancel(struct connectdata *conn);

/*
 * Curl_resolver_kill().
 *
 * This acts like Curl_resolver_cancel() except it will block until any threads
 * associated with the resolver are complete.  This never blocks for resolvers
 * that do not use threads.  This is intended to be the "last chance" function
 * that cleans up an in-progress resolver completely (before its owner is about
 * to die).
 *
 * It is safe to call this when conn is in any state.
 */
void Curl_resolver_kill(struct connectdata *conn);

/* Curl_resolver_getsock()
 *
 * This function is called from the multi_getsock() function.  'sock' is a
@@ -117,14 +132,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
/*
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * Waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.

 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **dnsentry);
@@ -148,6 +162,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */
#define Curl_resolver_cancel(x) Curl_nop_stmt
#define Curl_resolver_kill(x) Curl_nop_stmt
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_getsock(x,y,z) 0
+2 −5
Original line number Diff line number Diff line
@@ -537,10 +537,8 @@ static CURLcode multi_done(struct connectdata **connp,
    /* Stop if multi_done() has already been called */
    return CURLE_OK;

  if(data->mstate == CURLM_STATE_WAITRESOLVE) {
    /* still waiting for the resolve to complete */
    (void)Curl_resolver_wait_resolv(conn, NULL);
  }
  /* Stop the resolver and free its own resources (but not dns_entry yet). */
  Curl_resolver_kill(conn);

  Curl_getoff_all_pipelines(data, conn);

@@ -587,7 +585,6 @@ static CURLcode multi_done(struct connectdata **connp,
  }

  data->state.done = TRUE; /* called just now! */
  Curl_resolver_cancel(conn);

  if(conn->dns_entry) {
    Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
+3 −3
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2019, 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
@@ -179,8 +179,8 @@ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
\
test1560 test1561 \
\
test1590 \
test1591 \
test1590 test1591 test1592 \
\
test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
test1608 test1609 test1620 \
\
Loading