Skip to content

Commit 6870ebc

Browse files
authored
[CAS] Give Windows file mappings names to better ensure same mappings are used (llvm#190692)
1 parent e80f32f commit 6870ebc

File tree

5 files changed

+82
-12
lines changed

5 files changed

+82
-12
lines changed

llvm/include/llvm/Support/FileSystem.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ class mapped_file_region {
13351335
LLVM_ABI void willNeedImpl();
13361336

13371337
LLVM_ABI std::error_code init(sys::fs::file_t FD, uint64_t Offset,
1338-
mapmode Mode);
1338+
mapmode Mode, const char *Name);
13391339

13401340
public:
13411341
mapped_file_region() = default;
@@ -1351,7 +1351,8 @@ class mapped_file_region {
13511351

13521352
/// \param fd An open file descriptor to map. Does not take ownership of fd.
13531353
LLVM_ABI mapped_file_region(sys::fs::file_t fd, mapmode mode, size_t length,
1354-
uint64_t offset, std::error_code &ec);
1354+
uint64_t offset, std::error_code &ec,
1355+
const char *name = nullptr);
13551356

13561357
~mapped_file_region() { unmapImpl(); }
13571358

llvm/lib/CAS/MappedFileRegionArena.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,17 @@ Expected<MappedFileRegionArena> MappedFileRegionArena::create(
252252
// Create the mapped region.
253253
{
254254
std::error_code EC;
255+
const char *Name = nullptr;
256+
#ifdef _WIN32
257+
// Give the file mapping a name to ensure the same mappings are
258+
// shared across processes.
259+
std::string MapName = Result.Path;
260+
std::replace(MapName.begin(), MapName.end(), '\\', '/');
261+
MapName = "Local\\" + MapName;
262+
Name = MapName.c_str();
263+
#endif
255264
sys::fs::mapped_file_region Map(
256-
File, sys::fs::mapped_file_region::readwrite, Capacity, 0, EC);
265+
File, sys::fs::mapped_file_region::readwrite, Capacity, 0, EC, Name);
257266
if (EC)
258267
return createFileError(Result.Path, EC);
259268
Result.Region = std::move(Map);

llvm/lib/Support/Unix/Path.inc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -860,8 +860,8 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
860860
#endif
861861
}
862862

863-
std::error_code mapped_file_region::init(int FD, uint64_t Offset,
864-
mapmode Mode) {
863+
std::error_code mapped_file_region::init(int FD, uint64_t Offset, mapmode Mode,
864+
const char *Name) {
865865
assert(Size != 0);
866866

867867
int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
@@ -896,12 +896,13 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
896896
}
897897

898898
mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
899-
uint64_t offset, std::error_code &ec)
899+
uint64_t offset, std::error_code &ec,
900+
const char *name)
900901
: Size(length), Mode(mode) {
901902
sandbox::violationIfEnabled();
902903

903904
(void)Mode;
904-
ec = init(fd, offset, mode);
905+
ec = init(fd, offset, mode, name);
905906
if (ec)
906907
copyFrom(mapped_file_region());
907908
}

llvm/lib/Support/Windows/Path.inc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,8 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
10301030
}
10311031

