mirror of
https://github.com/smittix/intercept.git
synced 2026-06-09 06:31:55 -07:00
Fix WeFax start/stop/SSE reliability
- Replace blocking stdout.read() with select()-based non-blocking reads so the decode thread responds to stop within 0.5s - Make stop() non-blocking by releasing the lock before terminating the process and removing the redundant wait() - Move initial scanning SSE event from start() into the decode thread so it fires after the frontend EventSource connects - Update frontend stop() to give immediate UI feedback before the fetch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -205,16 +205,20 @@ var WeFax = (function () {
|
||||
}
|
||||
|
||||
function stop() {
|
||||
// Immediate UI feedback before waiting for backend response
|
||||
state.running = false;
|
||||
updateButtons(false);
|
||||
setStatus('Stopping...');
|
||||
disconnectSSE();
|
||||
|
||||
fetch('/wefax/stop', { method: 'POST' })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function () {
|
||||
state.running = false;
|
||||
updateButtons(false);
|
||||
setStatus('Stopped');
|
||||
disconnectSSE();
|
||||
loadImages();
|
||||
})
|
||||
.catch(function (err) {
|
||||
setStatus('Stopped');
|
||||
console.error('WeFax stop error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
+35
-16
@@ -15,6 +15,8 @@ import base64
|
||||
import contextlib
|
||||
import io
|
||||
import math
|
||||
import os
|
||||
import select
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
@@ -297,11 +299,6 @@ class WeFaxDecoder:
|
||||
f"WeFax decoder started: {frequency_khz} kHz, "
|
||||
f"station={station}, IOC={ioc}, LPM={lpm}"
|
||||
)
|
||||
self._emit_progress(WeFaxProgress(
|
||||
status='scanning',
|
||||
station=station,
|
||||
message=f'Scanning {frequency_khz} kHz for WeFax start tone...',
|
||||
))
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
@@ -395,9 +392,29 @@ class WeFaxDecoder:
|
||||
f"samples/line={samples_per_line}"
|
||||
)
|
||||
|
||||
# Emit initial scanning progress here (not in start()) so the
|
||||
# frontend SSE connection is established before this event fires.
|
||||
time.sleep(0.1)
|
||||
self._emit_progress(WeFaxProgress(
|
||||
status='scanning',
|
||||
station=self._station,
|
||||
message=f'Scanning {self._frequency_khz} kHz for WeFax start tone...',
|
||||
))
|
||||
|
||||
while self._running and self._rtl_process:
|
||||
try:
|
||||
raw_data = self._rtl_process.stdout.read(chunk_bytes)
|
||||
proc = self._rtl_process
|
||||
if not proc or not proc.stdout:
|
||||
break
|
||||
# Non-blocking read via select() — allows checking _running
|
||||
# on timeout instead of blocking indefinitely in read().
|
||||
fd = proc.stdout.fileno()
|
||||
ready, _, _ = select.select([fd], [], [], 0.5)
|
||||
if not ready:
|
||||
if not self._running:
|
||||
break
|
||||
continue
|
||||
raw_data = os.read(fd, chunk_bytes)
|
||||
if not raw_data:
|
||||
if self._running:
|
||||
stderr_msg = ''
|
||||
@@ -667,20 +684,22 @@ class WeFaxDecoder:
|
||||
))
|
||||
|
||||
def stop(self) -> None:
|
||||
"""Stop WeFax decoder."""
|
||||
"""Stop WeFax decoder.
|
||||
|
||||
Non-blocking: sets _running=False and terminates the process,
|
||||
then returns immediately. The decode thread handles cleanup
|
||||
when its read() returns empty.
|
||||
"""
|
||||
with self._lock:
|
||||
self._running = False
|
||||
proc = self._rtl_process
|
||||
self._rtl_process = None
|
||||
|
||||
if self._rtl_process:
|
||||
try:
|
||||
self._rtl_process.terminate()
|
||||
self._rtl_process.wait(timeout=5)
|
||||
except Exception:
|
||||
with contextlib.suppress(Exception):
|
||||
self._rtl_process.kill()
|
||||
self._rtl_process = None
|
||||
if proc:
|
||||
with contextlib.suppress(Exception):
|
||||
proc.terminate()
|
||||
|
||||
logger.info("WeFax decoder stopped")
|
||||
logger.info("WeFax decoder stopped")
|
||||
|
||||
def get_images(self) -> list[WeFaxImage]:
|
||||
"""Get list of decoded images."""
|
||||
|
||||
Reference in New Issue
Block a user