Running the following code on Windows 7 x64
#include <stdio.h>
#include <errno.h>
int main() {
int i;
FILE *tmp;
for (i = 0; i < 10000; i++) {
errno = 0;
if(!(tmp = tmpfile())) printf("Fail %d, err %d\n", i, errno);
fclose(tmp);
}
return 0;
}
Gives errno 13 (Permission denied), on the 637th and 1004th call, it works fine on XP (haven’t tried 7 x86). Am I missing something or is this a bug?
A bit of a refresher from the manpage of on
tmpfile(), which returns aFILE*:My verdict for this issue: Deleting a file on Windows is weird.
When you delete a file on Windows, for as long as something holds a handle, you can’t call
CreateFileon something with the same absolute path, otherwise it will fail with the NT error codeSTATUS_DELETE_PENDING, which gets mapped to the Win32 codeERROR_ACCESS_DENIED. This is probably whereEPERMinerrnois coming from. You can confirm this with a tool like Sysinternals Process Monitor.My guess is that CRT somehow wound up creating a file that has the same name as something it’s used before. I’ve sometimes witnessed that deleting files on Windows can appear asynchronous because some other process (sometimes even an antivirus product, in reaction to the fact that you’ve just closed a delete-on-close handle…) will leave a handle open to the file, so for some timing window you will see a visible file that you can’t get a handle to without hitting delete pending/access denied. Or, it could be that
tmpfilehas simply chosen a filename that some other process is working on.To avoid this sort of thing you might want to consider another mechanism for temp files… For example a function like Win32
GetTempFileNameallows you to create your own prefix which might make a collision less likely. That function appears to resolve race conditions by retrying if a create fails with “already exists”, so be careful about deleting the temp filenames that thing generates – deleting the file cancels your rights to use it concurrently with other processes/threads.