Issues with ASYNC_pause_job() wake up

Valerio Di Gregorio (vadigreg) vadigreg at cisco.com
Tue Feb 11 15:39:45 UTC 2020


Thanks Matt, this was very helpful. I'll dig into libcurl to understand better. I appreciated your help.

Kind regards,
Valerio 

--
Valerio Di Gregorio
ENGINEER.SOFTWARE ENGINEERING
vadigreg at cisco.com | +41 21 694 3840

.:|:.:|:. Cisco Systems International Sàrl

EPFL, Quartier de l'Innovation
Batiment E, 2nd Floor, Desk A4-7
1015 Ecublens, Vaud
Switzerland

-----Original Message-----
From: Matt Caswell <matt at openssl.org> 
Sent: Tuesday, February 11, 2020 4:14 PM
To: Valerio Di Gregorio (vadigreg) <vadigreg at cisco.com>; openssl-users at openssl.org
Subject: Re: Issues with ASYNC_pause_job() wake up



On 11/02/2020 14:49, Valerio Di Gregorio (vadigreg) wrote:
> My understanding is that libcurl's multi interface is async.

I know nothing about curl, but a quick search of the codebase does turn up some evidence that it seems to be ASYNC aware. At least it is prepared to accept SSL_ERROR_WANT_ASYNC as a return value from
SSL_get_error():

https://github.com/curl/curl/blob/355a5a310019659d9bf6818d2fd66fbb214dfed7/lib/vtls/openssl.c#L2940-L2955

> That's
> the interface I'm using. I configured SSL_CTX_set_mode(ssl_ctx,
> SSL_MODE_ASYNC) as you pointed out. I did in the same libcurl callback 
> I used for SSL_CTX_set_cert_verify_callback(). I can see
> ASYNC_pause_job() actually pausing and returning with no error, so I 
> must assume I'm into an async job.
> 
> Should I call ASYNC_start_job() right after the write() to wake-up and 
> read()?

When your application knows that the callback is ready to continue it must ensure that whatever OpenSSL I/O operation was in progress prior to the pause is then invoked again. So if SSL_connect() was being called at the time of the pause, then SSL_connect() needs to be called again.

I don't know what that means you need to do in libcurl terms.

Matt

> 
> Val
> 
> -----Original Message----- From: Matt Caswell <matt at openssl.org>
> Sent: Tuesday, February 11, 2020 3:36 PM To: Valerio Di Gregorio
> (vadigreg) <vadigreg at cisco.com>; openssl-users at openssl.org Subject:
> Re: Issues with ASYNC_pause_job() wake up
> 
> 
> 
> On 11/02/2020 14:26, Valerio Di Gregorio (vadigreg) wrote:
>> Hi Matt, Thanks for your reply. HTTPS request is initiated using 
>> libcurl. I've installed a callback in libcurl as 
>> CURLOP_T_SSL_CTX_FUNCTION which in turn installs a callback using 
>> SSL_CTX_set_cert_verify_callback(). So my application never calls 
>> ASYNC_start_job().
>> 
>> I expected my application to write() on the write file descriptor of 
>> the pipe and that was enough to un-pause, without any need of calling 
>> ASYNC_start_job() explicitily.
>> 
>> What's the right usage of this async APIs in my case?
> 
> Hmm. Well, unfortunately if libcurl is managing the interaction with 
> libssl then this won't work unless libcurl is async aware (I don't 
> know if it is or not).
> 
> ASYNC_pause_job() does nothing at all if you are not running within an 
> async job. An async job is *not* started automatically by libssl.
> In order for that to happen you have to put the SSL object into ASYNC 
> mode using a call to SSL_set_mode() or SSL_CTX_set_mode(), and passing 
> the `SSL_MODE_ASYNC` value. See:
> 
> https://www.openssl.org/docs/man1.1.1/man3/SSL_set_mode.html
> 
> Once set into async mode libssl will call ASYNC_start_job() 
> automatically for all IO functions (e.g. SSL_read()/SSL_write() etc)
> 
> Further, when the application calls SSL_get_error(), it must be 
> prepared to handle SSL_ERROR_WANT_ASYNC as a return value.
> 
> So, probably, you need to investigate whether libcurl can do this.
> 
> Matt
> 
>> 
>> Many thanks for helping!
>> 
>> Val
>> 
>> 
>> -----Original Message----- From: openssl-users 
>> <openssl-users-bounces at openssl.org> On Behalf Of Matt Caswell
>> Sent: Tuesday, February 11, 2020 2:52 PM To:
>> openssl-users at openssl.org Subject: Re: Issues with
>> ASYNC_pause_job() wake up
>> 
>> 
>> 
>> On 11/02/2020 13:05, Valerio Di Gregorio (vadigreg) via openssl-users 
>> wrote:
>>> 1. ASYNC_pause_job() can wake up before write(). It will then block 
>>> on the read(), which is too bad in my single-threaded code.
>>> 2. I fixed case 1 by making read() non-blocking, I then run
>>> ASYNC_pause_job() again and again until write() is actually 
>>> performed. So now I hit another issue. Time between
>>> printf("pause") and write() is ~100/200 milliseconds. However time 
>>> between write() and printf("resume") is usually ~4.5 seconds and 
>>> this way too much.
>> 
>> 
>> It's not clear from your description how your application starts the 
>> ASYNC job in the first place. Are you using libssl to do this, or 
>> does your application call ASYNC_start_job() directly?
>> 
>> When your certificate validation code calls ASYNC_pause_job() control 
>> will return to your application. Control will not return until 
>> ASYNC_start_job() is called again. Depending on how you started the 
>> job in the first place this will either be due to your application 
>> explicitly calling ASYNC_start_job() directly, or (if it used libssl 
>> to start the job), then by recalling the I/O function that hit the 
>> pause originally.
>> 
>> Once ASYNC_start_job() is invoked then context swap should happen 
>> immediately (so ~4.5 seconds would be totally unexpected).
>> 
>> So please explain a little more about how your application starts the 
>> job, and how it monitors its progress in order to know when to 
>> resume.
>> 
>> Matt
>> 
>> 
>>> 
>>> 
>>> 
>>> Is there a reliable way (only when data is really ready) and a 
>>> prompt way (in order of micro/milli-seconds) to wake up from 
>>> ASYNC_pause_job()?
>>> 
>>> 
>>> 
>>> Many thanks, any help would be much appreciated.
>>> 
>>> 
>>> 
>>> Kind Regards,
>>> 
>>> Valerio Di Gregorio
>>> 
>> 


More information about the openssl-users mailing list