Race condition with VisualC and filter drivers

OK guys here’s a strange one. I’m running WinXP Pro and VisualC 6 with
SP3. Today I noticed that with my filter installed, every fifth or sixth
time I tried to save a source file from within VisualC, I’d get the
error ‘Cannot save file. The file may be in use by another application.’
After clicking OK, I noticed that the original source file has been
DELETED from my hard drive. If I attempt to save again, it will usually
work and the file will be re-created, but nonetheless I assumed that
this was a bug with my filter.

Well, it turns out this has nothing to do with my filter per se. It is a
bug with ANY filesystem filter in combination with VisualC. It took me
just a few minutes of searching on Google to determine that dozens of
other people have experienced this in combinition with VisualC and
various other filter drivers (mostly Antivirus).

The problem is NOT that the filter is locking the file (as at least one
Microsoft employee claims on Usenet). The problem SEEMS TO BE a race
condition between two threads in VisualC. Any filter that delays the
operation of the IRP_MJ_CREATE request will expose this bug immediately.

You can see this easily by modifying a copy of Filemon to display the
thread ID for each request (in addition to the process ID). Then load up
a filesystem filter driver that performs some non-trivial amount of work
in IRP_MJ_CREATE. Then save a source file ‘foo.cpp’. What you will see
in the success case is something like this:

Thread 1: Dump contents of open source file foo.cpp to temp.tmp

Thread 2: Open foo.cpp
Thread 2: Cleanup foo.cpp
Thread 2: Close foo.cpp
Thread 1: Rename temp.tmp to foo.cpp

In the failure case you will instead see:

Thread 1: Dump contents of open source file to temp.tmp

Thread 2: Open foo.cpp
Thread 1: Rename temp.tmp to foo.cpp - ACCESS DENIED
Thread 2: Cleanup foo.cpp
Thread 2: Close foo.cpp

As you see, there is a nasty race condition here. In the failure case,
note that since Thread 2’s open of foo.cpp is delayed by the filter, it
doesn’t get a chance to close foo.cpp before Thread 1 attempts to rename
over it with the temp file. I don’t know what Thread 2’s purpose is, but
it’s definitely the party-pooper here.

This bug has apparently been around for years, according to the
newsgroups. I know that various Microsoft employees read this list quite
frequently, so please put in a word with the VisualC team about getting
it fixed (if it’s not fixed in Visual Studio .NET).

I am actually going to put in special-case code in my filter to retry
the rename if the current process is MSDEV.EXE to work around this. :slight_smile:

  • Nicholas Ryan

Does VisualC post Directory Change Notification IOCTLs? If so, this could
very well be the source of the anomaly you see. I have seen worse problems
with applications that use DirChangeNotify and filters that complete CREATE
IRPs on worker threads. The change notify completion happens on the FSD
caller’s thread before the filter has a chance to run it’s completion
routine. The behavior has been known to crash SFM, for example.

I’ve seen another, related, VisualC problem saving files on XP using SUBST’d
drives, but this happens without 3rd party filters. The “bug” doesn’t kick
in until you actual execute something in DevStudio. After that, I cannot
save workspace related stuff!

/ted

-----Original Message-----
From: Nicholas Ryan [mailto:xxxxx@nryan.com]
Sent: Tuesday, September 10, 2002 6:50 PM
To: File Systems Developers
Subject: [ntfsd] Race condition with VisualC and filter drivers

OK guys here’s a strange one. I’m running WinXP Pro and VisualC 6 with
SP3. Today I noticed that with my filter installed, every fifth or sixth
time I tried to save a source file from within VisualC, I’d get the
error ‘Cannot save file. The file may be in use by another application.’
After clicking OK, I noticed that the original source file has been
DELETED from my hard drive. If I attempt to save again, it will usually
work and the file will be re-created, but nonetheless I assumed that
this was a bug with my filter.

Well, it turns out this has nothing to do with my filter per se. It is a
bug with ANY filesystem filter in combination with VisualC. It took me
just a few minutes of searching on Google to determine that dozens of
other people have experienced this in combinition with VisualC and
various other filter drivers (mostly Antivirus).

The problem is NOT that the filter is locking the file (as at least one
Microsoft employee claims on Usenet). The problem SEEMS TO BE a race
condition between two threads in VisualC. Any filter that delays the
operation of the IRP_MJ_CREATE request will expose this bug immediately.

You can see this easily by modifying a copy of Filemon to display the
thread ID for each request (in addition to the process ID). Then load up
a filesystem filter driver that performs some non-trivial amount of work
in IRP_MJ_CREATE. Then save a source file ‘foo.cpp’. What you will see
in the success case is something like this:

Thread 1: Dump contents of open source file foo.cpp to temp.tmp

Thread 2: Open foo.cpp
Thread 2: Cleanup foo.cpp
Thread 2: Close foo.cpp
Thread 1: Rename temp.tmp to foo.cpp

In the failure case you will instead see:

Thread 1: Dump contents of open source file to temp.tmp

Thread 2: Open foo.cpp
Thread 1: Rename temp.tmp to foo.cpp - ACCESS DENIED
Thread 2: Cleanup foo.cpp
Thread 2: Close foo.cpp

As you see, there is a nasty race condition here. In the failure case,
note that since Thread 2’s open of foo.cpp is delayed by the filter, it
doesn’t get a chance to close foo.cpp before Thread 1 attempts to rename
over it with the temp file. I don’t know what Thread 2’s purpose is, but
it’s definitely the party-pooper here.

This bug has apparently been around for years, according to the
newsgroups. I know that various Microsoft employees read this list quite
frequently, so please put in a word with the VisualC team about getting
it fixed (if it’s not fixed in Visual Studio .NET).

I am actually going to put in special-case code in my filter to retry
the rename if the current process is MSDEV.EXE to work around this. :slight_smile:

  • Nicholas Ryan

You are currently subscribed to ntfsd as: xxxxx@livevault.com
To unsubscribe send a blank email to %%email.unsub%%