-
Notifications
You must be signed in to change notification settings - Fork 109
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?
Changes from all commits
7aa24c3
f3569f5
0cb5320
7293b48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ | |
map_exceptions, | ||
) | ||
from .._models import Origin, Request, Response | ||
from .._synchronization import AsyncLock, AsyncShieldCancellation | ||
from .._synchronization import AsyncThreadLock | ||
from .._trace import Trace | ||
from .interfaces import AsyncConnectionInterface | ||
|
||
|
@@ -62,7 +62,9 @@ def __init__( | |
self._keepalive_expiry: Optional[float] = keepalive_expiry | ||
self._expire_at: Optional[float] = None | ||
self._state = HTTPConnectionState.NEW | ||
self._state_lock = AsyncLock() | ||
self._state_thread_lock = ( | ||
AsyncThreadLock() | ||
) # thread-lock for sync, no-op for async | ||
self._request_count = 0 | ||
self._h11_state = h11.Connection( | ||
our_role=h11.CLIENT, | ||
|
@@ -76,7 +78,9 @@ async def handle_async_request(self, request: Request) -> Response: | |
f"to {self._origin}" | ||
) | ||
|
||
async with self._state_lock: | ||
with self._state_thread_lock: | ||
# We ensure that state changes at the start and end of a | ||
# request/response cycle are thread-locked. | ||
if self._state in (HTTPConnectionState.NEW, HTTPConnectionState.IDLE): | ||
self._request_count += 1 | ||
self._state = HTTPConnectionState.ACTIVE | ||
|
@@ -137,9 +141,8 @@ async def handle_async_request(self, request: Request) -> Response: | |
}, | ||
) | ||
except BaseException as exc: | ||
with AsyncShieldCancellation(): | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. this isn't tracing anymore |
||
raise exc | ||
|
||
# Sending the request... | ||
|
@@ -242,8 +245,12 @@ async def _receive_event( | |
# mypy fails to narrow the type in the above if statement above | ||
return event # type: ignore[return-value] | ||
|
||
async def _response_closed(self) -> None: | ||
async with self._state_lock: | ||
def _connection_should_close(self) -> bool: | ||
# Once the response is complete we either need to move into | ||
# an IDLE or CLOSED state. | ||
with self._state_thread_lock: | ||
# We ensure that state changes at the start and end of a | ||
# request/response cycle are thread-locked. | ||
if ( | ||
self._h11_state.our_state is h11.DONE | ||
and self._h11_state.their_state is h11.DONE | ||
|
@@ -253,8 +260,10 @@ async def _response_closed(self) -> None: | |
if self._keepalive_expiry is not None: | ||
now = time.monotonic() | ||
self._expire_at = now + self._keepalive_expiry | ||
else: | ||
await self.aclose() | ||
return False | ||
|
||
self._state = HTTPConnectionState.CLOSED | ||
return True | ||
Comment on lines
+263
to
+266
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||
|
||
# Once the connection is no longer required... | ||
|
||
|
@@ -344,15 +353,16 @@ async def __aiter__(self) -> AsyncIterator[bytes]: | |
# If we get an exception while streaming the response, | ||
# we want to close the response (and possibly the connection) | ||
# before raising that exception. | ||
with AsyncShieldCancellation(): | ||
await self.aclose() | ||
if self._connection._connection_should_close(): | ||
await self._connection.aclose() | ||
raise exc | ||
|
||
async def aclose(self) -> None: | ||
if not self._closed: | ||
self._closed = True | ||
async with Trace("response_closed", logger, self._request): | ||
await self._connection._response_closed() | ||
async with Trace("response_closed", logger, self._request, kwargs={}): | ||
if not self._closed: | ||
self._closed = True | ||
if self._connection._connection_should_close(): | ||
Comment on lines
+361
to
+364
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the await inside the There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
await self._connection.aclose() | ||
|
||
|
||
class AsyncHTTP11UpgradeStream(AsyncNetworkStream): | ||
|
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