Date: 25 Feb 2007 02:47:42 +0000
OK, I've got some code per the discussion so far. A patch is attached.
The patch is lengthy because there's some code movement. The actual
new lines of code is about 50. Here's what it does:
- progress callback can be called more than once a second.
- New function Curl_pselect() is like Curl_select() except that it
has the pselect-style signal-unblock mask argument.
Curl_select() now is just a loop around Curl_pselect. It feeds it a
null signal mask and repeats it when it fails with EINTR.
The Curl_select() in Transfer() is replaced with a Curl_pselect(),
but the rest of the Curl_select()s are untouched.
- Curl_pselect() does what Curl_select() used to do, except it surrounds
it with a signal unblock and restore. And to make the conditional
compilation easier to read, it splits the original code into two functions:
select_with_poll() and select_with_select().
- There's also a pselect-based receive_signals() that narrows the window
of missed signals on a system that has pselect(). It momentarily
unblocks signals and detects whether any waiting signal was received.
Curl_pselect() calls that before doing anything else.
- select.c contains a treatise on the various means of waiting for I/O
and how they respectively suck, and how libcurl deals with it.
- Transfer() blocks all signals and calls Curl_pselect() with an argument
saying to unblock them during the wait. Calls to the progress function
move slightly so one happens _before_ any waiting and they happen
while signals are blocked to make sure signals don't get missed.
- Transfer() doesn't just retry on EINTR - it goes through the whole loop,
including calling the progress callback.
-- Bryan Henderson San Jose, California
- application/octet-stream attachment: interruptiblecurl.patch