Paul Eggert wrote: > > Since this contradicts what you debugged on mingw, I ran the test 10000 > > times on native Windows. Result: > > - on 32-bit mingw, no failure. > > - on 64-bit mingw, around 30 failures (or around 10 failures with Paul's > > newest patch). That is, a probability of ca. 0.3% of getting the same > > file name as on the previous call. > > That's odd, for two reasons. First, 64-bit and 32-bit mingw shouldn't > differ, as they both use uint_fast64_t which should be the same width on > both platforms. Second, I could not reproduce the problem on 64-bit > Ubuntu x86-64 (after altering tempname.c to always define > HAS_CLOCK_ENTROPY to false) test-tempname always succeeded in 10000 tries. > > Could you investigate further why mingw 64-bit fails?
That's odd indeed, and here are more detailed results. I changed test-tempname.c to skip the case 1 and execute only case 2, and added printf statements per the attached tempname.c.diff. Then ran $ for i in `seq 1000`; do ./test-tempname.exe; done 2>&1 | tee out1000 In 32-bit mingw, the result is fully deterministic: each run behaves the same. The first file name is always gl-temp-3FXzHa.xyz; the second file name is always gl-temp-HgtmVy.xyz. Thus, for a single Emacs process, things will look fine, but as soon as someone starts to use temporary files in two different Emacs processes, in the way Eli described, there will be massive collisions. In 64-bit mingw, the 'tempname 1' value is deterministic. This simply shows that Windows 10 does not use address space randomization (ASLR). The 'tempname 2' value is unique 99% of the time: $ grep 'tempname 2' out1000-mingw64 | sort | uniq -d | wc -l 8 The interesting thing is that each of the duplicate values of v is occurring in the same process: $ grep 'tempname 2' out1000-mingw64 | sort | uniq -d tempname 2 v=0x00c1efa91fb60900 tempname 2 v=0x32ccb2946974f2f6 tempname 2 v=0x5cafcc69e359a147 tempname 2 v=0x6d0676018e27d771 tempname 2 v=0x6d95bd6083168079 tempname 2 v=0x7cb95116ffae8ece tempname 2 v=0xe0afc7086808ce33 tempname 2 v=0xe46a60c28fb0ec7f $ grep 'tempname 2' out1000-mingw64 | grep -n 0x00c1efa91fb60900 560:tempname 2 v=0x00c1efa91fb60900 561:tempname 2 v=0x00c1efa91fb60900 $ grep 'tempname 2' out1000-mingw64 | grep -n 0x32ccb2946974f2f6 1129:tempname 2 v=0x32ccb2946974f2f6 1130:tempname 2 v=0x32ccb2946974f2f6 etc. So, in this environment, different Emacs processes will not conflict. But within a single Emacs process, with 1% probability, the two resulting file names are the same. Bruno
--- lib/tempname.c 2022-08-16 21:27:10.455608233 +0200 +++ tempname.c 2022-08-17 01:55:47.590241280 +0200 @@ -308,6 +308,7 @@ for (count = 0; count < attempts; ++count) { +fprintf(stderr,"tempname 1 v=0x%016llx\n", v); fflush(stderr); for (size_t i = 0; i < x_suffix_len; i++) { if (vdigits == 0) @@ -315,6 +316,7 @@ do { v = random_bits (v, use_getrandom); +fprintf(stderr,"tempname 2 v=0x%016llx\n", v); fflush(stderr); use_getrandom = true; } while (unfair_min <= v); @@ -326,7 +328,7 @@ v /= 62; vdigits--; } - +fprintf(stderr,"tempname filename=%s\n", tmpl); fflush(stderr); fd = tryfunc (tmpl, args); if (fd >= 0) {
out1000-mingw32.gz
Description: application/gzip
out1000-mingw64.gz
Description: application/gzip