Skip to content

Commit 96353fe

Browse files
committed
Handle aborted transport connections gracefully
1 parent 46dca86 commit 96353fe

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

uvloop/handles/basetransport.pyx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,12 @@ cdef class UVBaseTransport(UVSocketHandle):
117117
cdef _wakeup_waiter(self):
118118
if self._waiter is not None:
119119
if not self._waiter.cancelled():
120-
self._waiter.set_result(True)
120+
if not self._is_alive():
121+
self._waiter.set_exception(
122+
RuntimeError(
123+
'closed Transport handle and unset waiter'))
124+
else:
125+
self._waiter.set_result(True)
121126
self._waiter = None
122127

123128
cdef _call_connection_made(self):
@@ -126,7 +131,10 @@ cdef class UVBaseTransport(UVSocketHandle):
126131
raise RuntimeError(
127132
'protocol is not set, cannot call connection_made()')
128133

129-
if self._closing:
134+
# We use `_is_alive()` and not `_closing`, because we call
135+
# `transport._close()` in `loop.create_connection()` if an
136+
# exception happens during `await waiter`.
137+
if not self._is_alive():
130138
# A connection waiter can be cancelled between
131139
# 'await loop.create_connection()' and
132140
# `_schedule_call_connection_made` and
@@ -147,7 +155,7 @@ cdef class UVBaseTransport(UVSocketHandle):
147155
self._wakeup_waiter()
148156
raise
149157

150-
if self._closing:
158+
if not self._is_alive():
151159
# This might happen when "transport.abort()" is called
152160
# from "Protocol.connection_made".
153161
self._wakeup_waiter()

uvloop/handles/stream.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ cdef class UVStream(UVBaseTransport):
254254

255255
cdef _start_reading(self):
256256
cdef int err
257+
258+
if self._closing:
259+
return
260+
257261
self._ensure_alive()
258262

259263
if self.__reading:

uvloop/loop.pyx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,11 @@ cdef class Loop:
17551755
tr._init_protocol()
17561756
await waiter
17571757
except:
1758+
# It's OK to call `_close()` here, as opposed to
1759+
# `_force_close()` or `close()` as we want to terminate the
1760+
# transport immediately. The `waiter` can only be waken
1761+
# up in `Transport._call_connection_made()`, and calling
1762+
# `_close()` before it is fine.
17581763
tr._close()
17591764
raise
17601765

0 commit comments

Comments
 (0)