Windows async read EOF handling (#3162)
fix Windows "file::preadv" emulation EOF handling
This commit is contained in:
parent
7ce20fd9d0
commit
5399a14027
44
src/file.cpp
44
src/file.cpp
|
@ -202,28 +202,42 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int num_waits = num_bufs;
|
||||||
for (int i = 0; i < num_bufs; ++i)
|
for (int i = 0; i < num_bufs; ++i)
|
||||||
{
|
{
|
||||||
DWORD num_read;
|
DWORD num_read;
|
||||||
if (ReadFile(fd, bufs[i].iov_base, DWORD(bufs[i].iov_len), &num_read, &ol[i]) == FALSE
|
if (ReadFile(fd, bufs[i].iov_base, DWORD(bufs[i].iov_len), &num_read, &ol[i]) == FALSE)
|
||||||
&& GetLastError() != ERROR_IO_PENDING
|
|
||||||
#ifdef ERROR_CANT_WAIT
|
|
||||||
&& GetLastError() != ERROR_CANT_WAIT
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ret = -1;
|
DWORD const last_error = GetLastError();
|
||||||
goto done;
|
if (last_error == ERROR_HANDLE_EOF)
|
||||||
|
{
|
||||||
|
num_waits = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (last_error != ERROR_IO_PENDING
|
||||||
|
#ifdef ERROR_CANT_WAIT
|
||||||
|
&& last_error != ERROR_CANT_WAIT
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_for_multiple_objects(int(h.size()), h.data()) == WAIT_FAILED)
|
if (num_waits == 0)
|
||||||
|
{
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_for_multiple_objects(num_waits, h.data()) == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& o : ol)
|
for (auto& o : libtorrent::span<OVERLAPPED>(ol).first(num_waits))
|
||||||
{
|
{
|
||||||
if (WaitForSingleObject(o.hEvent, INFINITE) == WAIT_FAILED)
|
if (WaitForSingleObject(o.hEvent, INFINITE) == WAIT_FAILED)
|
||||||
{
|
{
|
||||||
|
@ -233,11 +247,15 @@ namespace {
|
||||||
DWORD num_read;
|
DWORD num_read;
|
||||||
if (GetOverlappedResult(fd, &o, &num_read, FALSE) == FALSE)
|
if (GetOverlappedResult(fd, &o, &num_read, FALSE) == FALSE)
|
||||||
{
|
{
|
||||||
|
DWORD const last_error = GetLastError();
|
||||||
|
if (last_error != ERROR_HANDLE_EOF)
|
||||||
|
{
|
||||||
#ifdef ERROR_CANT_WAIT
|
#ifdef ERROR_CANT_WAIT
|
||||||
TORRENT_ASSERT(GetLastError() != ERROR_CANT_WAIT);
|
TORRENT_ASSERT(last_error != ERROR_CANT_WAIT);
|
||||||
#endif
|
#endif
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret += num_read;
|
ret += num_read;
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,25 +287,48 @@ TORRENT_TEST(file)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
file f;
|
file f;
|
||||||
TEST_CHECK(f.open("test_file", open_mode::read_write, ec));
|
std::string test_file_name = "test_file";
|
||||||
|
TEST_CHECK(f.open(test_file_name, open_mode::read_write, ec));
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
if (ec) std::printf("%s\n", ec.message().c_str());
|
if (ec) std::printf("%s\n", ec.message().c_str());
|
||||||
char test[] = "test";
|
char test[] = "test";
|
||||||
iovec_t b = {test, 4};
|
size_t const test_word_size = sizeof(test) - 1;
|
||||||
TEST_EQUAL(f.writev(0, b, ec), 4);
|
iovec_t b = {test, test_word_size};
|
||||||
|
TEST_EQUAL(f.writev(0, b, ec), test_word_size);
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("writev failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_CHECK(!ec);
|
TEST_CHECK(!ec);
|
||||||
char test_buf[5] = {0};
|
char test_buf[test_word_size + 1] = {0};
|
||||||
b = { test_buf, 4 };
|
b = { test_buf, test_word_size };
|
||||||
TEST_EQUAL(f.readv(0, b, ec), 4);
|
TEST_EQUAL(f.readv(0, b, ec), test_word_size);
|
||||||
if (ec)
|
if (ec)
|
||||||
std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
TEST_EQUAL(ec, error_code());
|
TEST_EQUAL(ec, error_code());
|
||||||
TEST_CHECK(test_buf == "test"_sv);
|
TEST_CHECK(test_buf == "test"_sv);
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
|
TEST_CHECK(f.open(test_file_name, open_mode::read_only, ec));
|
||||||
|
if (ec)
|
||||||
|
std::printf("open failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
|
TEST_EQUAL(ec, error_code());
|
||||||
|
if (ec) std::printf("%s\n", ec.message().c_str());
|
||||||
|
|
||||||
|
char test_buf2[test_word_size + 1] = {0};
|
||||||
|
std::memset(test_buf, 0, sizeof(test_buf));
|
||||||
|
iovec_t two_buffers[2] {
|
||||||
|
{test_buf, test_word_size},
|
||||||
|
{test_buf2, test_word_size}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_EQUAL(f.readv(0, two_buffers, ec), test_word_size);
|
||||||
|
if (ec)
|
||||||
|
std::printf("readv failed: [%s] %s\n", ec.category().name(), ec.message().c_str());
|
||||||
|
TEST_EQUAL(ec, error_code());
|
||||||
|
TEST_CHECK(test_buf == "test"_sv);
|
||||||
|
f.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(hard_link)
|
TORRENT_TEST(hard_link)
|
||||||
|
|
Loading…
Reference in New Issue