bin@minster.york.ac.uk (09/29/88)
Some System V systems, particularly those that include Berkeley networking, are afflicted with a fairly nasty bug if the following happens. <stdio.h.>: #define _NFILE 20 <sys/param.h>: #define NOFILE 30 /* anything > _NFILE */ and <stdio.h> again: #define _bufend(p) _bufendtab[(p)->_file] The trouble starts if a process opens some files with stdio, and others directly, using open, pipe, or whatever. Eventually, a stdio file can be opened that has a _file >= _NFILE. There are two problems: 1. _file == _NFILE System V stdio uses this as a flag for IO to and from a string buffer; this convention is used by sprintf/sscanf. The internal buffering functions, _filbuf and _flsbuf, will then mess up buffer filling & flushing. Actually, there is another bug here: _filbuf incorrectly makes a system call for string IO, which can slow sscanf down a little... 2. _file > _NFILE _bufendtab is declared _bufendtab[_NFILE+1], to allow for the convention mentioned above. The array entries are supposed to give the pointer to the end of the buffer for each stdio file. Unfortunately, in order to allow older binary files to be used without recompilation, this pointer was not made part of the FILE structure. Provided NOFILE <= _NFILE, this is merely inelegant. Otherwise, it is a disaster, since the pointer value for _file > _NFILE will be whatever junk appears after the array in memory, often the stdio buffers. Berkeley networking has nothing to do with this, of course, except that ``System V'' systems that have sockets (and perhaps NFS) seem to be more likely to increase NOFILE. It's interesting that programs affected by this will often work quite differently under the control of a debugger. Careless debuggers leave some extra file descriptors open to the executable image, core file, etc. Berkeley systems, including Suns, are unaffected, since they sensibly put the extra value in the FILE structure.
rpw3@amdcad.AMD.COM (Rob Warnock) (10/05/88)
In article <591535074.12423@minster.york.ac.uk> bin@minster.york.ac.uk writes: +--------------- | Berkeley networking has nothing to do with this, of course, except | that ``System V'' systems that have sockets (and perhaps NFS) seem | to be more likely to increase NOFILE... | Berkeley systems, including Suns, are unaffected, since they sensibly | put the extra value in the FILE structure. +--------------- Well, having just done a port of the Berkeley networking code into a System-V, let me point out that whoever ported your stuff had to fix a related problem I ran into over and over, a problem due to the *#&^$*#& "_bufendtab[]" which (as you say) does not exist in Berkeley systems: If you do an "freopen" of a file descriptor which is already open in an stdio stream, since the "_bufendtab[]" is indexed by *file descriptor* your new FILE will stuff *its* bufend over the *old* FILE's. This will cause illegal memory references and other assorted mayhem if you ever use the old FILE for anything! (*Hack* solution: change all cases of such "freopen(s,...) to "freopen(dup(s),...)", so as to get a new bufend entry.) Having _bufend be in a table indexed by f.d. instead of FILE* was a ghastly mistake. I certainly hope more recent versions of System-V have fixed it. Rob Warnock Systems Architecture Consultant UUCP: {amdcad,fortune,sun}!redwood!rpw3 ATTmail: !rpw3 DDD: (415)572-2607 USPS: 627 26th Ave, San Mateo, CA 94403
john@polyof.UUCP ( John Buck ) (10/07/88)
Aside from the NOFILE vs. _NFILE size problems, fdopen() introduces another little (possibly confusing) side effect to stdio. Namely, fd = open("somefile", 2); ... fp1 = fdopen(fd, "r"); fp2 = fdopen(fd, "r+"); Problem here is that fp1 and fp2 SHARE the same IO buffer, since the way "stdio" determines the buffer is via the bufendtab[file_descriptor]. If two "file handles" (FILE *'s) are open to the same file descriptor, buffer clashing will occur. This is something to watch out for, because I have been stung by it a couple of times. john@polyof.poly.edu john@polygraf.bitnet john@[128.238.10.100] (polyof.poly.edu) trixie!polyof!john