www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/05/02/12:14:28

Date: Sun, 2 May 1999 19:12:24 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: djgpp-workers AT delorie DOT com
Subject: Windows 9X bug when it runs out of file handles
Message-ID: <Pine.SUN.3.91.990502185855.136E-100000@is>
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

I found this when the Gawk test suite failed for me on Windows 95, but 
passed with flying colors on plain DOS.  The bug is so perverse that it 
cannot even be explained in a simple way.  So please bear with me.

Let's imagine you have a program that opens lots of files, until it
exhausts all the available file handles in the current DOS box.  The last
call to `open' fails with EMFILE; so far so good.  You now close one (or
more) of the open handles and retry the failed open call.  The call
succeeds, also as expected.  Here's the bug: the first (and only the
first) handle from a successful call to open after you got EMFILE will
fail for some operations in mysterious ways.  For example, try an innocent
call like lseek(fd, 0L, SEEK_END), and the call silently fails (i.e., the
file pointer stays at the beginning of the file).  In my case,
fdopen(file, "a") overwrote the file's contents instead of appending to
it. 

Phew!  That was certainly a mouthful!

Well, I played a bit with the code in open.c to try to see whether I can 
work around this.  It turns out that the bug doesn't appear if we don't 
call _creat after _open fails (don't ask me why, ask Bill Gates).  I 
don't think it makes any sense to call _creat if _open returns EMFILE or 
ENFILE, so I suggest the patch below.  Please see if there's something 
that this might break; if not, I will check this into CVS.

*** src/libc/posix/fcntl/open.c~2	Sun Jun 28 22:47:08 1998
--- src/libc/posix/fcntl/open.c	Sun May  2 18:15:26 1999
*************** open(const char* filename, int oflag, ..
*** 63,71 ****
         by some other program with DENY-NONE sharing bit, which fails
         the `_open' call above.  Try again with DENY-NONE bit set,
         unless some sharing bits were already set in the initial call.  */
!     if (fd == -1 && dont_have_share)
        fd = _open(filename, oflag | SH_DENYNO);
!     if (fd == -1 && oflag & O_CREAT)
        fd = _creat(filename, dmode);
    }
  
--- 63,79 ----
         by some other program with DENY-NONE sharing bit, which fails
         the `_open' call above.  Try again with DENY-NONE bit set,
         unless some sharing bits were already set in the initial call.  */
!     if (fd == -1 && errno != EMFILE && errno != ENFILE && dont_have_share)
        fd = _open(filename, oflag | SH_DENYNO);
! 
!     /* Windows 9X exhibits some weird behavior if the initial _open
!        above failed because there are no more available file handles
!        in the current DOS box, *and* if we try the _creat call below.
!        For example, lseek on the handle opened immediately after that
!        silently fails.  There's no sense in trying to create a file if
!        the OS doesn't have any more available handles, and avoiding
!        the call to _creat seems to work around the Windows bug.  */
!     if (fd == -1 && errno != EMFILE && errno != ENFILE && (oflag & O_CREAT))
        fd = _creat(filename, dmode);
    }
  

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019