diff options
author | Brad Spencer <bspencer@blackberry.com> | 2018-12-14 17:18:22 -0400 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2019-01-07 10:05:20 +0100 |
commit | 84a30d0a419ad95c53cbdfc76eb2eb75d2e51835 (patch) | |
tree | 5a7c04df819a465e7711f9c9b0c831f5532b0326 /tests/libtest/lib1592.c | |
parent | ebe658c1e5a6577178981a7f406794699305be5c (diff) |
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
Diffstat (limited to 'tests/libtest/lib1592.c')
-rw-r--r-- | tests/libtest/lib1592.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/tests/libtest/lib1592.c b/tests/libtest/lib1592.c new file mode 100644 index 000000000..5e6bf04eb --- /dev/null +++ b/tests/libtest/lib1592.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * 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 + * are also available at https://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. + * + ***************************************************************************/ +/* + * See https://github.com/curl/curl/issues/3371 + * + * This test case checks whether curl_multi_remove_handle() cancels + * asynchronous DNS resolvers without blocking where possible. Obviously, it + * only tests whichever resolver cURL is actually built with. + */ + +/* We're willing to wait a very generous two seconds for the removal. This is + as low as we can go while still easily supporting SIGALRM timing for the + non-threaded blocking resolver. It doesn't matter that much because when + the test passes, we never wait this long. */ +#define TEST_HANG_TIMEOUT 2 * 1000 + +#include "test.h" +#include "testutil.h" + +#include <sys/stat.h> + +int test(char *URL) +{ + int stillRunning; + CURLM *multiHandle = NULL; + CURL *curl = NULL; + CURLMcode res = CURLM_OK; + int timeout; + + global_init(CURL_GLOBAL_ALL); + + multi_init(multiHandle); + + easy_init(curl); + + easy_setopt(curl, CURLOPT_VERBOSE, 1L); + easy_setopt(curl, CURLOPT_URL, URL); + + /* Set a DNS server that hopefully will not respond when using c-ares. */ + if(curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, "0.0.0.0") == CURLE_OK) + /* Since we could set the DNS server, presume we are working with a + resolver that can be cancelled (i.e. c-ares). Thus, + curl_multi_remove_handle() should not block even when the resolver + request is outstanding. So, set a request timeout _longer_ than the + test hang timeout so we will fail if the handle removal call incorrectly + blocks. */ + timeout = TEST_HANG_TIMEOUT * 2; + else { + /* If we can't set the DNS server, presume that we are configured to use a + resolver that can't be cancelled (i.e. the threaded resolver or the + non-threaded blocking resolver). So, we just test that the + curl_multi_remove_handle() call does finish well within our test + timeout. + + But, it is very unlikely that the resolver request will take any time at + all because we haven't been able to configure the resolver to use an + non-responsive DNS server. At least we exercise the flow. + */ + fprintf(stderr, + "CURLOPT_DNS_SERVERS not supported; " + "assuming curl_multi_remove_handle() will block\n"); + timeout = TEST_HANG_TIMEOUT / 2; + } + + /* Setting a timeout on the request should ensure that even if we have to + wait for the resolver during curl_multi_remove_handle(), it won't take + longer than this, because the resolver request inherits its timeout from + this. */ + easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout); + + multi_add_handle(multiHandle, curl); + + /* This should move the handle from INIT => CONNECT => WAITRESOLVE. */ + fprintf(stderr, "curl_multi_perform()...\n"); + multi_perform(multiHandle, &stillRunning); + fprintf(stderr, "curl_multi_perform() succeeded\n"); + + /* Start measuring how long it takes to remove the handle. */ + fprintf(stderr, "curl_multi_remove_handle()...\n"); + start_test_timing(); + res = curl_multi_remove_handle(multiHandle, curl); + if(res) { + fprintf(stderr, "curl_multi_remove_handle() failed, " + "with code %d\n", (int)res); + goto test_cleanup; + } + fprintf(stderr, "curl_multi_remove_handle() succeeded\n"); + + /* Fail the test if it took too long to remove. This happens after the fact, + and says "it seems that it would have run forever", which isn't true, but + it's close enough, and simple to do. */ + abort_on_test_timeout(); + +test_cleanup: + curl_easy_cleanup(curl); + curl_multi_cleanup(multiHandle); + curl_global_cleanup(); + + return (int)res; +} |