Commit 72f6f386 authored by Jason Madden's avatar Jason Madden

Always unwrap the SSL socket before shutting it down.

parent d37c8ea9
......@@ -612,6 +612,7 @@ class SSLSocket(socket):
# that with a layer.
shutdown = self._sslobj.unwrap
s = self._sock
while True:
try:
s = shutdown()
......@@ -627,6 +628,12 @@ class SSLSocket(socket):
if self.timeout == 0.0:
raise
self._wait(self._write_event)
except OSError as e:
if e.errno == 0:
# What does this even mean? Seen on 3.7+.
break
raise
self._sslobj = None
......
......@@ -564,7 +564,13 @@ class SSLSocket(socket):
if not self._sslobj:
raise ValueError("No SSL wrapper around " + str(self))
s = self._sslobj_shutdown()
s = self._sock
try:
s = self._sslobj_shutdown()
except socket_error as ex:
if ex.args[0] != 0:
raise
self._sslobj = None
# match _ssl2; critical to drop/reuse here on PyPy
# XXX: _ssl3 returns an SSLSocket. Is that what the standard lib does on
......
......@@ -1228,7 +1228,9 @@ if PY37:
if APPVEYOR:
disabled_tests += [
# This sometimes produces ``self.assertEqual(1, len(s.select(0))): 1 != 0``.
# Probably needs to spin the loop once.
'test_selectors.DefaultSelectorTestCase.test_timeout',
]
if PY38:
......@@ -1283,16 +1285,13 @@ if OSX:
disabled_tests += [
# This sometimes produces OSError: Errno 40: Message too long
'test_socket.RecvmsgIntoTCPTest.testRecvmsgIntoGenerator',
]
if RUNNING_ON_CI:
disabled_tests += [
# These sometime timeout. Cannot reproduce locally.
'test_ftp.TestTLS_FTPClassMixin.test_mlsd',
'test_ftp.TestTLS_FTPClassMixin.test_retrlines_too_long',
'test_ftp.TestTLS_FTPClassMixin.test_storlines',
]
# These sometime timeout. Cannot reproduce locally.
'test_ftp.TestTLS_FTPClassMixin.test_mlsd',
'test_ftp.TestTLS_FTPClassMixin.test_retrlines_too_long',
'test_ftp.TestTLS_FTPClassMixin.test_storlines',
'test_ftp.TestTLS_FTPClassMixin.test_retrbinary_rest',
]
if RESOLVER_ARES and PY38 and not RUNNING_ON_CI:
disabled_tests += [
......
......@@ -309,6 +309,7 @@ class TestDefaultSpawn(TestCase):
self.ServerClass(self.get_listener(), backlog=25)
@greentest.skipOnLibuvOnCIOnPyPy("Sometimes times out")
@greentest.skipOnAppVeyor("Sometimes times out.")
def test_backlog_is_accepted_for_address(self):
self.server = self.ServerSubClass((greentest.DEFAULT_BIND_ADDR, 0), backlog=25)
self.assertConnectionRefused()
......
......@@ -166,20 +166,6 @@ class TestTCP(greentest.TestCase):
log("creating client connection")
client = self.create_connection(**client_args)
# We seem to have a buffer stuck somewhere on appveyor?
# https://ci.appveyor.com/project/denik/gevent/builds/27320824/job/bdbax88sqnjoti6i#L712
should_unwrap = hasattr(client, 'unwrap') and greentest.PY37 and greentest.WIN
# The implicit reference-based nastiness of Python 2
# sockets interferes, especially when using SSL sockets.
# The best way to get a decent FIN to the server is to shutdown
# the output. Doing that on Python 3, OTOH, is contraindicated
# except on PyPy, so this used to read ``PY2 or PYPY``. But
# it seems that a shutdown is generally good practice, and I didn't
# document what errors we saw without it. Per issue #1637
# lets do a shutdown everywhere.
should_shutdown = 1
# It's important to wait for the server to fully accept before
# we shutdown and close the socket. In SSL mode, the number
# and timing of data exchanges to complete the handshake and
......@@ -200,29 +186,32 @@ class TestTCP(greentest.TestCase):
try:
x = getattr(client, client_method)(data)
log("Client sent data: result from method", x)
except:
# unwrapping might not work after this because we're in
# a bad state.
if should_unwrap:
client.shutdown(socket.SHUT_RDWR)
should_unwrap = False
should_shutdown = False
raise
finally:
log("Client will: Shutdown?", should_shutdown, "Unwrap?", should_unwrap)
if should_shutdown:
client.shutdown(socket.SHUT_RDWR)
elif should_unwrap:
log("Client will unwrap and shutdown")
if hasattr(client, 'unwrap'):
# Are we dealing with an SSLSocket? If so, unwrap it
# before attempting to shut down the socket. This does the
# SSL shutdown handshake and (hopefully) stops ``accept_and_read``
# from generating ``ConnectionResetError`` on AppVeyor.
try:
client.unwrap()
except OSError as e:
if greentest.PY37 and greentest.WIN and e.errno == 0:
# ? 3.7.4 on AppVeyor sometimes raises
# "OSError[errno 0] Error" here, which doesn't make
# any sense.
pass
else:
raise
client = client.unwrap()
except ValueError:
pass
try:
# The implicit reference-based nastiness of Python 2
# sockets interferes, especially when using SSL sockets.
# The best way to get a decent FIN to the server is to shutdown
# the output. Doing that on Python 3, OTOH, is contraindicated
# except on PyPy, so this used to read ``PY2 or PYPY``. But
# it seems that a shutdown is generally good practice, and I didn't
# document what errors we saw without it. Per issue #1637
# lets do a shutdown everywhere, but only after removing any
# SSL wrapping.
client.shutdown(socket.SHUT_RDWR)
except (OSError, socket.error):
pass
log("Client will close")
client.close()
finally:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment