cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: [PATCH] Call progress function when poll()/select() is interrupted

From: Yang Tse <yangsita_at_gmail.com>
Date: Mon, 14 Apr 2008 15:15:54 +0200

2008/4/12, Pierre Ynard wrote:

> Hello,
>
> This patch makes the progress update function get called when
> poll()/select() in select.c are interrupted by a signal. As discussed in
> the previous thread (http://curl.haxx.se/mail/lib-2008-03/0011.html),
> the purpose is to allow applications using libcurl to cleanly abort
> operations upon receiving a signal in the middle of performing a request
> with libcurl.
>
> The progress update function can call a user-defined progress callback,
> which lets the user abort the request by returning an error value.
> Assuming that select.c is (should be) the only place where libcurl
> blocks (on poll()/select()), a signal will now interrupt the blocking
> call, run the progress callback, and give the user the possibility to
> abort if it has to, instead of looping back to poll()/select() and
> blocking for an unknown amount of time.
>
> The patch is based on the source code of the new 7.18.1 release.

Full message quoted intentionally !

This patch not only makes the progress update function get called when
poll()/select() in select.c are interrupted by a signal.

It will also make the progress update function get called for _every_
single call to Curl_socket_ready() and Curl_poll() no matter what. And
as described above an additional call to the progress update function
when poll()/select() are interrupted by a signal.

This implies that, unconditionally, for _every_ single call to
Curl_socket_ready() and Curl_poll() there will be a new additional
call to gettimeofday() that will somehow impact the performance of
lib/curl on _all_ platforms no matter what.

The unconditional call to the progress update function seems to exist
to allow the user to interrupt, via Curl_pgrsUpdate() the
Curl_socket_ready() and Curl_poll() functions even before they
internally call poll()/select().

The unconditional call to the progress update function might also
imply that Curl_pgrsUpdate() will be called at some points where this
wasn't intended with possible strange results.

I understand that the unconditional call to Curl_pgrsUpdate() is done
before poll()/select() to try to minimize the race condition that
would happen if the signal is delivered before the poll()/select()
function actually executes. But calling Curl_pgrsUpdate() has the
above mentioned side effects. :-(

But all this might somehow lead to a better implementation (or not ;-)...

Before calling poll()/select() what actually has to be executed is a
callback capable of returning a value which indicates if the operation
should be aborted or not, but with no libcurl side effects. This could
be done calling a Curl_checkAbort() function, before poll()/select()
which would call, if defined, a user provided abort callback.

I think that this sounds quite reasonable and nearly no overhead would
be introduced.

Obviously, once poll()/select() have finished due to a signal
interruption Curl_checkAbort() should be called instead of
Curl_pgrsUpdate(). Again there would be no libcurl side effects.

What is still missing from the big picture ?

A call to Curl_checkAbort() at most probably the beginning
Curl_pgrsUpdate(), and the CURLOPT_ support to 'install' the abort
callback function.

In this way the 'classic' way of aborting libcurl would still be
supported, and nearly no overhead would be introduced if the 'new'
abort callback function is used or not.

And once that the above is in place _and_ working it would even make
sense to internally introduce pselect() and ppoll().

Comments on this approach ? Pierre, Daniel anyone ?

PS: I'm flooded with work, so I'm unable anytime soon to implement
this approach, so if the approach is good enough and anyone wishes to
take on it go ahead. I don't have much time to discuss it, but
certainly zero time to code it.

Cheerz

-- 
-=[Yang]=-
Received on 2008-04-14