[Haskell-cafe] Re: sendfile leaking descriptors on Linux?

Bardur Arantsson spam at scientician.net
Sun Feb 14 15:04:30 EST 2010

> Jeremy Shaw wrote:
>> import Control.Concurrent
>> import Control.Concurrent.MVar
>> import System.Posix.Types
>> data RW = Read | Write
>> threadWaitReadWrite :: Fd -> IO RW
>> threadWaitReadWrite fd =
>>   do m <- newEmptyMVar
>>      rid <- forkIO $ threadWaitRead fd  >> putMVar m Read
>>      wid <- forkIO $ threadWaitWrite fd >> putMVar m Write
>>      r <- takeMVar m
>>      killThread rid
>>      killThread wid
>>      return r

I've tested this extensively during this weekend and not a single 
"leaked" FD so far.

I think we can safely say that polling an FD for read readiness is 
sufficient to properly detect a disconnected client regardless of 
why/how the client disconnected.

The only issue I can see with just dropping the above code directly into 
the sendfile library is that it may lead to busy-waiting on EAGAIN *if* 
the client is actually trying to send data to the server while it's 
receiving the file via sendfile(). If the client sends even a single 
byte and the server isn't reading it from the socket, then 
threadWaitRead will keep returning immediately since it's 
level-triggered rather than edge triggered.

In the worst case this could be exploited by evil clients as a trivial 
way to DoS a server -- simply send data while the server is sending you 
a file. Bam, instant 100% CPU utilization on the server.

Not sure what the best solution for this would be, API-wise... Maybe 
actually have sendfile read the data and supply it to a user-defined 
function which could react to the data in some way? (Could supply two 
standard functions: "disconnect immediately" and "accumulate all 
received data into a bytestring".)


More information about the Haskell-Cafe mailing list