I'm very puzzled by something. We recently had a problem where Apache would
start getting EAGAIN errors on accept() calls, and generally things would go
to hell from that point. This was with Apache 1.3.2x on BSDI.
I investigated, and determined that this was the problem: we had a php page,
and the php code invoked a third-party program via system(). One of the
things that program was doing was basically this:
for ( int i = 3; i < something; ++i )
{
int flags = fcntl( i, F_GETFL );
if ( flags != -1 )
fcntl( i, F_SETFL, flags | O_NONBLOCK );
}
It turns out that, with Apache 1.3.2x, the php page, and the program it
invokes with system(), is called with several file descriptors of Apache's.
In particular, it has the socket Apache is listening on, and Apache does not
appreciate having the O_NONBLOCK flag set on that socket.
Programs invoked via CGI do not have those file descriptors. They only get
stdin, stdout, and stderr.
So, first question: why does doesn't Apache close all file descriptors > 2
before invoking php?
I tried this on Linux, and that leads to the second puzzle. On Linux,
Apache isn't bothered by having its listen socket's mode changed to
non-blocking. (And I verified that it is really getting changed). So,
second question: can anyone explain offhand why Apache on BSDI gets upset in
this situation, and Apache on Linux does not? (Same version of Apache in
both cases. I downloaded and compiled the same tarball on both).
Finally, I grabbed Apache 2.something, and tried that. It seemed to me that
php scripts getting all file descriptors, instead of just std{in|out|error}
was a bug, and so I wanted to see if that was fixed. Well, not only do php
scripts still get all of Apache's file descriptors, CGI gets them all, too,
unlike in 1.3.2x!
So, third and final question: for CGI and php scripts, what file descriptors
actually *should* be left open after Apache forks, and which should it
close? (I'm not sure exactly how php works in Apache. If the php module is
actually running the php interpreter, than I guess it makes sense to not
close things...but I can't think of a justification for CGI getting
everything).
--Tim Smith