classification
Title: SSLWantWriteError being raised by blocking SSL socket
Type: behavior Stage:
Components: Library (Lib), SSL Versions: Python 3.7, Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: christian.heimes Nosy List: alex, christian.heimes, dstufft, janssen, njs, pitrou
Priority: normal Keywords:

Created on 2017-12-05 04:01 by njs, last changed 2017-12-05 11:10 by njs.

Messages (4)
msg307634 - (view) Author: Nathaniel Smith (njs) * Date: 2017-12-05 04:01
I have a test case that sets up a blocking SSLSocket, and eventually calls unwrap() to do a proper SSL shutdown.

Every once in a while, the test blows up, because unwrap() unexpectedly raises SSLWantWriteError. This is very unexpected for a blocking socket.

Unfortunately, since this is intermittent, I don't have a reliable reproducer.

Both of the times I've seen this so far, it was on MacOS with CPython 3.6 (the official python.org build, so whichever openssl it uses), and it was specifically in unwrap():

    https://travis-ci.org/python-trio/trio/jobs/298164123
    https://travis-ci.org/python-trio/trio/jobs/311618077

Here's the code that fails -- as you can see it's just a straightforward blocking echo server using SSLContext.wrap_socket:

    https://github.com/python-trio/trio/blob/3e62bf64946b1dcbf42c2d03e39435d4b1ba00ac/trio/tests/test_ssl.py#L92
msg307636 - (view) Author: Nathaniel Smith (njs) * Date: 2017-12-05 04:05
Oh darn, I restarted the 311618077 build on Travis and apparently that makes it delete the log. Well, it was the same traceback as the one that's left, but triggered by a different test.
msg307648 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-12-05 08:44
You might want to add debugging code in _ssl__SSLSocket_shutdown_impl() (Modules/_ssl.c) and see what happens exactly.

Does your socket have a timeout?  If not, you may want to ask the OpenSSL mailing-list whether it's possible for SSL_shutdown to return SSL_ERROR_WANT_WRITE on a blocking socket...

PS: it seems the _ssl module doesn't retry I/O routines on EINTR. See also https://stackoverflow.com/questions/24188013/openssl-and-signals
msg307655 - (view) Author: Nathaniel Smith (njs) * Date: 2017-12-05 11:10
There's no timeout. The man page claims SSL_ERROR_WANT_WRITE can't happen on a blocking socket, but who knows...

Re: EINTR, this is all happening in a child thread. On Linux, this would mean that it almost certainly isn't receiving any signals. I'm not sure about MacOS, though. (POSIX allows signals to be delivered to any thread, but most Unixes are much more conservative in practice.)
History
Date User Action Args
2017-12-05 11:10:00njssetmessages: + msg307655
2017-12-05 08:44:10pitrousetversions: + Python 3.7
nosy: + pitrou

messages: + msg307648

components: + Library (Lib)
type: behavior
2017-12-05 04:05:42njssetmessages: + msg307636
2017-12-05 04:01:08njscreate