@@ -224,6 +224,7 @@ def __init__(self, stream_reader, client_connected_cb=None, loop=None):
224224 self ._stream_writer = None
225225 self ._client_connected_cb = client_connected_cb
226226 self ._over_ssl = False
227+ self ._closed = self ._loop .create_future ()
227228
228229 def connection_made (self , transport ):
229230 self ._stream_reader .set_transport (transport )
@@ -243,6 +244,11 @@ def connection_lost(self, exc):
243244 self ._stream_reader .feed_eof ()
244245 else :
245246 self ._stream_reader .set_exception (exc )
247+ if not self ._closed .done ():
248+ if exc is None :
249+ self ._closed .set_result (None )
250+ else :
251+ self ._closed .set_exception (exc )
246252 super ().connection_lost (exc )
247253 self ._stream_reader = None
248254 self ._stream_writer = None
@@ -259,6 +265,13 @@ def eof_received(self):
259265 return False
260266 return True
261267
268+ def __del__ (self ):
269+ # Prevent reports about unhandled exceptions.
270+ # Better than self._closed._log_traceback = False hack
271+ closed = self ._closed
272+ if closed .done () and not closed .cancelled ():
273+ closed .exception ()
274+
262275
263276class StreamWriter :
264277 """Wraps a Transport.
@@ -303,6 +316,12 @@ def can_write_eof(self):
303316 def close (self ):
304317 return self ._transport .close ()
305318
319+ def is_closing (self ):
320+ return self ._transport .is_closing ()
321+
322+ async def wait_closed (self ):
323+ await self ._protocol ._closed
324+
306325 def get_extra_info (self , name , default = None ):
307326 return self ._transport .get_extra_info (name , default )
308327
@@ -318,15 +337,14 @@ async def drain(self):
318337 exc = self ._reader .exception ()
319338 if exc is not None :
320339 raise exc
321- if self ._transport is not None :
322- if self ._transport .is_closing ():
323- # Yield to the event loop so connection_lost() may be
324- # called. Without this, _drain_helper() would return
325- # immediately, and code that calls
326- # write(...); await drain()
327- # in a loop would never call connection_lost(), so it
328- # would not see an error when the socket is closed.
329- await sleep (0 , loop = self ._loop )
340+ if self ._transport .is_closing ():
341+ # Yield to the event loop so connection_lost() may be
342+ # called. Without this, _drain_helper() would return
343+ # immediately, and code that calls
344+ # write(...); await drain()
345+ # in a loop would never call connection_lost(), so it
346+ # would not see an error when the socket is closed.
347+ await sleep (0 , loop = self ._loop )
330348 await self ._protocol ._drain_helper ()
331349
332350
0 commit comments