#10 transport (obdcore/transport.py): - TcpTransport.read raises IOError on a real socket error or peer-close instead of swallowing it as a timeout, so a dead WiFi link surfaces (via the #8 poll handler) as 'connection lost' rather than a frozen dashboard. - TcpTransport.reset_input_buffer drains at most 64 chunks — never spins forever. - BleTransport closes the client + stops the event-loop thread on connect timeout (no leak), caps the notification buffer at 64 KiB, and close() is robust when only partially initialised. #11 controller (gui/controller.py, obdcore/store.py): - connect() closes the transport and nulls the link if init()/connect() raises, so a failed/retried connect doesn't orphan sockets/threads. - stop_record() unhooks store.recorder BEFORE closing it, and CsvRecorder now has a 'closed' guard so a poll-thread write racing close() is a no-op instead of an I/O-on-closed-file crash. Closes #10 Closes #11 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs
This commit is contained in:
+18
-8
@@ -76,12 +76,21 @@ class Controller:
|
||||
self.link = ElmLink.ble(c["address"])
|
||||
else:
|
||||
self.link = ElmLink.serial(c.get("port", port), c.get("baud", baud))
|
||||
self.link.init()
|
||||
ok = self.link.connect()
|
||||
try:
|
||||
self.link.fast_timing(True)
|
||||
try: # don't leak the transport if handshake fails
|
||||
if not mock:
|
||||
self.link.init()
|
||||
ok = self.link.connect()
|
||||
try:
|
||||
self.link.fast_timing(True)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.link.close()
|
||||
except Exception:
|
||||
pass
|
||||
self.link = None
|
||||
raise
|
||||
self.poll_error = None
|
||||
self.sched = PollScheduler(self.link, self.reg, self.store, clock=time.time,
|
||||
on_error=self._on_poll_error)
|
||||
@@ -119,9 +128,10 @@ class Controller:
|
||||
self.store.recorder = CsvRecorder(path)
|
||||
|
||||
def stop_record(self):
|
||||
if self.store.recorder:
|
||||
self.store.recorder.close()
|
||||
self.store.recorder = None
|
||||
rec = self.store.recorder
|
||||
if rec:
|
||||
self.store.recorder = None # unhook first so the poll thread stops writing
|
||||
rec.close()
|
||||
|
||||
def now(self):
|
||||
return (time.time() - self.t0) if self.t0 else 0.0
|
||||
|
||||
Reference in New Issue
Block a user