William A. Rowe, Jr. wrote:
Phillip Susi wrote:
When I asked about this a month or two ago, someone explained that
Apache uses TransmitFile() to implement sendfile but in a weird way
that makes it really, really slow. Disabling sendfile in the apache
config, and just using the mmap module gives the best throughput on
windows.
We, the apr developers, would be very interested in their observations
if you can find a pointer.
Right here is your pointer.. and the poor performance of apr_sendfile on windows has been discussed before
(here and on [EMAIL PROTECTED]).
Windows does not provide a way to see if a call to TransmitFile is 'making progress' and it does not provide a
way to set an 'activity timeout' on a sync call to transmitfile. IIS supports async network i/o, so IIS does
not require the thread that makes the call to TransmitFile to hang around waiting for the send to complete.
Apache httpd otoh, requires the thread to not unwind the stack until the call to TransmitFile completes. So
you make a call to TransmitFile to send an entire 100MB file... if you make the call syncronously, your
exposed to a DoS attack if the client does not read the data. If you make the call non-blocking, how long do
you wait for the 100MB send to complete? Certainly not 'timeout' seconds; you'll not send 100M bytes over a
reasonably fast link in the default timeout period, so your transfer would timeout prematurely.
My thinking on how to solve this has changed over the past year or so... there are numerous ways to DoS an
httpd server and you can't protect against the more effective attacks at the httpd layer. I would be infavor
or changing apr_sendfile on Windows in one of the following ways (both will dramatically boost the file
transfer speed):
1. Make a synchronous call to TransmitFile to send -all- the requested content (rather than breaking up the
sends in 64 KB chunks). This is a trivially easy change to make.
2. Make a non-blocking call to TransmitFile to send -all- the request content (rather than breaking up the
sends into 64 KB chunks) and adjusting the timeout according to a simple algorithm:
timeout = Timeout (the config directive) * sizeofsend/64KB
option 2 would at least provide a method to eventually timeout a DoS call. This is a trivially easy change to
make as well.
I would be in favor of making either change as compared to what is in apr_sendfile now (whcih causes so much
grief).
There are other options involving watchdog threads and such, but they are limited by the inability to detect
if a TransmitFile is 'making progress'.
votes?
Bill