Deletion race in NtSetFileInformation ? (Directory not empty error in rm -r -f)

Corinna Vinschen
Tue Sep 14 10:46:00 GMT 2010

On Sep 13 14:20, Earl Chew wrote:
> I have a Makefile which performs "rm -f -r" as part of a clean target.
> On Win7 with 1.7.5-1 this can fail with:
> rm -f -r win32
> rm: cannot remove directory `win32': Directory not empty
> I tried 1.7.7-1 but the problem still seems to be there.
> Doing a little digging, I find that /bin/rm calls
> unlinkat("win32/dll"), which eventually calls unlink_nt().
> A short time later, /bin/rm calls unlink_at("win32") and
> fails at check_dir_not_empty() because it finds the following
> entries::
>  413407 [main] rm 3612 check_dir_not_empty: File name: 2 0x2E 0x610E 0x10 "."
>  413493 [main] rm 3612 check_dir_not_empty: File name: 4 0x2E 0x2E 0x18   ".."
>  413574 [main] rm 3612 check_dir_not_empty: File name: 6 0x64 0x6C 0x6C   "dll"
> Huh?  Wasn't this the directory that was just deleted?
> Taking a look in the directory after the fact shows that the parent directory
> appears to be empty :
> W:> dir win32
>  Volume in drive W is OS
>  Volume Serial Number is C0E0-BBEE
>  Directory of W:\cerberus\acl\col_\ato\win32
> 13/09/2010  01:57 PM    <DIR>          .
> 13/09/2010  01:57 PM    <DIR>          ..
>                0 File(s)              0 bytes
>                2 Dir(s)  392,720,297,984 bytes free
> Hmm ... my reading of unlink_nt() is that the directory "win32/dll"
> is deleted by setting FileDispositionInformation via NtSetFileInformation().

Yes, that's how it is done by the Win32 API as well.

> Since the file entry seems to be found during the subsequent check_dir_not_empty()
> call when trying to delete the parent directory, is some form
> of explicit synchronisation required when deleting
> the child "win32/dll" to be sure that the deletion is
> actually complete?

There shouldn't be any race.  When you set the delete disposition,
the file is actually deleted as soon as the last handle to the file
is closed.  If the file isn't opened by another process, it will
disappear right at the NtClose at the end of unlink_nt.  Please note
that the call to check_dir_not_empty already takes place *only* if
trying to open the directory failed with STATUS_SHARING_VIOLATION.
So there *was* another process blocking things.


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

Problem reports:
Unsubscribe info:

More information about the Cygwin mailing list