bobm@rtech.UUCP (02/04/87)
I ran across this while trying to figure out how to tell following an fopen() call that the reason it failed was due to too many open file pointers. Take the following program which simply opens a file over and over again until it fails and prints the number of the failed fopen(), and the last error number (the obvious declarations omitted for brevity): ++argv; for (count = 1; 1; ++count) { if (fopen(*argv,"r") == NULL) { printf("file %d, errno %d\n",count,errno); exit(1); } } If you just run this thing, you get: file 62, errno 0 This is on an ULTRIX system which allows 64 open files. Fine. Subtract 3 for stdin / stdout / stderr, realize that fopen() doesn't leave errno set. That's what you ought to get. "exec" this thing under either ksh or sh and you get the same result. NOW, "exec" it under csh, and you get: file 58, errno 24 24 is the error number for too many open files. Two questions I'm curious about: WHAT is csh doing with those 4 extra file pointers it apparently has open? WHAT does csh set up differently which causes the errno 24 to be hanging around after the fopen call (I assume coming from the underlying open())? You get this same result (4 fewer files / meaningful error number) on a couple other systems (Pyramids and CCIs) except for the actual number of files opened, which differs from system to system. You also get this result if you assure that you are opening different files, not that that should make any difference. -- Bob McQueer {amdahl, sun, mtxinu, hoptoad, cpsc6a}!rtech!bobm
brett@wjvax.UUCP (02/11/87)
In article <638@rtech.UUCP> bobm@rtech.UUCP (Bob Mcqueer) writes: >I ran across this while trying to figure out how to tell following an >fopen() call that the reason it failed was due to too many open file >pointers. >WHAT is csh doing with those 4 extra file pointers it apparently has open? >WHAT does csh set up differently which causes the errno 24 to be hanging >around after the fopen call (I assume coming from the underlying open())? I don't have source, but I will hazard a guess. The stdio package allocates a static list of NOFILE entries, where NOFILE is the number of file descriptors which can be open; stdin, stdout, and stderr are set to be already open. When you fopen(), the stdio package first must find an entry in this list; then it must open() the underlying file. Apparently, csh leaves some other file descriptors open across the exec(), which the stdio package can't know about. Thus, the stdio package still has entries available when it runs out of file descriptors. However, if the shell only leaves stdin, stdout, and stderr open, the stdio package runs out of FILE entries and file descriptors at the same time. However, it must check for a FILE entry first; otherwise the open might fail and yet leave the underlying file open. Thus, fopen() returns error because there are no FILE entries left, and the stdio package is too stupid to simulate an EMFILE error in that case. -- ------------- Brett Galloway {pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett
ken@rochester.UUCP (02/13/87)
I seem to remember csh used its own file descriptors for error messages to the terminal. That would account for one descriptor used up. Anybody got the full story? Ken
chris@mimsy.UUCP (02/13/87)
In article <176@quacky.mips.UUCP> dce@mips.UUCP (David Elliott) writes: >I believe that what csh does with the extra file descriptors is to use >them to save the values of the standard file descriptors when redirection >and pipes are done. Without this, you have to fork each time you do >redirection or pipes, which can cause problems when it involves control >structures (if, while, foreach, etc.). Indeed, csh salts away copies of its stdin, stdout, and stderr in `high numbered' file descriptors. In 4.1BSD these were 17, 18, and 19, as NOFILE was 20, making [0..20) legal file descriptor values. These were arranged to be closed on exec() by, as I recall, FIOCLEX ioctls on the *old* descriptors. Dup2 originally carried this attribute over to the new descriptors. This behaviour was deemed bogus, and dropped in 4.2. It seems, however, that the 4.2 csh was converted by a process best described as `tweak it until it works'. No one noticed that the extra descriptors were left behind. I thought all this had been straightened out in 4.3BSD, but it is possible it was overlooked. Csh is one large series of bugs, and desperately needs a complete overhaul. But I do not promise to do it. Incidentally, it really is not necessary to move stdin &c out of the way for redirection of internal commands. A possible data structure to demonstrate: struct cnode { /* command node */ int cn_type; /* type of this node */ char **cn_cmd; /* argv */ struct redir *cn_redir;/* I/O redirections */ caddr_t cn_data; /* type-dependent data (if any) */ }; /* * There may be many command nodes pointing at some particular * redirection node. In particular, a redirected loop construct * will have all its subcommands pointing to the same redir * (unless those subcommands have also been redirected). */ struct redir { /* redirection node */ int r_refcnt; /* reference count */ struct redir *r_next; /* linked list */ int r_type; /* type: TIE<, TIE>; <, <<, >, >>; | */ union { char *r_fname; /* file name for < > >> */ int r_hereis; /* hereis file for << */ /* * A `tied' redirect lists an actual fd * (owned by this process) and a desired * or `pretend' fd, so that >'d shell * constructs will list an acutal fd of * whatever the shell opened, with a * desired fd of 1, e.g. * * Tied fd's are also used as back links in * pipes. */ struct { int rt_realfd; /* actual fd */ int rt_desfd; /* desired fd */ } r_tie; struct cnode *r_pipe; /* link in pipe */ } r_redir; }; (How is that for convoluted? :-) It could well be wrong, too; I just now made it up.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: seismo!mimsy!chris ARPA/CSNet: chris@mimsy.umd.edu
gwyn@brl-smoke.UUCP (02/14/87)
In article <176@quacky.mips.UUCP> dce@quacky.UUCP (David Elliott) writes: >... Unless the folks at AT&T rewrote a major portion >of csh, the System V.3 csh works much the same way. ?? Does SVR3 really have csh? It's not in my copy of the User's Reference Manual. (Actually I hope they don't have it.) I hear rumors that ksh may become part of the standard release of UNIX System V. Anyone know for sure?
guy@gorodish.UUCP (02/14/87)
>Unless the folks at AT&T rewrote a major portion of csh, the System V.3 >csh works much the same way. The System V.3 *what*?
karl@osu-eddie.UUCP (02/15/87)
dce@mips writes: >>The problem with the guess is that csh doesn't use stdio. It even uses >>a local version of printf(), and in 4.xBSD, you have to come up with >>a new version when you port csh to a new machine because the code is >>in assembly language. Unless the folks at AT&T rewrote a major portion >>of csh, the System V.3 csh works much the same way. guy%gorodish@Sun.COM writes: > The System V.3 *what*? No kidding, that could make several people's stomach's do gymnastics. If there's a V.3 Csh, I sure wish someone would tell *me* about it, and I'd give up my own version. No such thing exists except as local hacks like mine, and I doubt anyone wants to make it part of official SysV.anything. Too bad in some ways, very good in others. Besides, it's absolutely no problem at all to get the printf() incompatibilities out of the way. Just go to any ex/vi source area and pick up the portable printf (in C) - it drops right into csh in place of the standard (ha - assembly code as standard) printf.c and doprnt.c. -- Karl