bpo-33694: Fix race condition in asyncio proactor (GH-7498)

The cancellation of an overlapped WSARecv() has a race condition
which causes data loss because of the current implementation of
proactor in asyncio.

No longer cancel overlapped WSARecv() in _ProactorReadPipeTransport
to work around the race condition.

Remove the optimized recv_into() implementation to get simple
implementation of pause_reading() using the single _pending_data
attribute.

Move _feed_data_to_bufferred_proto() to protocols.py.

Remove set_protocol() method which became useless.
This commit is contained in:
Victor Stinner 2018-06-08 00:25:52 +02:00 committed by GitHub
parent d3ed67d14e
commit 79790bc35f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 152 deletions

View file

@ -11,6 +11,7 @@ except ImportError:
import asyncio
from asyncio import log
from asyncio import protocols
from asyncio import sslproto
from asyncio import tasks
from test.test_asyncio import utils as test_utils
@ -189,28 +190,28 @@ class BaseStartTLS(func_tests.FunctionalTestCaseMixin):
for usemv in [False, True]:
proto = Proto(1, usemv)
sslproto._feed_data_to_bufferred_proto(proto, b'12345')
protocols._feed_data_to_bufferred_proto(proto, b'12345')
self.assertEqual(proto.data, b'12345')
proto = Proto(2, usemv)
sslproto._feed_data_to_bufferred_proto(proto, b'12345')
protocols._feed_data_to_bufferred_proto(proto, b'12345')
self.assertEqual(proto.data, b'12345')
proto = Proto(2, usemv)
sslproto._feed_data_to_bufferred_proto(proto, b'1234')
protocols._feed_data_to_bufferred_proto(proto, b'1234')
self.assertEqual(proto.data, b'1234')
proto = Proto(4, usemv)
sslproto._feed_data_to_bufferred_proto(proto, b'1234')
protocols._feed_data_to_bufferred_proto(proto, b'1234')
self.assertEqual(proto.data, b'1234')
proto = Proto(100, usemv)
sslproto._feed_data_to_bufferred_proto(proto, b'12345')
protocols._feed_data_to_bufferred_proto(proto, b'12345')
self.assertEqual(proto.data, b'12345')
proto = Proto(0, usemv)
with self.assertRaisesRegex(RuntimeError, 'empty buffer'):
sslproto._feed_data_to_bufferred_proto(proto, b'12345')
protocols._feed_data_to_bufferred_proto(proto, b'12345')
def test_start_tls_client_reg_proto_1(self):
HELLO_MSG = b'1' * self.PAYLOAD_SIZE