-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove shielding from cancellation process. #927
base: master
Are you sure you want to change the base?
Conversation
async with Trace("response_closed", logger, self._request, kwargs={}): | ||
if not self._closed: | ||
self._closed = True | ||
if self._connection._connection_should_close(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the await inside the Trace.__aenter__
cause issues here? Ie can there be a cancellation with the await inside it that would cause a skip of the self._closed
-checks and self._connection._connection_should_close()
? (Might be a stupid question so sorry about that :D)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this is a problem, It's also a problem if the trace function raises, I think you'll need to do this:
# synchronization.py
aclose_forcefully = anyio.aclose_forcefully
def close_forcefully(sock):
sock.close()
async def aclose(self):
entered_cmgr = False
try:
async with Trace("response_closed", logger, self._request, kwargs={}):
entered_cmgr = True
if not self._closed:
self._closed = True
if self._connection._connection_should_close():
await self._connection.aclose()
except BaseException:
if entered_cmgr:
raise
if not self._closed:
self._closed = True
if self._connection._connection_should_close():
await aclose_forcefully(self._connection)
raise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also in connection_pool and http2
return False | ||
|
||
self._state = HTTPConnectionState.CLOSED | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why returning bool here? all references are trying to close connection, why avoid do it at here?
httpcore/.DS_Store
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
junk?
@tomchristie do you intend to take this over the line, or would it be helpful for someone else to try to take it over? (for context, users of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably don't want this file
async with Trace("response_closed", logger, self._request, kwargs={}): | ||
if not self._closed: | ||
self._closed = True | ||
if self._connection._connection_should_close(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this is a problem, It's also a problem if the trace function raises, I think you'll need to do this:
# synchronization.py
aclose_forcefully = anyio.aclose_forcefully
def close_forcefully(sock):
sock.close()
async def aclose(self):
entered_cmgr = False
try:
async with Trace("response_closed", logger, self._request, kwargs={}):
entered_cmgr = True
if not self._closed:
self._closed = True
if self._connection._connection_should_close():
await self._connection.aclose()
except BaseException:
if entered_cmgr:
raise
if not self._closed:
self._closed = True
if self._connection._connection_should_close():
await aclose_forcefully(self._connection)
raise
async with Trace("response_closed", logger, request) as trace: | ||
await self._response_closed() | ||
if self._connection_should_close(): | ||
await self._network_stream.aclose() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't tracing anymore
Any update here? Would contributions be welcome? |
For handling async-cancellations we're currently shielding
close
operations, in order to ensure we don't end up with a connection in an inconsistent state when cancellations are used.A better approach is to ensure that the state changes for this case are handled synchronously (so that cancellations won't propagate into those). While the network close remains unshielded async (it's okay for cancellations to propagate into those).
Reasoning about the state when cancellations occur is a bit fiddly, tho I think we can apply this same style of approach all the way through to remove the need for async cancellation-shielding. (Closing state is applied first synchronously. Network close operations are then attempted, and may propagate cancellation.)
Refs #922