I'm sure most of you have a favorite CreateFile flag (I kid, I kid). Mine is FILE_FLAG_DELETE_ON_CLOSE and I've been using it in my software development career for many years, to great effect, IMHO.
I'd like to write a few articles to describe what it does, why it's awesome, and to present some frustrations with its usage as a challenge to library writers.
Resolving to CreateFile is done whether the call originates from a higher level API like C++'s std::fstream, .Net's File.Open, whatever.
CreateFile has a number of flags that tweak behavior that can be bitwise OR'ed together in the 6th paramter called dwFlagsAndAttributes.
When you use the flag FILE_FLAG_DELETE_ON_CLOSE, this tells the Windows operating system to delete the file when all handles to it are closed.
In case you don't see it yet, this is super effective for temporary files that are created during process execution, where data has to live outside of the process and on disk for whatever reason (too big for process memory, needs to be accessed by an external process, library requires filesystem access to do it's thang, ...).
When you're all done with the temporary file, you need to tidy up your room, by getting rid of the junk piles on the floor. To delete those files after usage (Mom says "clean your room... NOW!") instead of executing DeleteFile, you can just CloseHandle and let the operating system take care of it.
Now, here's the awesomeness: Think about what happens if your process is torn down by an exception, taskkill, whatever. You've never reached the line of code that calls DeleteFile, so you've left a mess.
<IMPORTANT>
If you use FILE_FLAG_DELETE_ON_CLOSE, the operating system will delete the file for you as it tears down the process.
</IMPORTANT>
As the operating system tears down a process for whatever reason, it iterates through all open handles and, effectively, calls CloseHandle one by one. Side effects of the CloseHandle, like honoring FILE_FLAG_DELETE_ON_CLOSE, are done.
Combining this with RAII semantics in code can make the resource of the temporary file automatically go away as soon as it is no longer needed, where the destructor of your temporary file management class closes the handle before the object dies, with the added safeguard that if something bad happens during your process execution, your file will still be removed.
Next up, FILE_FLAG_DELETE_ON_CLOSE all the things! Where using this flag doesn't work well. Soon.
I'd like to write a few articles to describe what it does, why it's awesome, and to present some frustrations with its usage as a challenge to library writers.
OVERVIEW
At the lowest API level, when opening up a file for reading or writing in a Windows process, your call will wind up in the CreateFile function. Actually, CreateFile does a ton more than just reading and writing - check out that MSDN link above - but for this article, let's just focus on regular disk files.NOTE: The above link takes you to CreateFileW, which is different from CreateFileA. The W and A are Microsoft's way of distinguishing Wide (2 byte) characters from nArrow (1 byte) characters. Macros hide this from you in your C++ code, so your calls are all done using CreateFile without the W or A suffix.
Resolving to CreateFile is done whether the call originates from a higher level API like C++'s std::fstream, .Net's File.Open, whatever.
CreateFile has a number of flags that tweak behavior that can be bitwise OR'ed together in the 6th paramter called dwFlagsAndAttributes.
When you use the flag FILE_FLAG_DELETE_ON_CLOSE, this tells the Windows operating system to delete the file when all handles to it are closed.
In case you don't see it yet, this is super effective for temporary files that are created during process execution, where data has to live outside of the process and on disk for whatever reason (too big for process memory, needs to be accessed by an external process, library requires filesystem access to do it's thang, ...).
When you're all done with the temporary file, you need to tidy up your room, by getting rid of the junk piles on the floor. To delete those files after usage (Mom says "clean your room... NOW!") instead of executing DeleteFile, you can just CloseHandle and let the operating system take care of it.
Now, here's the awesomeness: Think about what happens if your process is torn down by an exception, taskkill, whatever. You've never reached the line of code that calls DeleteFile, so you've left a mess.
<IMPORTANT>
If you use FILE_FLAG_DELETE_ON_CLOSE, the operating system will delete the file for you as it tears down the process.
</IMPORTANT>
As the operating system tears down a process for whatever reason, it iterates through all open handles and, effectively, calls CloseHandle one by one. Side effects of the CloseHandle, like honoring FILE_FLAG_DELETE_ON_CLOSE, are done.
Combining this with RAII semantics in code can make the resource of the temporary file automatically go away as soon as it is no longer needed, where the destructor of your temporary file management class closes the handle before the object dies, with the added safeguard that if something bad happens during your process execution, your file will still be removed.
NOTE: FILE_FLAG_DELETE_ON_CLOSE can't protect you against all events: a power outage or a well placed hammer strike on the CPU will not go through the operating system's process teardown routine. YMMV.
Next up, FILE_FLAG_DELETE_ON_CLOSE all the things! Where using this flag doesn't work well. Soon.
No comments:
Post a Comment