mirror of
https://github.com/curl/curl.git
synced 2026-08-25 14:43:33 +03:00
multi: clear the dirty set of transfers no longer processing
When a transfer is no longer processed, it might still apear in the dirty bitset. Clear the dirty bit when this condition is encountered. Closes #17718
This commit is contained in:
parent
6425ce47df
commit
c7a6319698
2 changed files with 71 additions and 38 deletions
15
lib/multi.c
15
lib/multi.c
|
|
@ -1187,6 +1187,7 @@ CURLMcode curl_multi_waitfds(CURLM *m,
|
|||
if(!data) {
|
||||
DEBUGASSERT(0);
|
||||
Curl_uint_bset_remove(&multi->process, mid);
|
||||
Curl_uint_bset_remove(&multi->dirty, mid);
|
||||
continue;
|
||||
}
|
||||
Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
|
||||
|
|
@ -1270,6 +1271,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
|||
if(!data) {
|
||||
DEBUGASSERT(0);
|
||||
Curl_uint_bset_remove(&multi->process, mid);
|
||||
Curl_uint_bset_remove(&multi->dirty, mid);
|
||||
continue;
|
||||
}
|
||||
Curl_multi_getsock(data, &ps, "multi_wait");
|
||||
|
|
@ -2234,6 +2236,7 @@ static CURLMcode state_connect(struct Curl_multi *multi,
|
|||
multistate(data, MSTATE_PENDING);
|
||||
/* move from process to pending set */
|
||||
Curl_uint_bset_remove(&multi->process, data->mid);
|
||||
Curl_uint_bset_remove(&multi->dirty, data->mid);
|
||||
Curl_uint_bset_add(&multi->pending, data->mid);
|
||||
*resultp = CURLE_OK;
|
||||
return rc;
|
||||
|
|
@ -2665,6 +2668,7 @@ statemachine_end:
|
|||
|
||||
/* remove from the other sets, add to msgsent */
|
||||
Curl_uint_bset_remove(&multi->process, data->mid);
|
||||
Curl_uint_bset_remove(&multi->dirty, data->mid);
|
||||
Curl_uint_bset_remove(&multi->pending, data->mid);
|
||||
Curl_uint_bset_add(&multi->msgsent, data->mid);
|
||||
--multi->xfers_alive;
|
||||
|
|
@ -2702,6 +2706,7 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
|
|||
if(!data) {
|
||||
DEBUGASSERT(0);
|
||||
Curl_uint_bset_remove(&multi->process, mid);
|
||||
Curl_uint_bset_remove(&multi->dirty, mid);
|
||||
continue;
|
||||
}
|
||||
if(data != multi->admin) {
|
||||
|
|
@ -3010,6 +3015,11 @@ static CURLMcode multi_run_dirty(struct multi_run_ctx *mrc)
|
|||
mrc->run_cpool = TRUE;
|
||||
continue;
|
||||
}
|
||||
else if(!Curl_uint_bset_contains(&multi->process, mid)) {
|
||||
/* We are no longer proecessing this transfer */
|
||||
Curl_uint_bset_remove(&multi->dirty, mid);
|
||||
continue;
|
||||
}
|
||||
|
||||
mrc->run_xfers++;
|
||||
sigpipe_apply(data, &mrc->pipe_st);
|
||||
|
|
@ -3225,7 +3235,10 @@ static bool multi_has_dirties(struct Curl_multi *multi)
|
|||
do {
|
||||
struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
|
||||
if(data) {
|
||||
return TRUE;
|
||||
if(Curl_uint_bset_contains(&multi->process, mid))
|
||||
return TRUE;
|
||||
/* We are no longer proecessing this transfer */
|
||||
Curl_uint_bset_remove(&multi->dirty, mid);
|
||||
}
|
||||
else {
|
||||
CURL_TRC_M(multi->admin, "dirty transfer %u no longer found", mid);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,30 @@
|
|||
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
static struct t530_ctx {
|
||||
int socket_calls;
|
||||
int max_socket_calls;
|
||||
int timer_calls;
|
||||
int max_timer_calls;
|
||||
char buf[1024];
|
||||
} t530_ctx;
|
||||
|
||||
static const char *t530_tag(void)
|
||||
{
|
||||
curl_msnprintf(t530_ctx.buf, sizeof(t530_ctx.buf),
|
||||
"[T530-%d-%d] [%d/%d]",
|
||||
t530_ctx.max_socket_calls, t530_ctx.max_timer_calls,
|
||||
t530_ctx.socket_calls, t530_ctx.timer_calls);
|
||||
return t530_ctx.buf;
|
||||
}
|
||||
|
||||
static void t530_msg(const char *msg)
|
||||
{
|
||||
curl_mfprintf(stderr, "%s %s\n", t530_tag(), msg);
|
||||
}
|
||||
|
||||
|
||||
struct t530_Sockets {
|
||||
curl_socket_t *sockets;
|
||||
int count; /* number of sockets actually stored in array */
|
||||
|
|
@ -53,7 +77,7 @@ static void t530_removeFd(struct t530_Sockets *sockets, curl_socket_t fd,
|
|||
int i;
|
||||
|
||||
if(mention)
|
||||
curl_mfprintf(stderr, "Remove socket fd %d\n", (int) fd);
|
||||
curl_mfprintf(stderr, "%s remove socket fd %d\n", t530_tag(), (int)fd);
|
||||
|
||||
for(i = 0; i < sockets->count; ++i) {
|
||||
if(sockets->sockets[i] == fd) {
|
||||
|
|
@ -76,7 +100,8 @@ static int t530_addFd(struct t530_Sockets *sockets, curl_socket_t fd,
|
|||
* To ensure we only have each file descriptor once, we remove it then add
|
||||
* it again.
|
||||
*/
|
||||
curl_mfprintf(stderr, "Add socket fd %d for %s\n", (int) fd, what);
|
||||
curl_mfprintf(stderr, "%s add socket fd %d for %s\n",
|
||||
t530_tag(), (int)fd, what);
|
||||
t530_removeFd(sockets, fd, 0);
|
||||
/*
|
||||
* Allocate array storage when required.
|
||||
|
|
@ -104,9 +129,6 @@ static int t530_addFd(struct t530_Sockets *sockets, curl_socket_t fd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int max_socket_calls;
|
||||
static int socket_calls = 0;
|
||||
|
||||
/**
|
||||
* Callback invoked by curl to poll reading / writing of a socket.
|
||||
*/
|
||||
|
|
@ -118,10 +140,10 @@ static int t530_curlSocketCallback(CURL *easy, curl_socket_t s, int action,
|
|||
(void)easy; /* unused */
|
||||
(void)socketp; /* unused */
|
||||
|
||||
curl_mfprintf(stderr, "CURLMOPT_SOCKETFUNCTION called: %u\n",
|
||||
socket_calls++);
|
||||
if(socket_calls == max_socket_calls) {
|
||||
curl_mfprintf(stderr, "curlSocketCallback returns error\n");
|
||||
t530_ctx.socket_calls++;
|
||||
t530_msg("-> CURLMOPT_SOCKETFUNCTION");
|
||||
if(t530_ctx.socket_calls == t530_ctx.max_socket_calls) {
|
||||
t530_msg("<- CURLMOPT_SOCKETFUNCTION returns error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -141,9 +163,6 @@ static int t530_curlSocketCallback(CURL *easy, curl_socket_t s, int action,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int max_timer_calls;
|
||||
static int timer_calls = 0;
|
||||
|
||||
/**
|
||||
* Callback invoked by curl to set a timeout.
|
||||
*/
|
||||
|
|
@ -152,9 +171,10 @@ static int t530_curlTimerCallback(CURLM *multi, long timeout_ms, void *userp)
|
|||
struct curltime *timeout = userp;
|
||||
|
||||
(void)multi; /* unused */
|
||||
curl_mfprintf(stderr, "CURLMOPT_TIMERFUNCTION called: %u\n", timer_calls++);
|
||||
if(timer_calls == max_timer_calls) {
|
||||
curl_mfprintf(stderr, "curlTimerCallback returns error\n");
|
||||
t530_ctx.timer_calls++;
|
||||
t530_msg("-> CURLMOPT_TIMERFUNCTION");
|
||||
if(t530_ctx.timer_calls == t530_ctx.max_timer_calls) {
|
||||
t530_msg("<- CURLMOPT_TIMERFUNCTION returns error");
|
||||
return -1;
|
||||
}
|
||||
if(timeout_ms != -1) {
|
||||
|
|
@ -187,8 +207,8 @@ static int t530_checkForCompletion(CURLM *curl, int *success)
|
|||
*success = 0;
|
||||
}
|
||||
else {
|
||||
curl_mfprintf(stderr, "Got an unexpected message from curl: %i\n",
|
||||
(int)message->msg);
|
||||
curl_mfprintf(stderr, "%s got an unexpected message from curl: %i\n",
|
||||
t530_tag(), (int)message->msg);
|
||||
result = 1;
|
||||
*success = 0;
|
||||
}
|
||||
|
|
@ -237,8 +257,8 @@ static int socket_action(CURLM *curl, curl_socket_t s, int evBitmask,
|
|||
int numhandles = 0;
|
||||
CURLMcode result = curl_multi_socket_action(curl, s, evBitmask, &numhandles);
|
||||
if(result != CURLM_OK) {
|
||||
curl_mfprintf(stderr, "Curl error on %s (%i) %s\n",
|
||||
info, result, curl_multi_strerror(result));
|
||||
curl_mfprintf(stderr, "%s Curl error on %s (%i) %s\n",
|
||||
t530_tag(), info, result, curl_multi_strerror(result));
|
||||
}
|
||||
return (int)result;
|
||||
}
|
||||
|
|
@ -261,7 +281,7 @@ static int t530_checkFdSet(CURLM *curl, struct t530_Sockets *sockets,
|
|||
return result;
|
||||
}
|
||||
|
||||
static CURLcode testone(char *URL, int timercb, int socketcb)
|
||||
static CURLcode testone(char *URL, int timer_fail_at, int socket_fail_at)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
CURL *curl = NULL; CURLM *m = NULL;
|
||||
|
|
@ -271,12 +291,11 @@ static CURLcode testone(char *URL, int timercb, int socketcb)
|
|||
timeout.tv_sec = (time_t)-1;
|
||||
|
||||
/* set the limits */
|
||||
max_timer_calls = timercb;
|
||||
max_socket_calls = socketcb;
|
||||
timer_calls = 0; /* reset the globals */
|
||||
socket_calls = 0;
|
||||
memset(&t530_ctx, 0, sizeof(t530_ctx));
|
||||
t530_ctx.max_timer_calls = timer_fail_at;
|
||||
t530_ctx.max_socket_calls = socket_fail_at;
|
||||
|
||||
curl_mfprintf(stderr, "start test: %d %d\n", timercb, socketcb);
|
||||
t530_msg("start");
|
||||
start_test_timing();
|
||||
|
||||
res_global_init(CURL_GLOBAL_ALL);
|
||||
|
|
@ -355,14 +374,14 @@ static CURLcode testone(char *URL, int timercb, int socketcb)
|
|||
}
|
||||
|
||||
if(!success) {
|
||||
curl_mfprintf(stderr, "Error getting file.\n");
|
||||
t530_msg("Error getting file.");
|
||||
res = TEST_ERR_MAJOR_BAD;
|
||||
}
|
||||
|
||||
test_cleanup:
|
||||
|
||||
/* proper cleanup sequence */
|
||||
curl_mfprintf(stderr, "cleanup: %d %d\n", timercb, socketcb);
|
||||
t530_msg("cleanup");
|
||||
curl_multi_remove_handle(m, curl);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_multi_cleanup(m);
|
||||
|
|
@ -371,6 +390,7 @@ test_cleanup:
|
|||
/* free local memory */
|
||||
free(sockets.read.sockets);
|
||||
free(sockets.write.sockets);
|
||||
t530_msg("done");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -380,25 +400,25 @@ static CURLcode test_lib530(char *URL)
|
|||
CURLcode rc;
|
||||
/* rerun the same transfer multiple times and make it fail in different
|
||||
callback calls */
|
||||
rc = testone(URL, 0, 0);
|
||||
rc = testone(URL, 0, 0); /* no callback fails */
|
||||
if(rc)
|
||||
curl_mfprintf(stderr, "test 0/0 failed: %d\n", rc);
|
||||
curl_mfprintf(stderr, "%s FAILED: %d\n", t530_tag(), rc);
|
||||
|
||||
rc = testone(URL, 1, 0);
|
||||
rc = testone(URL, 1, 0); /* fail 1st call to timer callback */
|
||||
if(!rc)
|
||||
curl_mfprintf(stderr, "test 1/0 failed: %d\n", rc);
|
||||
curl_mfprintf(stderr, "%s FAILED: %d\n", t530_tag(), rc);
|
||||
|
||||
rc = testone(URL, 2, 0);
|
||||
rc = testone(URL, 2, 0); /* fail 2nd call to timer callback */
|
||||
if(!rc)
|
||||
curl_mfprintf(stderr, "test 2/0 failed: %d\n", rc);
|
||||
curl_mfprintf(stderr, "%s FAILED: %d\n", t530_tag(), rc);
|
||||
|
||||
rc = testone(URL, 0, 1);
|
||||
rc = testone(URL, 0, 1); /* fail 1st call to socket callback */
|
||||
if(!rc)
|
||||
curl_mfprintf(stderr, "test 0/1 failed: %d\n", rc);
|
||||
curl_mfprintf(stderr, "%s FAILED: %d\n", t530_tag(), rc);
|
||||
|
||||
rc = testone(URL, 0, 2);
|
||||
rc = testone(URL, 0, 2); /* fail 2nd call to socket callback */
|
||||
if(!rc)
|
||||
curl_mfprintf(stderr, "test 0/2 failed: %d\n", rc);
|
||||
curl_mfprintf(stderr, "%s FAILED: %d\n", t530_tag(), rc);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue