X-Recipient: archive-cygwin AT delorie DOT com X-Spam-Check-By: sourceware.org Date: Tue, 14 Sep 2010 10:38:21 +0200 From: Corinna Vinschen To: cygwin AT cygwin DOT com Subject: Re: Deletion race in NtSetFileInformation ? (Directory not empty error in rm -r -f) Message-ID: <20100914083821.GF16534@calimero.vinschen.de> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com References: <4C8E958B DOT 1040807 AT ixiacom DOT com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <4C8E958B.1040807@ixiacom.com> User-Agent: Mutt/1.5.20 (2009-06-14) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com 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 . > 13/09/2010 01:57 PM .. > 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 -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Project Co-Leader cygwin AT cygwin DOT com Red Hat -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple