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

Reply via email to