Skip Menu |

This queue is for tickets about the Module-Build CPAN distribution.

Report information
The Basics
Id: 80696
Status: open
Priority: 0/
Queue: Module-Build

People
Owner: Nobody in particular
Requestors: NWELLNHOF [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: "Build clean" fails on Windows
I get lots of random failures when running "Build clean" on Windows that look like: Couldn't remove 'dir': That's because 'delete_filetree' in Module::Build::Base checks whether the file or directory still exists after deletion. But on Windows, deleted files are still visible in the file system as long as another process (for example a virus scanner) has an open handle on that file. So can you please disable this check on Windows platforms?
I also get this problem, it seems that under windows there can sometimes be a short delay between a file being removed and you running in perl -e($_) and getting false. I made a patch for Module build 0.4005 that could address this issue without noticeable performance impact for other platforms. It simply does the following File::Path::rmtree($_, 0, 0) or die "Couldn't remove '$_': $!\n"; sleep 1 if (-e $_); die "Couldn't remove '$_': $!\n" if -e $_; instead of File::Path::rmtree($_, 0, 0); die "Couldn't remove '$_': $!\n" if -e $_;
Subject: Module-Build-0.4005-Module-Build-Base.pm.patch
diff --git "a/Module/Build/Base.pm" "b/Module/Build/Base-patched.pm" index 5fb8506..133facb 100644 --- "a/Module/Build/Base.pm" +++ "b/Module/Build/Base-patched.pm" @@ -5296,7 +5296,8 @@ sub delete_filetree { foreach (@_) { next unless -e $_; $self->log_verbose("Deleting $_\n"); - File::Path::rmtree($_, 0, 0); + File::Path::rmtree($_, 0, 0) or die "Couldn't remove '$_': $!\n"; + sleep 1 if (-e $_); die "Couldn't remove '$_': $!\n" if -e $_; $deleted++; }
On Fri May 17 11:07:31 2013, https://mafoo.pip.verisignlabs.com/ wrote: Show quoted text
> sleep 1 if (-e $_);
I don't think this is a good solution. It simply hides the problem and it would slow down cleaning of the project I work on a lot. Simply dropping the check on Windows ($^O eq 'MSWin32') seems like the best idea to me. The -e check should work on Cygwin, btw. Anyone who's interested in this notorious issue is encouraged to have a look at Cygwin's unlink_nt function.
Subject: Re: [rt.cpan.org #80696] "Build clean" fails on Windows
Date: Tue, 21 May 2013 19:10:13 +0200
To: bug-Module-Build [...] rt.cpan.org
From: Leon Timmermans <fawaka [...] gmail.com>
On Tue, May 21, 2013 at 5:55 PM, Nick Wellnhofer via RT <bug-Module-Build@rt.cpan.org> wrote: Show quoted text
> Queue: Module-Build > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=80696 > > > On Fri May 17 11:07:31 2013, https://mafoo.pip.verisignlabs.com/ wrote:
>> sleep 1 if (-e $_);
> > I don't think this is a good solution. It simply hides the problem and it would slow down cleaning of the project I work on a lot. Simply dropping the check on Windows ($^O eq 'MSWin32') seems like the best idea to me.
I agree this is a rather poor solution. And TBH I'm wondering if this isn't a bug in File::Path instead of Module::Build. Leon
On Tue May 21 13:10:49 2013, fawaka@gmail.com wrote: Show quoted text
> And TBH I'm wondering if this > isn't a bug in File::Path instead of Module::Build.
AFAICS, File::Path doesn't guarantee POSIX file deletion semantics. And it's really hard to approximate them on Windows. I'd simply change the check to: # Windows doesn't guarantee that files and directories # disappear from the file system immediately. die "Couldn't remove '$_': $!\n" if $^O ne 'MSWin32' && -e $_;
From: Matthew Vale
I agree that it could add delay to larger project due to the number of sleeps but I don't agree about ignoring the result of the file delete and feel it should be stopped if there was a problem otherwise your build could have issues! That is why I proposed the compromise of sleep only 1 second if the file still exists after asking for it to be deleted then give up if it still remained. generally what i found was that 1 file of many would cause the delay to kick but it was enough to keep the build running. it's NOT adding 1 second x number of files to be deleted, it only does +1 second per file that failed to complete it's delete first time. I think what is happening is under windows the delete operation goes of and runs asynchronously where as under unix and other os's it is running synchronously. Realistically the File::Path::rmtree needs adjusting to cope with this artefact. An alternative compromise would be create a temporary directory inside the build location (so you are not cross filesystem) then use the move operation on an item first going into the temp folder (to get the files out of the way of the build) then trigger the delete. this would mean it doesn't matter if there is a delay between asking for it to be deleted and it actually going as the file/directory being removed is not in the build location it has for all intensive purposes been deleted.
From: Matthew Vale
Something like this would make the alternate compromise work (this is untested, just spooling of the top of my head) File::Copy::move($_, $_."_deleting"); File::Path::rmtree($_."_deleting", 0, 0) or die "Couldn't remove '$_"."_deleting': $!\n"; die "Couldn't remove '$_"."_deleting': $!\n" if -e $_; instead of File::Path::rmtree($_, 0, 0); die "Couldn't remove '$_': $!\n" if -e $_;