Skip to content

Commit df7df29

Browse files
authored
Only call connection_lost after the serial port is actually closed (#16)
1 parent 9822bd0 commit df7df29

File tree

1 file changed

+25
-20
lines changed

1 file changed

+25
-20
lines changed

serial_asyncio_fast/__init__.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,16 @@
1717
"""
1818
import asyncio
1919
import os
20+
import logging
2021
import urllib.parse
2122
from functools import partial
2223
from typing import Any, Callable, Coroutine, List, Optional, Set, Tuple, Union
2324

2425
import 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

483488
async def create_serial_connection(

0 commit comments

Comments
 (0)