Skip to content

Commit

Permalink
fix(doip): Improve closing of open connections to avoid TIME_WAIT states
Browse files Browse the repository at this point in the history
  • Loading branch information
ferdinandjarisch committed Feb 28, 2024
1 parent fd26b81 commit b8c3ce0
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/gallia/transports/doip.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import asyncio
import errno
import struct
from dataclasses import dataclass
from enum import IntEnum, unique
Expand Down Expand Up @@ -374,6 +375,10 @@ async def _read_worker(self) -> None:
logger.debug(f"read worker received EOF: {e}")
except Exception as e:
logger.critical(f"read worker died with {type(e)}: {e}")
finally:
logger.debug("Feeding EOF to reader and requesting a close")
self.reader.feed_eof()
await self.close()

async def read_frame_unsafe(self) -> DoIPFrame:
# Avoid waiting on the queue forever when
Expand Down Expand Up @@ -538,11 +543,31 @@ async def write_alive_check_response(self) -> None:
await self.write_request_raw(hdr, payload)

async def close(self) -> None:
logger.debug("Closing DoIP connection...")
if self._is_closed:
logger.debug("Already closed!")
return
self._is_closed = True
logger.debug("Cancelling read worker")
self._read_task.cancel()
try:
logger.debug(
"Writing garbage to help our kernel realize the connection is closed to avoid TIME_WAIT"
)
self.writer.write(b"\xAF\xFE")
await self.writer.drain()
logger.debug("Writing EOF")
self.writer.write_eof()
await self.writer.drain()
except OSError as e:
if e.errno == errno.ENOTCONN:
logger.debug(
f"Could not write EOF, but expected since the kernel might already have closed the socket: {e!r}"
)
else:
raise e
self.writer.close()
logger.debug("Awaiting confirmation of closed writer")
await self.writer.wait_closed()


Expand Down

0 comments on commit b8c3ce0

Please sign in to comment.