> > Now the next question you might want to ask, "is it
> allowed for 
> > exactly two threads to operate specifically the
> SSL_read() and 
> > SSL_write() on the _SAME_ 'SSL *' instance at the same
> time ?"  My 
> > understanding would be that the answer is
> NO.   This is a limitation in 
> > the OpenSSL library, since some of the shared parts of
> 'SSL *' have no 
> > protection and the SSL_read() and SSL_write()
> code-paths have not been 
> > audited/reworked to minimize the contention/data-race
> issues.
> 
> This is how everything else works, it's odd to say it's
> somehow a limitation
> of OpenSSL that it works the same way everything else
> works. Try to read to
> a string in one thread while you write to it from another.

I think we've lost the point: if I write to a socket from more than one thread 
at a time, clearly I've messed up.  Even if the operating system doesn't 
complain, my stream is nonsense (unless I only ever write a single byte at a 
time).

However, it's clearly alright to read a socket from one thread while writing a 
socket from another: indeed, this is the purpose of a socket.  That OpenSSL 
doesn't allow this usage seems like a limitation of the library.  (Although 
maybe it's actually of the TLS protocol itself...?)

> The other gotcha is that if you use separate read and write
> threads, you
> *must* remember that an SSL connection only has one state.
> You cannot
> independently maintain your own state in each thread, or
> you can deadlock.

> You see, in step 4, the write thread *must* know that the
> read thread
> changed the SSL connection's status. Otherwise you
> deadlock.

Your explanation here is excellent.  If I understand it correctly it's not 
really the problem of multiple access to a shared buffer which would 
understandably cause corruption, it's that there's a single flag which 
indicates the 'direction' if you will of the SSL structure itself:

#define SSL_ERROR_WANT_READ             2
#define SSL_ERROR_WANT_WRITE            3

And since these are defined in such a way that you can't have both READ|WRITE 
at the same time, if I don't somehow externally remember this information and 
share it between my threads I could run into trouble.

Ok so to summarize you Dave and Darryl: Blocking sockets + OpenSSL will only 
work for a request-response model without redesigning the library itself, 
because external synchronization deadlocks (for obvious reasons) and no 
synchronization deadlocks because the library/application no longer know what 
needs to happen to make forward progress.

Forgive me if I misunderstand either of you, but it sounds like if I use 
non-blocking sockets, I'll be able to use but a single thread to both push & 
pull independent streams of data, and I don't have to wait for an interrupted 
write to complete in order to begin a new read, or vice versa, so long as I 
remember the actual WANT_* state of each stream.

I'd been warned away from non-blocking socket use in OpenSSL from the varies 
searches I did across this mailing list, but honestly I'd actually prefer to 
use them.

To make sure I'm clear on this: if I myself don't have any data to read and an 
SSL_write returns WANT_READ, that doesn't mean I myself need to call SSL_read-- 
what it means is I need to wait until the socket is readable, and then call 
SSL_write again (with the same args of course).

It'd be awesome if there was a 'canonical' example for this... I've read 
through several different applications using OpenSSL (stunnel, Ice, curl) but 
they're so heavily hacked up to overcome various system limitations / 
implementation needs that it's not entirely obvious what's going on.

Guess I'll go make that example now.  :)

Thanks much,

--jason



      
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to