-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CURL_READFUNC_ABORT is lost if returned in a middle of transfer #4813
Comments
This sounds annoying. Can you create a simple source code that reproduces this problem for us to use to debug this? |
The libcurl test lib643.c uses this callback. I'll see if I can just adjust that and create a test case for this scenario... |
His analysis may be correct though and I don't know why it would not return abort either. That pattern is in the code several times, Patrick put it there, let's see what he has to say. |
I figured it out. Test 644 simply isn't a good test case. The callback keeps getting called, exactly as reported here, but the code doesn't detect or fail the test because of it. To improve test 644 (and thus reproduce this bug): --- a/tests/libtest/lib643.c
+++ b/tests/libtest/lib643.c
@@ -39,14 +39,19 @@ struct WriteThis {
};
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
{
#ifdef LIB644
+ static int count = 0;
(void)ptr;
(void)size;
(void)nmemb;
(void)userp;
+ if(++count > 1) {
+ printf("Wrongly called >1 times\n");
+ exit(1); /* trigger major failure */
+ }
return CURL_READFUNC_ABORT;
#else
struct WriteThis *pooh = (struct WriteThis *)userp;
int eof = !*pooh->readptr; |
When *ABORT is returned from the callback, the transfer must stop immediately and the return code must be passed back to the parent all the way up to Curl_fillreadbuffer(). Test 644 was supposed to verify this but it wasn't done right. Now it makes sure the callback is never called again after CURL_READFUNC_ABORT is returned and it also makes sure the data transfer is actually stopped as instructed. Also removed the 'flaky' keyword since the test is now modified. Fixes #4813 Reported-by: MrdUkk on github
Function As soon as the callback returns a non-positive byte count, the loop is exited. If some data were read since function entry, the count is returned to process them. Else the end code.
This is not random: this is the effective number of bytes read since readback_part() entry. Maybe we should latch the last read size/status to handle this persistence in libcurl itself rather than in the read callback and thereby avoid calling the latter again? If we do that, resetting the CURL_READFUNC_PAUSE state will probably be difficult. |
Yes, it's exactly like @bagder says: my callback is called repeatedly (3-4 times observed in debugger). my project using multithreading. thread1 uses curl_easy interface doing data transfer and thread2 posting messages to thread1 (with data). static size_t ReadMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
SharedBuffer *ptr = (SharedBuffer *)userp;
size_t realsize = size * nmemb;
for (;;)
{
DWORD PE = WaitForMultipleObjects(2, ptr->PEvent, FALSE, INFINITE);
if (PE == WAIT_OBJECT_0)
return CURL_READFUNC_ABORT;
else if (PE == WAIT_OBJECT_0 + 1)
{
char *ab=ptr->TryDequeune();
if (!ab) continue;
memcpy(contents, ab, realsize);
return realsize;
}
}
return 0;
} |
The callback should not get called again within the same transfer, if it returned ABORT previously. It is a bug. |
Yes. An ABORT from the callback really means abort and it should not be called again. (What if the second call would return something else?) Calling it again also means that the code doesn't actually abort but somehow still tries to continue.
Difficult maybe, but that's how the API should behave. The callback should only have to return PAUSE once. |
i tested old libcurl (version 7.39.0) -works like a charm. my callback is called once. |
works now when using https://github.com/monnerat/curl/tree/mime-abort-pause |
In case a read callback returns a status (pause, abort, eof, error) instead of a byte count, drain the bytes read so far but remember this status for further processing. Takes care of not losing data when pausing, and properly resume a paused mime structure when requested. New tests 670-673 check unpausing cases, with easy or multi interface and mime or form api. Fixes #4813 Reported-by: MrdUkk on github Closes #4833
Reverted the merge, this issue is still open. |
I did this
in a middle of transfer want to cancel transfer. so i return in my callback function to CURL specified
CURL_READFUNC_ABORT value.
I expected the following
expect to see immediately aborted transfer but libcurl REPEATEDLY call again and again my callback function and doesn't stop!
curl/libcurl version
7.68.0
operating system
VS2015 Windows 8.1.
after debugging i find out some strange behaviour in mime.c function
readback_part() calling sz = read_part_content(part, buffer, bufsize);
we are returning in sz CURL_READFUNC_ABORT value , stepping next switch
here i see random non zero 'cursize' values (is it bytes transfered already before we abort?)
and cursize is not zero it will don't return (losing) proper CURL_READFUNC_ABORT to upper levels of callstack.
it's sounds something simular to old 2011 bug . (see git repo commit 840eff4).
transfer isn't stopped and hung in curl_easy_perform()
The text was updated successfully, but these errors were encountered: