1717"""
1818import asyncio
1919import os
20+ import logging
2021import urllib .parse
2122from functools import partial
2223from typing import Any , Callable , Coroutine , List , Optional , Set , Tuple , Union
2324
2425import serial
2526
26- try :
27- import termios
28- except ImportError :
29- termios = None
30-
3127__version__ = "0.13"
3228
29+ _LOGGER = logging .getLogger (__name__ )
3330
3431# Prevent tasks from being garbage collected.
3532_BACKGROUND_TASKS : Set [asyncio .Task ] = set ()
@@ -438,7 +435,7 @@ def _close(self, exc: Optional[Exception] = None) -> None:
438435 self ._remove_reader ()
439436 if self ._flushed ():
440437 self ._remove_writer ()
441- _create_background_task (self ._call_connection_lost (exc ))
438+ _create_background_task (self ._call_connection_lost (exc , flush = True ))
442439
443440 def _abort (self , exc : Optional [BaseException ]) -> None :
444441 """Close the transport immediately.
@@ -452,9 +449,11 @@ def _abort(self, exc: Optional[BaseException]) -> None:
452449 self ._closing = True
453450 self ._remove_reader ()
454451 self ._remove_writer () # Pending buffered data will not be written
455- _create_background_task (self ._call_connection_lost (exc ))
452+ _create_background_task (self ._call_connection_lost (exc , flush = False ))
456453
457- async def _call_connection_lost (self , exc : Optional [Exception ]) -> None :
454+ async def _call_connection_lost (
455+ self , exc : Optional [Exception ], * , flush : bool
456+ ) -> None :
458457 """Close the connection.
459458
460459 Informs the protocol through connection_lost() and clears
@@ -463,21 +462,27 @@ async def _call_connection_lost(self, exc: Optional[Exception]) -> None:
463462 assert self ._closing
464463 assert not self ._has_writer
465464 assert not self ._has_reader
466- try :
467- await self ._loop .run_in_executor (None , self ._serial .flush )
468- except serial .SerialException if os .name == "nt" else termios .error :
469- # ignore serial errors which may happen if the serial device was
470- # hot-unplugged.
471- pass
465+
466+ # The write buffer is either empty by this point or we are aborting
467+ self ._write_buffer .clear ()
468+
469+ if flush :
470+ try :
471+ await self ._loop .run_in_executor (None , self ._serial .flush )
472+ except Exception :
473+ _LOGGER .debug ("Failed to flush serial connection" , exc_info = True )
472474
473475 try :
474- self ._protocol .connection_lost (exc )
475- finally :
476- self ._write_buffer .clear ()
477476 await self ._loop .run_in_executor (None , self ._serial .close )
478- self ._serial = None
479- self ._protocol = None
480- self ._loop = None
477+ except Exception :
478+ _LOGGER .debug ("Failed to close serial connection" , exc_info = True )
479+
480+ self ._serial = None
481+ self ._loop = None
482+
483+ # Only call `connection_lost` once everything else is done
484+ self ._protocol .connection_lost (exc )
485+ self ._protocol = None
481486
482487
483488async def create_serial_connection (
0 commit comments