Causing a process switch to test a theory.

Matthew Hagerty matthew at digitalstratum.com
Sun Mar 20 12:55:11 PST 2005


Greetings,

I posted a similar message earlier, but I think I was too vague to 
solicit any kind of response.  I'm also trying to stay relevant to the 
forum, but I can only offer the fact that I'm using FreeBSD as my OS of 
choice.  If this is too far removed from being on topic, I apologize in 
advance and will take my questions elsewhere.

I think I have found a possible bug in Apache's logging when using their 
"reliable pipe" feature, but I'd like to test it prior to submitting a 
bug report (or possibly a patch.)  Of course I posted a message on the 
Apache development forum before posting here, but I have had no response 
from that group.

My understanding of PIPE_BUF is that it is the largest amount of data 
the kernel will guarantee to be atomic when writing to a pipe.  Thus if 
more than one process is writing to the same pipe, and more than 
PIPE_BUF bytes needs to be written, there is the chance of the data 
being interleaved due to a context switch during write(), or between 
multiple calls to write() in order to write all required data.

I've been reading the Apache source code to try and determine if 
PIPE_BUF is taken into consideration while logging entries to a pipe.  
What appears to happen is that if a single log entry is more than 512 
bytes, it is simply written to the the pipe without regard to PIPE_BUF.  
But there is a lot going on in Apache and I might very easily miss 
what's really happening somewhere else in the code.  I'm pretty sure I 
can see what's going on and that the code needs to be fixed, but I don't 
want to go blowing my horn without some proof.  What fstat seems to show 
me is that each child process (I'm running the 1.x branch of Apache) has 
the pipe open for writing, thus each child logs it's own entries instead 
of passing them to a single logging process (which could be used as some 
sort of serialization and control to prevent interleaving the log entries.)

In this situation (each child logging it's own entries) it seems there 
is the possibility that a child could be preempted during it's call to 
write() when trying to write more than PIPE_BUF bytes of log data.  What 
I'd like to do is create a test where I would be making requests to 
Apache that would cause log entries longer than PIPE_BUF in length, then 
be able to show the interleaving of log entries due to the PIPE_BUF 
limit being exceeded.

The 2.x branch of Apache has an experimental features called 
BufferedLogs, that if used seems to protect the writing of the log 
entries with a mutex.  However, it is not enabled by default and the 
normal logging does not use the mutex.  I would have assumed the 
PIPE_BUF limit would not have been overlooked by the Apache developers, 
especially since they don't ignore log entires until they reach 8190 
bytes (which is certainly longer than PIPE_BUF.)

Basically it comes down to what happens when making this call:

write(cls->log_fd, str, len);

Under the conditions such that cls->log_fd is a pipe (inherited from the 
parent), len > PIPE_BUF, and there are multiple child processes all 
logging entries with this code.

Knowing if Apache could possibly write interleaved logs when writing to 
a pipe is critical to a program I'm developing which receives log 
entries from Apache via a pipe.

Thank you,
Matthew



More information about the freebsd-hackers mailing list