Date: Sun, 2 May 1999 19:12:24 +0300 (IDT) From: Eli Zaretskii 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: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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); }