mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-01 05:02:29 +07:00
* Add test for #2435 mmap::open with concurrent writer Verifies that detail::mmap can open a file held open with GENERIC_WRITE by another handle (e.g. an active log file). Currently fails on Windows because CreateFile2 omits FILE_SHARE_WRITE. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix #2435: allow mmap to open files held open for writing Add FILE_SHARE_WRITE to the share mode passed to ::CreateFile2 so detail::mmap can open a file even when another process holds it open with GENERIC_WRITE (e.g. an active log file). Without this, CreateFile2 fails with ERROR_SHARING_VIOLATION because the new opener's share mode must permit the existing handle's access mode. This brings the Windows path's behavior in line with the POSIX path which uses ::open(O_RDONLY) and is unaffected by other processes' write handles. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
0cbeafe6a4
commit
c2678f0186
@@ -5319,8 +5319,9 @@ inline bool mmap::open(const char *path) {
|
||||
auto wpath = u8string_to_wstring(path);
|
||||
if (wpath.empty()) { return false; }
|
||||
|
||||
hFile_ = ::CreateFile2(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
|
||||
OPEN_EXISTING, NULL);
|
||||
hFile_ =
|
||||
::CreateFile2(wpath.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, NULL);
|
||||
|
||||
if (hFile_ == INVALID_HANDLE_VALUE) { return false; }
|
||||
|
||||
|
||||
@@ -7939,6 +7939,31 @@ TEST(MountTest, MultibytesPathName) {
|
||||
EXPECT_EQ(U8("日本語コンテンツ"), res->body);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Issue #2435: mmap::open() must succeed even when another handle holds
|
||||
// the file open for writing (e.g. an active log file).
|
||||
TEST(MmapTest, OpenWhileFileHeldForWriting) {
|
||||
const char *path = "mmap_concurrent_writer_test.txt";
|
||||
const char *content = "hello";
|
||||
|
||||
{
|
||||
std::ofstream f(path, std::ios::binary);
|
||||
f.write(content, static_cast<std::streamsize>(strlen(content)));
|
||||
}
|
||||
auto file_cleanup = detail::scope_exit([&] { std::remove(path); });
|
||||
|
||||
HANDLE writer = ::CreateFileA(path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ASSERT_NE(INVALID_HANDLE_VALUE, writer);
|
||||
auto handle_cleanup = detail::scope_exit([&] { ::CloseHandle(writer); });
|
||||
|
||||
detail::mmap m(path);
|
||||
ASSERT_TRUE(m.is_open());
|
||||
EXPECT_EQ(strlen(content), m.size());
|
||||
EXPECT_EQ(0, std::memcmp(content, m.data(), strlen(content)));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(KeepAliveTest, ReadTimeout) {
|
||||
Server svr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user