> > 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 [email protected]
Automated List Manager [email protected]