On Mon, 4 Mar 2024, Martin Storsjö wrote:
Looking closer at our mkstemp implementation, we have this loop:
/*
Like OpenBSD, mkstemp() will try at least 2 ** 31 combinations before
giving up.
*/
for (i = 0; i >= 0; i++) {
for(j = index; j < len; j++) {
template_name[j] = letters[rand () % 62];
}
fd = _sopen(template_name,
_O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
_SH_DENYNO, _S_IREAD | _S_IWRITE);
if (fd != -1) return fd;
if (fd == -1 && errno != EEXIST) return -1;
}
This should retry an absolutely insane number of times, so as long as one
process finds a unique file name and stops iterating, the other parallel
process should also find a unique one soon after, one would expect.
So if this fails, it looks like something is fishy here; if we have this
clash, do we hit the "if (fd == -1 && errno != EEXIST) return -1;" case
directly on the first iteration?
I tried reproducing this myself. I was able to hit the error, but only
very very rarely (I only reproduced it twice while running these loops for
an hour or two)).
The loop does work as expected, normally - in most cases of collisions, we
do continue iterating. Only in a very very small fraction of cases, we end
up with errno set to something else than EEXIST, e.g. EACCES. And overall,
erroring out on EACCES is the right thing to do, otherwise we'd loop
(near) infinitely if trying to create a temp file in a directory without
write permission.
So that clarifies the mystery to me. And the suggested fix of using
rand_s() sounds good to me, but we should keep a fallback to rand().
I'll post a new patch with that behaviour implemented, and with a slightly
updated commit message.
// Martin
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public