WIP: bpo-33694, asyncio: fix proactor transport pause/resume#7479
WIP: bpo-33694, asyncio: fix proactor transport pause/resume#7479vstinner wants to merge 1 commit intopython:masterfrom vstinner:proactor_cancel
Conversation
Fix pause_reading()/resume_reading() of proactor transpors: don't cancel overlapped WSARecv() anymore. Sometimes, cancelling an overlapped WSARecv() looses data since the I/O already completed, but Overlapped.cancel() silently ignores the ERROR_NOT_FOUND error of CancelIoEx(). If the transport is paused, store the result in the transport if it's paused, and only call data_received()/buffer_updated() on resuming reading. The complex part is when the read starts with data_received() but completes during reading is paused and a new protocol using buffer_updated() is set. Or the opposite: transition from buffer_updated() to data_received(). FIXME: get_buffer(-1) error is not handled yet and a fix unit tests on proactor which rely on implementation details are failing, but functional tests pass.
| assert self._pending_data is None | ||
| self._pending_data = data | ||
| else: | ||
| self._data_received(data) |
There was a problem hiding this comment.
I moved this code because it was easier for me, to be able to implement the switch from data_received to buffer_updated: "if self._protocol_use_buffer(): self._loop_reading__get_buffer(None)" below. I'm not sure if moving this code changes the semantics? It shouldn't, but 3 proactor tests are failing.
|
@1st1: What do you think of the overall design? Does it sound reasonable or crazy? |
|
I'm aware that 3 tests of test_asyncio are failing. I prefer to wait for a first round of review before looking at fixing them. |
|
I actually like the fix and I think it's a very nice way of solving the race between different protocols types after |
I don't think that my code for data_received() <=> buffer_updated() protocol transitions is safe. My code keeps a reference to the buffer of the previous protocol (after set_protocol()) and even write into the old buffer, again, even after set_protocol(). That's weird and counter-intuitive, and may lead to crazy bugs. All the complexity of my PR comes from the fact that proactor has two implementation to read: recv() and recv_into(). If we reimplemented recv_into() on top of recv(), the code becomes again managable, simple and straightforward. Well, it's not my idea, it's @1st1 idea :-) Since we are close to 3.7.0 final, I would prefer to first to loose data randomly, and then reconsider implementing recv_into() optimization :-) |
|
Here's an alternative PR, which I believe is simpler and more robust: #7486 |
|
This can now be closed, right? |
I wanted to close it, right. |
Fix pause_reading()/resume_reading() of proactor transpors: don't
cancel overlapped WSARecv() anymore. Sometimes, cancelling an
overlapped WSARecv() looses data since the I/O already completed, but
Overlapped.cancel() silently ignores the ERROR_NOT_FOUND error of
CancelIoEx().
If the transport is paused, store the result in the transport if it's
paused, and only call data_received()/buffer_updated() on resuming
reading.
The complex part is when the read starts with data_received() but
completes during reading is paused and a new protocol using
buffer_updated() is set. Or the opposite: transition from
buffer_updated() to data_received().
FIXME: get_buffer(-1) error is not handled yet and a fix unit tests
on proactor which rely on implementation details are failing, but
functional tests pass.
https://bugs.python.org/issue33694