FileRequest: Make Stop() cancel the request as soon as possible

This commit implements a check for the flag raised by Stop() to cancel
a given request as soon as possible. Cancelled requests will return
B_INTERRUPTED regardless of whether the request has completed,
on par with how BHttpRequest is behaving at the moment.

Change-Id: Ia8a95b910cff158c710c5b2ed58b4675e705642e
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3071
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Leorize 2020-07-15 22:56:53 -05:00 committed by waddlesplash
parent 5b98fa06d5
commit 1f569db086
5 changed files with 133 additions and 7 deletions

View File

@ -79,12 +79,19 @@ BFileRequest::_ProtocolLoop()
fListener->HeadersReceived(this, fResult);
ssize_t chunkSize;
ssize_t chunkSize = 0;
char chunk[4096];
while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0) {
fListener->DataReceived(this, chunk, transferredSize, chunkSize);
transferredSize += chunkSize;
while (!fQuit) {
chunkSize = file.Read(chunk, sizeof(chunk));
if (chunkSize > 0) {
fListener->DataReceived(this, chunk, transferredSize,
chunkSize);
transferredSize += chunkSize;
} else
break;
}
if (fQuit)
return B_INTERRUPTED;
// Return error if we didn't transfer everything
if (transferredSize != size) {
if (chunkSize < 0)
@ -122,7 +129,7 @@ BFileRequest::_ProtocolLoop()
char name[B_FILE_NAME_LENGTH];
BEntry entry;
while (directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
while (!fQuit && directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
// We read directories using the EPLF (Easily Parsed List Format)
// This happens to be one of the formats that WebKit can understand,
// and it is not too hard to parse or generate.
@ -160,7 +167,8 @@ BFileRequest::_ProtocolLoop()
if (fListener != NULL)
fListener->DownloadProgress(this, transferredSize, transferredSize);
fResult.SetLength(transferredSize);
if (!fQuit)
fResult.SetLength(transferredSize);
return B_OK;
return fQuit ? B_INTERRUPTED : B_OK;
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2020, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#include "FileTest.h"
#include <stdlib.h>
#include <File.h>
#include <FileRequest.h>
#include <Url.h>
#include <UrlProtocolRoster.h>
#include <UrlProtocolListener.h>
#include <ThreadedTestCaller.h>
#include <TestUtils.h>
#include "TestServer.h"
class StopTestListener : public BUrlProtocolListener {
public:
StopTestListener() {}
void DataReceived(BUrlRequest *caller, const char*, off_t, ssize_t)
{
caller->Stop();
}
};
void
FileTest::StopTest()
{
StopTestListener listener;
char tmpl[] = "/tmp/filestoptestXXXXXX";
int fd = mkstemp(tmpl);
CHK(fd != -1);
close(fd);
BFile file(tmpl, O_WRONLY | O_CREAT);
CHK(file.InitCheck() == B_OK);
BString content;
/* number chosen to be larger than BFileRequest buffer, adjust as needed */
content.Append('f', 40960);
CHK(file.WriteExactly(content.String(), content.Length()) == B_OK);
BUrl url("file://");
url.SetPath(tmpl);
BUrlRequest *request = BUrlProtocolRoster::MakeRequest(url, &listener);
CHK(request != NULL);
thread_id thr = request->Run();
status_t dummy;
wait_for_thread(thr, &dummy);
CHK(request->Status() == B_INTERRUPTED);
delete request;
request = BUrlProtocolRoster::MakeRequest("file:///", &listener);
CHK(request != NULL);
thr = request->Run();
wait_for_thread(thr, &dummy);
CHK(request->Status() == B_INTERRUPTED);
delete request;
}
/* static */ void
FileTest::AddTests(BTestSuite& parent)
{
CppUnit::TestSuite *suite = new CppUnit::TestSuite("FileTest");
suite->addTest(new CppUnit::TestCaller<FileTest>("FileTest: Stop requests",
&FileTest::StopTest));
parent.addTest("FileTest", suite);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2014-2020 Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef FILE_TEST_H
#define FILE_TEST_H
#include <Url.h>
#include <TestCase.h>
#include <TestSuite.h>
#include <cppunit/TestSuite.h>
#include <tools/cppunit/ThreadedTestCase.h>
#include "TestServer.h"
class FileTest : public BThreadedTestCase {
public:
FileTest() {};
void StopTest();
static void AddTests(BTestSuite& suite);
};
#endif

View File

@ -9,6 +9,7 @@ UnitTestLib servicekittest.so :
DataTest.cpp
HttpTest.cpp
UrlTest.cpp
FileTest.cpp
TestServer.cpp
: be $(TARGET_NETWORK_LIBS) $(HAIKU_NETAPI_LIB) [ TargetLibstdc++ ]

View File

@ -11,6 +11,7 @@
#include "DataTest.h"
#include "HttpTest.h"
#include "UrlTest.h"
#include "FileTest.h"
BTestSuite*
@ -22,6 +23,7 @@ getTestSuite()
UrlTest::AddTests(*suite);
HttpTest::AddTests(*suite);
DataTest::AddTests(*suite);
FileTest::AddTests(*suite);
return suite;
}