develooper Front page | perl.perl5.porters | Postings from October 2005

Re: Inconsistent behaviour when removing files on Cygwin

Thread Previous | Thread Next
October 27, 2005 00:19
Re: Inconsistent behaviour when removing files on Cygwin
Message ID:
On 10/27/05, Yitzchak Scott-Thoennes <> wrote:
> On Wed, Oct 26, 2005 at 05:28:30PM +0200, S?bastien Aperghis-Tramoni wrote:
> > Hello,
> >
> > While correcting a bug in Net::Pcap Makefile.PL with a Windows developer,
> > we stumbled upon the strange behaviour of the unlink() function under
> > Cygwin. It looks like it tries to emulates the Unix behaviour but fails
> > to achieve it.
>  ...
> > Ok, the equivalent program in C produces the same results, so the error is
> > likely to be inside Cygwin API, but shouldn't this be documented somewhere?
> > Maybe in perlport/"DOS and Derivatives"?
> perlport says it short and sweet: (implied: For portable code:) "Don't
> C<unlink> or C<rename> an open file."  I don't think repeating that in
> a dosish section would be more helpful.
> cygwin may defer unlinks until the file is closed or until the process
> ends.  Exactly what it does depends on the exact flavor of windows and
> how reliable (cygwin thinks) the relevant win32 api calls are there.

Actually, afaiui its not a "may" its a "must". The Win32 API doesnt
support unlink directly.

The way you delete a file in Win32 is you use CreateFile with the
DELETE_ON_CLOSE flag. When you close the file it is either marked as
"Pending Delete" (if other processes also have the file open) or it is
outright deleted (if no other processes have the file open).
(See references below, this is better explained in the last posting on
the last url in my reference list)

The Win32 C Libraries provide _unlink and _wunlink for compatibility
purposes, but they just do what is described above.

Note however this applies ONLY to files opened with FILE_SHARE_DELETE.
If a file is not opened with this sharing flag then nothing can delete
or rename the file while it is open.

Anyway, as i said before the reason the Cygwin and the Win32 version
behave differently is because Cygwin obviously opens files with
FILE_SHARE_DELETE allowing the OS to mark the handle as
"DELETE_ON_CLOSE" via unlink. Whereas Win32 Perl does NOT open files
with the FILE_SHARE_DELETE flag set in normal circumstances (it does
internally for such things as stat()).

The end result is that Cygwin has decided to go with the unixy
behaviour of "you can delete open files" and Win32 Perl has decided to
go with the Win32 behaviour of "by default you cannot delete open

But the truth is that you CAN'T delete open files at all on Win32
systems, you can only ask the OS to delete them when the refcount on
the handle falls to zero.

Im guessing that the bit you say about "until the process ends"
implies that on Win95/98/ME cygwin somehow simulates the delete on
close behaviour. Im not sure how as those versions of windows dont
support FILE_SHARE_DELETE so if some process had the file open there
is no way to delete the file until it is closed again.

Also, there is some further insanity in this picture: if two process
have a file open with FILE_SHARE_DELETE is possible for one of them to
delete the file, (and thus have it marked DELETE_PENDING) and then
have the other one change the flag so it is not DELETE_PENDING so the
file never actually gets deleted.  The first process thinks the file
has been deleted correctly, but the second overrides it. There are
some other traps and zaps here too from what i have seen, so the
default behaviour of not using FILE_SHARE_DELETE is maybe actually the
least surprising approach.

Related info is here:

perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About