10321032
std::error_code mapped_file_region::init(sys::fs::file_t OrigFileHandle,
1033-
uint64_t Offset, mapmode Mode) {
1033+
uint64_t Offset, mapmode Mode,
1034+
const char *Name) {
10341035
this->Mode = Mode;
10351036
if (OrigFileHandle == INVALID_HANDLE_VALUE)
10361037
return make_error_code(errc::bad_file_descriptor);
@@ -1048,8 +1049,14 @@ std::error_code mapped_file_region::init(sys::fs::file_t OrigFileHandle,
10481049
break;
10491050
}
10501051

1051-
HANDLE FileMappingHandle = ::CreateFileMappingW(OrigFileHandle, 0, flprotect,
1052-
Hi_32(Size), Lo_32(Size), 0);
1052+
SmallVector<wchar_t, 128> NameUTF16;
1053+
if (Name)
1054+
if (std::error_code EC = UTF8ToUTF16(Name, NameUTF16))
1055+
return EC;
1056+
1057+
HANDLE FileMappingHandle =
1058+
::CreateFileMappingW(OrigFileHandle, 0, flprotect, Hi_32(Size),
1059+
Lo_32(Size), Name ? c_str(NameUTF16) : 0);
10531060
if (FileMappingHandle == NULL) {
10541061
std::error_code ec = mapWindowsError(GetLastError());
10551062
return ec;
@@ -1106,11 +1113,11 @@ std::error_code mapped_file_region::init(sys::fs::file_t OrigFileHandle,
11061113

11071114
mapped_file_region::mapped_file_region(sys::fs::file_t fd, mapmode mode,
11081115
size_t length, uint64_t offset,
1109-
std::error_code &ec)
1116+
std::error_code &ec, const char *name)
11101117
: Size(length) {
11111118
sandbox::violationIfEnabled();
11121119

1113-
ec = init(fd, offset, mode);
1120+
ec = init(fd, offset, mode, name);
11141121
if (ec)
11151122
copyFrom(mapped_file_region());
11161123
}

llvm/unittests/Support/Path.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,58 @@ TEST_F(FileSystemTest, FileMappingSync) {
16571657
ASSERT_FALSE((bool)fs::remove(FileName));
16581658
}
16591659

1660+
#ifdef _WIN32
1661+
TEST_F(FileSystemTest, FileMappingNamed) {
1662+
// Create a temp file.
1663+
SmallString<0> TempPath(TestDirectory);
1664+
sys::path::append(TempPath, "test-%%%%");
1665+
auto TempFileOrError = fs::TempFile::create(TempPath);
1666+
ASSERT_TRUE((bool)TempFileOrError);
1667+
fs::TempFile File = std::move(*TempFileOrError);
1668+
StringRef Content("hello there");
1669+
std::string FileName = File.TmpName;
1670+
ASSERT_NO_ERROR(
1671+
fs::resize_file_before_mapping_readwrite(File.FD, Content.size()));
1672+
{
1673+
// Map in the file twice with the same name
1674+
std::error_code EC1;
1675+
fs::mapped_file_region MFR1(
1676+
fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite,
1677+
Content.size(), 0, EC1, "Local\\FileSystemTest_map");
1678+
ASSERT_NO_ERROR(EC1);
1679+
1680+
std::error_code EC2;
1681+
fs::mapped_file_region MFR2(
1682+
fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite,
1683+
Content.size(), 0, EC2, "Local\\FileSystemTest_map");
1684+
ASSERT_NO_ERROR(EC2);
1685+
1686+
// Write content through mapped memory and check the content
1687+
llvm::copy(Content, MFR1.data());
1688+
ASSERT_EQ(std::memcmp(MFR1.data(), MFR2.data(), Content.size()), 0);
1689+
}
1690+
{
1691+
// Map in the file twice named and unnamed
1692+
std::error_code EC1;
1693+
fs::mapped_file_region MFR1(fs::convertFDToNativeFile(File.FD),
1694+
fs::mapped_file_region::readwrite,
1695+
Content.size(), 0, EC1, nullptr);
1696+
ASSERT_NO_ERROR(EC1);
1697+
1698+
std::error_code EC2;
1699+
fs::mapped_file_region MFR2(
1700+
fs::convertFDToNativeFile(File.FD), fs::mapped_file_region::readwrite,
1701+
Content.size(), 0, EC2, "Local\\FileSystemTest_map2");
1702+
ASSERT_NO_ERROR(EC2);
1703+
1704+
// Write content through mapped memory and check the content
1705+
llvm::copy(Content, MFR1.data());
1706+
ASSERT_EQ(std::memcmp(MFR1.data(), MFR2.data(), Content.size()), 0);
1707+
}
1708+
ASSERT_FALSE((bool)File.discard());
1709+
}
1710+
#endif
1711+
16601712
TEST(Support, NormalizePath) {
16611713
// Input, Expected Win, Expected Posix
16621714
using TestTuple = std::tuple<const char *, const char *, const char *>;

0 commit comments

Comments
 (0)