mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Fix USB device contention when starting audio pipeline
Add retry mechanism (3 attempts) for usb_claim_interface errors when the SDR device hasn't been fully released by a previous process. Also kill rtl_power alongside rtl_fm during cleanup and increase the USB release delay. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -731,35 +731,48 @@ def _start_audio_stream(frequency: float, modulation: str):
|
|||||||
shell_cmd = f"{' '.join(sdr_cmd)} 2>{rtl_stderr_log} | {' '.join(encoder_cmd)} 2>{ffmpeg_stderr_log}"
|
shell_cmd = f"{' '.join(sdr_cmd)} 2>{rtl_stderr_log} | {' '.join(encoder_cmd)} 2>{ffmpeg_stderr_log}"
|
||||||
logger.info(f"Starting audio: {frequency} MHz, mod={modulation}, device={scanner_config['device']}")
|
logger.info(f"Starting audio: {frequency} MHz, mod={modulation}, device={scanner_config['device']}")
|
||||||
|
|
||||||
audio_rtl_process = None # Not used in shell mode
|
# Retry loop for USB device contention (device may not be
|
||||||
audio_process = subprocess.Popen(
|
# released immediately after a previous process exits)
|
||||||
shell_cmd,
|
max_attempts = 3
|
||||||
shell=True,
|
for attempt in range(max_attempts):
|
||||||
stdout=subprocess.PIPE,
|
audio_rtl_process = None # Not used in shell mode
|
||||||
stderr=subprocess.PIPE,
|
audio_process = subprocess.Popen(
|
||||||
bufsize=0,
|
shell_cmd,
|
||||||
start_new_session=True # Create new process group for clean shutdown
|
shell=True,
|
||||||
)
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
bufsize=0,
|
||||||
|
start_new_session=True # Create new process group for clean shutdown
|
||||||
|
)
|
||||||
|
|
||||||
# Brief delay to check if process started successfully
|
# Brief delay to check if process started successfully
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
|
|
||||||
if audio_process.poll() is not None:
|
if audio_process.poll() is not None:
|
||||||
# Read stderr from temp files
|
# Read stderr from temp files
|
||||||
rtl_stderr = ''
|
rtl_stderr = ''
|
||||||
ffmpeg_stderr = ''
|
ffmpeg_stderr = ''
|
||||||
try:
|
try:
|
||||||
with open(rtl_stderr_log, 'r') as f:
|
with open(rtl_stderr_log, 'r') as f:
|
||||||
rtl_stderr = f.read().strip()
|
rtl_stderr = f.read().strip()
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
with open(ffmpeg_stderr_log, 'r') as f:
|
with open(ffmpeg_stderr_log, 'r') as f:
|
||||||
ffmpeg_stderr = f.read().strip()
|
ffmpeg_stderr = f.read().strip()
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}, ffmpeg stderr: {ffmpeg_stderr}")
|
|
||||||
return
|
if 'usb_claim_interface' in rtl_stderr and attempt < max_attempts - 1:
|
||||||
|
logger.warning(f"USB device busy (attempt {attempt + 1}/{max_attempts}), waiting for release...")
|
||||||
|
time.sleep(1.0)
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.error(f"Audio pipeline exited immediately. rtl_fm stderr: {rtl_stderr}, ffmpeg stderr: {ffmpeg_stderr}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Pipeline started successfully
|
||||||
|
break
|
||||||
|
|
||||||
# Validate that audio is producing data quickly
|
# Validate that audio is producing data quickly
|
||||||
try:
|
try:
|
||||||
@@ -807,18 +820,19 @@ def _stop_audio_stream_internal():
|
|||||||
audio_process = None
|
audio_process = None
|
||||||
audio_rtl_process = None
|
audio_rtl_process = None
|
||||||
|
|
||||||
# Kill any orphaned rtl_fm and ffmpeg processes
|
# Kill any orphaned rtl_fm, rtl_power, and ffmpeg processes
|
||||||
try:
|
for proc_pattern in ['rtl_fm', 'rtl_power']:
|
||||||
subprocess.run(['pkill', '-9', 'rtl_fm'], capture_output=True, timeout=0.5)
|
try:
|
||||||
except:
|
subprocess.run(['pkill', '-9', proc_pattern], capture_output=True, timeout=0.5)
|
||||||
pass
|
except Exception:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
subprocess.run(['pkill', '-9', '-f', 'ffmpeg.*pipe:0'], capture_output=True, timeout=0.5)
|
subprocess.run(['pkill', '-9', '-f', 'ffmpeg.*pipe:0'], capture_output=True, timeout=0.5)
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Pause for SDR device to be released (important for frequency/modulation changes)
|
# Pause for SDR device USB interface to be released by kernel
|
||||||
time.sleep(0.7)
|
time.sleep(1.0)
|
||||||
|
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|||||||
Reference in New Issue
Block a user