When should WriteFile block when called on a HANDLE that was opened with FILE_FLAG_WRITE_THROUGH?

205 Views Asked by At

At work we run our unit tests regularly on several build machines with the help of Jenkins. One of the unit tests opens a file with FILE_FLAG_WRITE_THROUGH, and makes tens of thousands of WriteFile calls on this file. Why it does that is not relevant to this question. On just one of the build machines, this test timed out constantly. After some investigation, it turned out the root cause for this was that each call to WriteFile was blocking (the thread was switched out, and switched in later), making the test run substantially slower. Curiously enough, when the test was started manually on this machine, WriteFile did not block, and thus the test did not time out.

After hours of trial and error, I found a "workaround": on the affected machine if Jenkins was started with Task Scheduler, WriteFile blocked, if it was started manually or by placing a BAT file in the Startup folder, it did not. I thought I needed to investigate more, so I created a minimal repro, a small program that opens a file with FILE_FLAG_WRITE_THROUGH, and calls WriteFile on it with random data 10000 times. With this minimal repro, WriteFile blocks constantly, regardless of how I launch it. I'm really confused, so here I am asking for any explanation of this behavior. All the machines I performed tests on had SATA drives, with default settings (write caching and Windows write-cache flushing enabled).

First of all for me, it's not even 100% clear what FILE_FLAG_WRITE_THROUGH should do. Information on the internet states that a special flag is passed down to the device, asking it to flush its cache after the write. According to Raymond Chen (and a bunch of other people), this is mostly irrelevant nowadays, as the majority of SATA drives silently ignore this flag due to performance reasons. On the "should or should not block" side, this page clearly states that with FILE_FLAG_WRITE_THROUGH WriteFile should block:

The write call doesn't return until the data is written to the file.

Do you have any ideas why I'm seeing this strange behavior (inconsistently)? How can I investigate further?

0

There are 0 best solutions below