Issues with ASYNC_pause_job() wake up
Matt Caswell
matt at openssl.org
Tue Feb 11 15:13:40 UTC 2020
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