@@ -266,6 +266,7 @@ def _add_reader(self, fd, callback, *args):
266266 (handle , writer ))
267267 if reader is not None :
268268 reader .cancel ()
269+ return handle
269270
270271 def _remove_reader (self , fd ):
271272 if self .is_closed ():
@@ -302,6 +303,7 @@ def _add_writer(self, fd, callback, *args):
302303 (reader , handle ))
303304 if writer is not None :
304305 writer .cancel ()
306+ return handle
305307
306308 def _remove_writer (self , fd ):
307309 """Remove a writer callback."""
@@ -329,7 +331,7 @@ def _remove_writer(self, fd):
329331 def add_reader (self , fd , callback , * args ):
330332 """Add a reader callback."""
331333 self ._ensure_fd_no_transport (fd )
332- return self ._add_reader (fd , callback , * args )
334+ self ._add_reader (fd , callback , * args )
333335
334336 def remove_reader (self , fd ):
335337 """Remove a reader callback."""
@@ -339,7 +341,7 @@ def remove_reader(self, fd):
339341 def add_writer (self , fd , callback , * args ):
340342 """Add a writer callback.."""
341343 self ._ensure_fd_no_transport (fd )
342- return self ._add_writer (fd , callback , * args )
344+ self ._add_writer (fd , callback , * args )
343345
344346 def remove_writer (self , fd ):
345347 """Remove a writer callback."""
@@ -362,13 +364,15 @@ async def sock_recv(self, sock, n):
362364 pass
363365 fut = self .create_future ()
364366 fd = sock .fileno ()
365- self .add_reader (fd , self ._sock_recv , fut , sock , n )
367+ self ._ensure_fd_no_transport (fd )
368+ handle = self ._add_reader (fd , self ._sock_recv , fut , sock , n )
366369 fut .add_done_callback (
367- functools .partial (self ._sock_read_done , fd ))
370+ functools .partial (self ._sock_read_done , fd , handle = handle ))
368371 return await fut
369372
370- def _sock_read_done (self , fd , fut ):
371- self .remove_reader (fd )
373+ def _sock_read_done (self , fd , fut , handle = None ):
374+ if handle is None or not handle .cancelled ():
375+ self .remove_reader (fd )
372376
373377 def _sock_recv (self , fut , sock , n ):
374378 # _sock_recv() can add itself as an I/O callback if the operation can't
@@ -401,9 +405,10 @@ async def sock_recv_into(self, sock, buf):
401405 pass
402406 fut = self .create_future ()
403407 fd = sock .fileno ()
404- self .add_reader (fd , self ._sock_recv_into , fut , sock , buf )
408+ self ._ensure_fd_no_transport (fd )
409+ handle = self ._add_reader (fd , self ._sock_recv_into , fut , sock , buf )
405410 fut .add_done_callback (
406- functools .partial (self ._sock_read_done , fd ))
411+ functools .partial (self ._sock_read_done , fd , handle = handle ))
407412 return await fut
408413
409414 def _sock_recv_into (self , fut , sock , buf ):
@@ -446,11 +451,12 @@ async def sock_sendall(self, sock, data):
446451
447452 fut = self .create_future ()
448453 fd = sock .fileno ()
449- fut .add_done_callback (
450- functools .partial (self ._sock_write_done , fd ))
454+ self ._ensure_fd_no_transport (fd )
451455 # use a trick with a list in closure to store a mutable state
452- self .add_writer (fd , self ._sock_sendall , fut , sock ,
453- memoryview (data ), [n ])
456+ handle = self ._add_writer (fd , self ._sock_sendall , fut , sock ,
457+ memoryview (data ), [n ])
458+ fut .add_done_callback (
459+ functools .partial (self ._sock_write_done , fd , handle = handle ))
454460 return await fut
455461
456462 def _sock_sendall (self , fut , sock , view , pos ):
@@ -502,18 +508,21 @@ def _sock_connect(self, fut, sock, address):
502508 # connection runs in background. We have to wait until the socket
503509 # becomes writable to be notified when the connection succeed or
504510 # fails.
511+ self ._ensure_fd_no_transport (fd )
512+ handle = self ._add_writer (
513+ fd , self ._sock_connect_cb , fut , sock , address )
505514 fut .add_done_callback (
506- functools .partial (self ._sock_write_done , fd ))
507- self .add_writer (fd , self ._sock_connect_cb , fut , sock , address )
515+ functools .partial (self ._sock_write_done , fd , handle = handle ))
508516 except (SystemExit , KeyboardInterrupt ):
509517 raise
510518 except BaseException as exc :
511519 fut .set_exception (exc )
512520 else :
513521 fut .set_result (None )
514522
515- def _sock_write_done (self , fd , fut ):
516- self .remove_writer (fd )
523+ def _sock_write_done (self , fd , fut , handle = None ):
524+ if handle is None or not handle .cancelled ():
525+ self .remove_writer (fd )
517526
518527 def _sock_connect_cb (self , fut , sock , address ):
519528 if fut .done ():
0 commit comments