multi: xfers_really_alive
No binary (build failed)
—
(log yok)
| @@ -531,6 +531,8 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *curl) | |
| /* set the easy handle */ | |
| multistate(data, MSTATE_INIT); | |
| + | /* not yet passed INIT state */ |
| + | data->state.really_alive = FALSE; |
| #ifdef USE_LIBPSL | |
| /* Do the same for PSL. */ | |
| @@ -570,12 +572,6 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *curl) | |
| data->set.server_response_timeout; | |
| multi->admin->set.no_signal = data->set.no_signal; | |
| - | mresult = multi_assess_wakeup(multi); |
| - | if(mresult) { |
| - | failf(data, "error enabling wakeup listening: %d", mresult); |
| - | return mresult; |
| - | } |
| - | |
| CURL_TRC_M(data, "added to multi, mid=%u, running=%u, total=%u", | |
| data->mid, Curl_multi_xfers_running(multi), | |
| Curl_uint32_tbl_count(&multi->xfers)); | |
| @@ -851,6 +847,12 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *curl) | |
| /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */ | |
| if(!Curl_uint32_bset_contains(&multi->msgsent, data->mid)) | |
| --multi->xfers_alive; | |
| + | if(data->state.really_alive) { |
| + | data->state.really_alive = FALSE; |
| + | --multi->xfers_really_alive; |
| + | if(!multi->xfers_really_alive) |
| + | (void)multi_assess_wakeup(multi); |
| + | } |
| Curl_wildcard_dtor(&data->wildcard); | |
| @@ -1151,7 +1153,9 @@ CURLMcode Curl_multi_pollset(struct Curl_easy *data, | |
| /* The admin handle always listens on the wakeup socket when there | |
| * are transfers alive. */ | |
| if(data->multi && (data == data->multi->admin) && | |
| - | data->multi->xfers_alive) { |
| + | data->multi->xfers_really_alive) { |
| + | CURL_TRC_M(data, "adding wakeup, %u xfers really alive", |
| + | data->multi->xfers_really_alive); |
| result = Curl_pollset_add_in(data, ps, data->multi->wakeup_pair[0]); | |
| } | |
| #endif | |
| @@ -2459,6 +2463,12 @@ static void handle_completed(struct Curl_multi *multi, | |
| Curl_uint32_bset_remove(&multi->dirty, data->mid); | |
| Curl_uint32_bset_remove(&multi->pending, data->mid); | |
| Curl_uint32_bset_add(&multi->msgsent, data->mid); | |
| + | if(data->state.really_alive) { |
| + | data->state.really_alive = FALSE; |
| + | --multi->xfers_really_alive; |
| + | if(!multi->xfers_really_alive) |
| + | (void)multi_assess_wakeup(multi); |
| + | } |
| --multi->xfers_alive; | |
| if(!multi->xfers_alive) | |
| multi_assess_wakeup(multi); | |
| @@ -2466,6 +2476,18 @@ static void handle_completed(struct Curl_multi *multi, | |
| static CURLMcode multistate_init(struct Curl_easy *data, CURLcode *result) | |
| { | |
| + | if(!data->state.really_alive) { |
| + | data->state.really_alive = TRUE; |
| + | ++data->multi->xfers_really_alive; |
| + | if(data->multi->xfers_really_alive == 1) { |
| + | CURLMcode mresult = multi_assess_wakeup(data->multi); |
| + | if(mresult) { |
| + | failf(data, "error enabling wakeup listening: %d", mresult); |
| + | return mresult; |
| + | } |
| + | } |
| + | } |
| + | |
| *result = Curl_pretransfer(data); | |
| if(*result) | |
| return CURLM_OK; | |
| @@ -85,6 +85,8 @@ struct Curl_multi { | |
| unsigned int xfers_alive; /* amount of added transfers that have | |
| not yet reached COMPLETE state */ | |
| + | unsigned int xfers_really_alive; /* amount of added transfers that have |
| + | passed INIT state but are not COMPLETE yet */ |
| curl_off_t xfers_total_ever; /* total of added transfers, ever. */ | |
| struct uint32_tbl xfers; /* transfers added to this multi */ | |
| /* Each transfer's mid may be present in at most one of these */ | |
| @@ -704,11 +704,7 @@ struct UrlState { | |
| uint8_t httpreq; /* Curl_HttpReq; what kind of HTTP request (if any) | |
| is this */ | |
| - | /* when curl_easy_perform() is called, the multi handle is "owned" by |
| - | the easy handle so curl_easy_cleanup() on such an easy handle will |
| - | also close the multi handle! */ |
| - | BIT(multi_owned_by_easy); |
| - | |
| + | BIT(really_alive); /* transfer is really alive in multi, passed INIT */ |
| BIT(this_is_a_follow); /* this is a followed Location: request */ | |
| BIT(refused_stream); /* this was refused, try again */ | |
| BIT(errorbuf); /* Set to TRUE if the error buffer is already filled in. | |
| @@ -262,7 +262,7 @@ test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 \ | |
| test2309 test2310 test2311 \ | |
| \ | |
| test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 \ | |
| - | test2408 test2409 test2410 test2411 \ |
| + | test2408 test2409 test2410 test2411 test2412 \ |
| \ | |
| test2500 test2501 test2502 test2503 test2504 test2505 test2506 \ | |
| \ | |
| @@ -0,0 +1,50 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | multi |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data nocheck="yes"> |
| + | HTTP/1.1 200 OK |
| + | Date: Tue, 09 Nov 2010 14:49:00 GMT |
| + | Server: test-server/fake |
| + | Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT |
| + | ETag: "21025-dc7-39462498" |
| + | Accept-Ranges: bytes |
| + | Content-Length: 6007 |
| + | Connection: close |
| + | Content-Type: text/html |
| + | Funny-head: yesyes |
| + | |
| + | -foo- |
| + | %repeat[1000 x foobar]% |
| + | </data> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <features> |
| + | wakeup |
| + | </features> |
| + | <server> |
| + | http |
| + | </server> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | <name> |
| + | checking curl_multi_fdset on nothing to do |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | </verify> |
| + | </testcase> |
| @@ -115,6 +115,7 @@ TESTS_C = \ | |
| lib2023.c lib2032.c lib2082.c \ | |
| lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c \ | |
| lib2402.c lib2404.c lib2405.c \ | |
| + | lib2412.c \ |
| lib2502.c lib2504.c lib2505.c lib2506.c \ | |
| lib2700.c \ | |
| lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c \ | |
| @@ -0,0 +1,95 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Dmitry Karpov <[email protected]> |
| + | * |
| + | * 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.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. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | |
| + | #include "first.h" |
| + | #include "testtrace.h" |
| + | |
| + | static CURLcode test_lib2412(const char *URL) |
| + | { |
| + | CURLcode result = CURLE_OK; |
| + | CURLM *multi = NULL; |
| + | CURL *easy = NULL; |
| + | CURLMcode rc; |
| + | fd_set readFdSet, writeFdSet, exceptFdSet; |
| + | int maxFd; |
| + | |
| + | (void)URL; |
| + | global_init(CURL_GLOBAL_ALL); |
| + | |
| + | multi = curl_multi_init(); |
| + | if(!multi) { |
| + | curl_mfprintf(stderr, "curl_multi_init() failed\n"); |
| + | result = TEST_ERR_MAJOR_BAD; |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | easy = curl_easy_init(); |
| + | if(!easy) { |
| + | curl_mfprintf(stderr, "curl_easy_init() failed\n"); |
| + | result = TEST_ERR_MAJOR_BAD; |
| + | goto test_cleanup; |
| + | } |
| + | debug_config.nohex = TRUE; |
| + | debug_config.tracetime = TRUE; |
| + | easy_setopt(easy, CURLOPT_DEBUGDATA, &debug_config); |
| + | easy_setopt(easy, CURLOPT_DEBUGFUNCTION, libtest_debug_cb); |
| + | easy_setopt(easy, CURLOPT_VERBOSE, 1L); |
| + | |
| + | rc = curl_multi_add_handle(multi, easy); |
| + | if(rc) { |
| + | curl_mfprintf(stderr, "curl_multi_add_handle() failed: %d\n", rc); |
| + | result = TEST_ERR_MAJOR_BAD; |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | FD_ZERO(&readFdSet); |
| + | FD_ZERO(&writeFdSet); |
| + | FD_ZERO(&exceptFdSet); |
| + | maxFd = -1; |
| + | rc = curl_multi_fdset(multi, &readFdSet, &writeFdSet, &exceptFdSet, |
| + | &maxFd); |
| + | if(rc) { |
| + | curl_mfprintf(stderr, "curl_multi_fdset() failed: %d\n", rc); |
| + | result = TEST_ERR_MAJOR_BAD; |
| + | goto test_cleanup; |
| + | } |
| + | |
| + | if(maxFd == -1) |
| + | curl_mfprintf(stderr, "There are no file descriptors to wait for\n"); |
| + | else { |
| + | curl_mfprintf(stderr, "libcurl supplied a file descriptor to " |
| + | "wait for (maxFd=%d). Waiting now ...\n", maxFd); |
| + | result = TEST_ERR_FAILURE; |
| + | } |
| + | |
| + | test_cleanup: |
| + | if(easy) { |
| + | curl_multi_remove_handle(multi, easy); |
| + | curl_easy_cleanup(easy); |
| + | } |
| + | if(multi) |
| + | curl_multi_cleanup(multi); |
| + | curl_global_cleanup(); |
| + | return result; |
| + | } |
| @@ -29,6 +29,7 @@ | |
| */ | |
| #include "first.h" | |
| + | #include "testtrace.h" |
| static struct t530_ctx { | |
| int socket_calls; | |
| @@ -300,6 +301,8 @@ static CURLcode testone(const char *URL, int timer_fail_at, int socket_fail_at) | |
| easy_setopt(curl, CURLOPT_URL, URL); | |
| /* go verbose */ | |
| + | easy_setopt(curl, CURLOPT_DEBUGDATA, &debug_config); |
| + | easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb); |
| easy_setopt(curl, CURLOPT_VERBOSE, 1L); | |
| multi_init(multi); | |