This is an archive of the discontinued LLVM Phabricator instance.

[Support] [Windows] Use the regular RemoveFileOnSignal() mechanism on Windows too
AbandonedPublic

Authored by mstorsjo on Oct 24 2021, 5:03 AM.

Details

Summary

This effectively reverts 3ecd20430cace7eb9e78ef0a9ff9cc95a377feb9
(together with some further fixes from
881ba104656c40098d4bc90c52613c08136f0fe1).

The original change away from RemoveFileOnSignal() didn't say why
what was gained, other than "We won't see the temp file no more.".

All use of FILE_FLAG_DELETE_ON_CLOSE or FILE_DISPOSITION_INFO
with DeleteFile=true, and the DELETE access flag, cause various
issues. The original FILE_FLAG_DELETE_ON_CLOSE (in
3ecd20430cace7eb9e78ef0a9ff9cc95a377feb9) had to be worked around
when deciding to keep the file (to cancel the effect of the flag).
This was reworked in 881ba104656c40098d4bc90c52613c08136f0fe1 / D48051
as that approach broke some cases when memory mapping and closing
files (as used in LTO).

This further broke cases when writing temp files on network shares,
worked around in 79657e2339b58bc01fe1b85a448bb073d57d90bb / D81803,
which then broke some cases on Windows 7, worked around in
64ab2b6825c5aeae6e4afa7ef0829b89a6828102. After that, the temp
files were left behind on network shares, even after calling
TempFile::discard(). Fixes for this were attempted in D111875,
but would end up needing to set the DELETE access flag when opening
files for writing in general (or further splitting up/changing the
OF_Delete flag), which breaks when opening a file multiple times
(see discussion in D111875).

Thus simply backtrack and abandon the whole use of delete-on-close
flags on Windows, and use the same RemoveFileOnSignal() mechanism
as on Unix. (The RemoveFileOnSignal() mechanism was still used for
other temp files, not created by TempFile::create.)

After this change, one could maybe also reinstante
51c63bb7efff5f90cd3894dc2b6f73a614dbfb96 (which was reverted as
part of 881ba104656c40098d4bc90c52613c08136f0fe1 / D48051), to
use TempFile in the implementation of LockFileManager.

Diff Detail

Event Timeline

mstorsjo created this revision.Oct 24 2021, 5:03 AM
mstorsjo requested review of this revision.Oct 24 2021, 5:03 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 24 2021, 5:03 AM
mstorsjo updated this revision to Diff 381799.Oct 24 2021, 2:10 PM

Fixed lld/test/ELF/link-open-file.test (renaming over a currently open file) by keeping more of the Windows specific renaming logic (using rename_handle instead of plain rename).

I think on Windows the RemoveFileOnSignal path doesn't always work when the process is killed, which causes temp files to be left sometimes (see https://reviews.llvm.org/D102736)

I think on Windows the RemoveFileOnSignal path doesn't always work when the process is killed, which causes temp files to be left sometimes (see https://reviews.llvm.org/D102736)

Oh, thanks. That's indeed a good reason for keeping the existing approach, although it seems to become a giant pile of hacks/workarounds... I'll see what I can do on the other patch again, then.

rnk added a comment.Oct 26 2021, 12:33 PM

I think on Windows the RemoveFileOnSignal path doesn't always work when the process is killed, which causes temp files to be left sometimes (see https://reviews.llvm.org/D102736)

Yeah, at least in our usage, we found RemoveFileOnSignal was unreliable. The fancy delete disposition feature seemed like exactly what we wanted, it's just a shame that it only seems to work on local NTFS volumes.

I was going to try to come up with one last alternative, something like splitting OF_Delete into OF_DeleteOnClose and OF_Delete. One gives you the ability to delete the file, and the other is the old delete-on-close semantic. Does that work? Sorry for the delay, apologies if I missed something while skimming...

I was going to try to come up with one last alternative, something like splitting OF_Delete into OF_DeleteOnClose and OF_Delete. One gives you the ability to delete the file, and the other is the old delete-on-close semantic. Does that work? Sorry for the delay, apologies if I missed something while skimming...

On second thought, we don't even need to split it - we could just change the OF_Delete flag into "just set the delete access mode, nothing else" and call setDeleteDisposition directly from TempFile::create. Then we could either keep the approach of checking is_local for deciding whether we should call setDeleteDisposition, or go back to making setDeleteDisposition update a reference parameter about whether it did something or not. (But those bool reference returns are a bit ugly, so unless there's some unforseen issue with upfront checking with is_local, maybe that's cleaner.)

Hi,
in https://reviews.llvm.org/D81803 I showed that is_local_internal had no chances to execute because

if (std::error_code EC = realPathFromHandle(Handle, FinalPath))

failed with error 40 (ERROR_INVALID_FUNCTION, function_not_supported). This happens at RAM-disk https://sourceforge.net/projects/imdisk-toolkit/.
Currently emscripten versions 2.0.9+ couldn't pass tests at RAM-disk and versions 2.0.19+ couldn't even link anything when temporaries are at RAM-disk.

Hi,
in https://reviews.llvm.org/D81803 I showed that is_local_internal had no chances to execute because

if (std::error_code EC = realPathFromHandle(Handle, FinalPath))

failed with error 40 (ERROR_INVALID_FUNCTION, function_not_supported). This happens at RAM-disk https://sourceforge.net/projects/imdisk-toolkit/.
Currently emscripten versions 2.0.9+ couldn't pass tests at RAM-disk and versions 2.0.19+ couldn't even link anything when temporaries are at RAM-disk.

Hmm, I think this would work with D111875 then, if I’d update it to remove the check for the specific error code on the return from setDeleteDisposition?

mstorsjo abandoned this revision.Oct 28 2021, 12:48 AM

Abandoning this in favour of D111875.

Thanks everyone for looking at this (see also the very recent https://xkcd.com/2531/).