cURL / Mailing Lists / curl-library / Single Mail

curl-library

interruptible curl_easy_perform()

From: Bryan Henderson <bryanh_at_giraffe-data.com>
Date: 15 Feb 2007 20:43:46 +0000

It ought to be possible to interrupt curl_easy_perform() with a signal.

There are a number of places curl_easy_perform() takes a long time, but
the one I'm focussing on right now is where it waits for the server to
respond. This is a select() call in Transfer() that waits for data to
arrive on a socket, among other things.

If the libcurl user sets up a signal handler and the process receives a
signal and runs the handler, the select() exits with an EINTR failure.
Transfer() responds by repeating the select(), i.e. it wants to ignore
such interruptions.

If instead, Transfer() just goes ahead as if the select() had returned
rc 0, it would skip past all the socket reading and writing logic,
since there aren't any sockets ready, and run the user's progress
callback. If the progress callback returns the "This is taking too
long" return code, Transfer() and ultimately curl_easy_perform() would
fail immediately with the CURLE_ABORTED_BY_CALLBACK error code, thus
effecting the desired interruption. Presumably, the user's signal handler
and his progress callback routine would be in communication.

The only hard part of this is that you have to make sure the process
doesn't receive a signal after the progress callback and before the
select(), because then there would be nothing to interrupt the select.
That can be done by blocking signals except when select() is waiting,
and that is what pselect() is for. It might also require a slight movement
of where progress callbacks happen.

Does this sound like a viable thing?

More about pselect(), for those unfamiliar: It's the same as select(),
except you additionally give it a set of signals to unblock at the
moment it starts waiting. It re-blocks them before it returns. It is
a relatively recent addition to POSIX; there are probably systems that
don't have it. On such a system you can emulate it with sigaction()
and select(), but that leaves a tiny window in which the process might
miss a signal and wait anyhow. With older Linux kernels, pselect()
actually has that same window exposed. Note that isn't any worse than
libcurl's present logic, in which it _always_ waits in spite of
receiving signals.

-- 
Bryan Henderson                                   San Jose, California
Received on 2007-02-15