Here's the code that actually performs the work of close-on-exec when
exec runs. (/usr/src/sys.386bsd/kern/kern_descrip.c.)
/*
* Close any files on exec?
*/
void
fdcloseexec(p)
struct proc *p;
{
register struct filedesc *fdp = p->p_fd;
struct file **fpp;
register int i;
fpp = fdp->fd_ofiles;
for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
if (*fpp && (fdp->fd_ofileflags[i] & UF_EXCLOSE)) {
(void) closef(*fpp, p);
*fpp = 0;
}
}
Now, look at the for loop. (Several of us have looked at it before.)
Note that i is counting down from fd_lastfile, presumably so
as to use a decrement-and-compare-with-zero, which probably maps to
some instruction on some architectures.
Note also that i is used as an index into fd_ofileflags. Ok,
so we're scanning down from the top.
Now, note that fpp is scanning the fd_ofiles list *UPWARDS*
from the 0th element. Oops.
"Oh. Gee. Is it really doing that?" I hear you cry. Well, yes.
Lots of kernel printf's later, and a working tcsh 6 (yay! :-) have
made it rather clear that this is an example of why this type of
optimization is really better left to the compiler :-)
The obvious fix:
! for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
----
! for (i = 0; i <= fdp->fd_lastfile; i++, fpp++)
Have fun...
_Mark_ <eic...@athena.mit.edu>
MIT Student Information Processing Board
Cygnus Support <eic...@cygnus.com>
ps. Does Bill Jolitz actually read this? I suppose I should be sending
some of these directly to him, though it would be good for someone to
set up an explicit "bug-386bsd" mailing list [if they could guarantee
that the Jolitz' are on it.]