Title: SSLWantWriteError being raised by blocking SSL socket
Type: behavior Stage:
Components: Library (Lib), SSL Versions: Python 3.7, Python 3.6
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) * (Python committer) 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 build, so whichever openssl it uses), and it was specifically in unwrap():

Here's the code that fails -- as you can see it's just a straightforward blocking echo server using SSLContext.wrap_socket:
msg307636 - (view) Author: Nathaniel Smith (njs) * (Python committer) 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
msg307655 - (view) Author: Nathaniel Smith (njs) * (Python committer) 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.)
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