File operation functions return, but are not actually committed when Windows shuts down

367 Views Asked by At

I am working on an MFC application that can (among other things) be used to shut Windows down. When doing this, Windows of course sends the WM_QUERYENDSESSION and WM_ENDSESSION to all applications, mine included. However, the problem is that my application, as part of some destructors, delete certain files (with CFile::Remove) that have been used during the execution. I have reason to believe that the destructors are called (but that is hard to know for certain) when the application is closed by Windows.

However, when Windows starts back up again, I do occasionally notice that the files that were supposed to be deleted are still present. This does not happen consistently, even when the execution of the program is identical (I have a script for testing this). This leads me to think that one of two things are happening: Either a) the destructors are not consistently being called, or b) the Remove function returns, but the file is not actually deleted before Windows is shut down.

The only work-around I have found so far is that if I get the system to wait with the shutdown for approximately 10 seconds after my program has stopped, then the files will be properly deleted. This leads me to believe that b) may be the case.

I hope someone is able to help me with this problem.

Regards Mort

3

There are 3 best solutions below

0
On BEST ANSWER

Once your program returns from WM_ENDSESSION, Windows can terminate it at any time:

If the session is being ended, this parameter is TRUE; the session can end any time after all applications have returned from processing this message.

If the session ends quickly, then it may end before your destructors run. You must do all your cleanup before returning from WM_ENDSESSION, because there is no guarantee that you will get a chance to do it afterwards.

2
On

The problem here is that some versions of Windows report back that file handling operations have been completed before they actually have. This isn't a problem unless shutdown is triggered as some operations, including file delete will be abandoned.

I would suggest that you cope with this by forcing your code to wait for a confirmed deletion of the files (have a process look for the files and raise an event when they've gone) before calling for system shutdown.

0
On

If the system is properly shut down (nut went sudden power loss or etc.) then all the cached data is flushed. In particular this includes flushing the global file descriptor table (or whatever it's called in your file system) which should commit the file deletion.

So the problem seems to be that the user-mode code doesn't call DeleteFile, or it failes (for whatever reason). Note that there are several ways the application (process) may exit, whereas not always d'tors are called. There are automatic objects which are destroyed in the context of their callstack, plus there are global/static objects, which are initialized and destroyed by the CRT init/cleanup code.

Below is a short summary of ways to terminate the process, with the consequences:

  • All process threads exit conventionally (return from their procedure). The OS terminates the process that has no threads. All the d'tors are executed.
  • Some threads either exit via ExitThread or killed by TerminateThread. The automatic objects of those threads are not d'tructed.
  • Process exited by ExitProcess. Automatic objects are not destructed, global may be destructed (this happens in the CRT is used in a DLL)
  • Process is terminated by TerminateProcess. All d'tors are not called.

I suggest you check if the DeleteFile (or CFile::Remove that wraos it) is called indeed, and check also if it succeeds. For instance you may open the same file twice for whatever reason