[libcxx] [test] Fix back-to-back use of get_temp_file_name() on Windows

On non-Windows platforms, get_temp_file_name() uses `mkstemp()`,
which picks a unique name and creates a file atomically. The
Windows implementation uses `_mktemp_s()`, which doesn't create the
file. The documentation of `_mktemp_s()` also says that by design,
the function uses the same pattern within a process, as long as that
file doesn't exist.

Thus previously, two consecutive calls to `get_temp_file_name()`
on Windows returned the same file name.

Try to create the suggested temp file with `_O_EXCL` (marking the
file name as already used for future calls to `_mktemp_s`) and retry
if we weren't able to exclusively create the file.

This fixes the test failures on Windows observed in D122257.

Differential Revision: https://reviews.llvm.org/D122612
This commit is contained in:
Martin Storsjö 2022-03-28 23:49:31 +03:00
parent b9ca1e5a5a
commit 64e4dd329c
1 changed files with 14 additions and 3 deletions

View File

@ -39,6 +39,8 @@
#include <string>
#if defined(_WIN32)
# include <io.h> // _mktemp_s
# include <fcntl.h> // _O_EXCL, ...
# include <sys/stat.h> // _S_IREAD, ...
#else
# include <unistd.h> // close
#endif
@ -54,9 +56,18 @@ inline
std::string get_temp_file_name()
{
#if defined(_WIN32)
char Name[] = "libcxx.XXXXXX";
if (_mktemp_s(Name, sizeof(Name)) != 0) abort();
return Name;
while (true) {
char Name[] = "libcxx.XXXXXX";
if (_mktemp_s(Name, sizeof(Name)) != 0) abort();
int fd = _open(Name, _O_RDWR | _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE);
if (fd != -1) {
_close(fd);
return Name;
}
if (errno == EEXIST)
continue;
abort();
}
#else
std::string Name;
int FD = -1;