Some questions about unflushed data and calling FlushFileBuffers on a new handle to a file

Consider the following sequence of events:

  1. Process A opens a file with Create­File with attributes that include neither FILE_FLAG_NO_BUFFERING nor FILE_FLAG_WRITE_THROUGH.
  2. Process A writes to the file with Write­File. These writes are internally buffered since we didn't disable buffering.
  3. Process A crashes without calling Close­Handle, and before the operating system's internal buffers are flushed to disk.

First question: Under these conditions, will the data written in step 2 be lazy-written to disk? Or is it at risk of being lost forever because the handle wasn't closed?

Let's look at the last part first. Whether the process closed the handle before crashing doesn't affect the story, because the kernel will close all the handles as part of process cleanup. The handle does get closed eventually. Whether the handle closure was done explicitly by the app or implicitly by the kernel doesn't affect the answer.

Okay, now let's look at the first part: Yes, the data written in step 2 will eventually be lazy-written to disk, assuming your system doesn't crash before then.

And that's the middle part of the question: The data is at risk of being lost forever, but not because the handle wasn't closed. It's at risk of being lost forever because the system might crash before it gets flushed out.

Okay, let's extend the scenario:

  1. Before the operating system flushes its internal buffers naturally, Process B opens the same file, with the same attributes.
  2. Process B calls Flush­File­Buffers.

Does this call to Flush­File­Buffers cause the data written by Process A to be flushed to disk?

Yes. A call to Flush­File­Buffers will flush data for that file, even if the data was written by a different handle.

If Flush­File­Buffers is never called, then the operating system will flush the buffer at its convenience.

Note: In step 2, the relevant call is Write­File. If you write the data to the file using a runtime-provided function like fwrite, then that data might be sitting in the runtime's buffer without ever triggering a Write­File. Only when the data is written with Write­File does the data actually reach the operating system's buffers.

Comments (11)
  1. henke37 says:

    Different handle to the same open file object or different handle to the same open file object? You should be clearer, even if only one is what you’ve possibly meant.

    Also note that WriteFile has to complete before the system will ensure that the data will not be lost unless the system crashes.

    1. Sergei Vorobiev says:

      Those buffers belong to stream control block, not to file object.

    2. Wombat says:

      “Different handle to the same open file object or different handle to the same open file object?”

      What’s the difference? All I can see is one has D for different, and the other has d. Otherwise you have said the same thing twice.

      I’m sure you meant something, but I cannot tell what.

  2. StefanH says:

    I must have been doing to much Win32 programming, because I usually gain a lot of insight from this blog. Today, however, I already knew the answers and couldn’t imagine it working any other way.

  3. cheong00 says:

    Need some clarification.

    Does it mean “the handle to Process A and B points to the same file buffer”, or is it just that “the call to FlushFileBuffers() will flush all file buffers attached to the underlying file record regardless of which file handle you’re calling the function from”?

    1. StefanH says:

      There is only one file object and hence one file buffer even when multiple processes have multiple handles to it. Hence, if you call FlushFileBuffers(), that’s the buffer that’s flushed.

      1. Sergei Vorobiev says:

        As long as you don’t mind I put on my kernel-colored glasses.

        FILE_OBJECT is what HANDLE is in kernel. there are multiple streams in a file. And cache is fully coherent. Therefore there is one Stream Control Block. The File Objects point to it. Your handles are um nicknames for File Objects.

        Yes, there is one SCB. You are correct in the assumption that multiple users of the same stream see the same bytes.

  4. alegr1 says:

    Does WriteFile on a file opened with FILE_FLAG_NO_BUFFERING also updates/invalidates any copies of the data in cache? I would expect that for data coherency reasons.

  5. Some Handles Don't Flush? says:

    –“Process B opens the same file, with the same attributes”
    But if Process B uses different attributes for the same file, this behavior is not guaranteed? I could not find anything in FlushFileBuffers, CreateFile, SetFileAttributes, “Creating and Opening Files”, that said this. It seems sensible that Flush”File”Buffers would flush all buffers associated with the “file object”, no matter which handle was used to invoke the action. But, if some handles to the file don’t invoke the same action, because different attributes were specified when the handle was created, that seems like something one should know.

    1. Sergei Vorobiev says:

      It is guaranteed. There is one Stream Control Block.

  6. Sergei Vorobiev says:

    Raymond, can we have the next installment discussing FlushFileBuffers() and network shares?

Comments are closed.

Skip to main content