fix(engine): stop recognition before switching engines to prevent segfault (fixes #350) (#355)

When switching from whisper.cpp to VOSK via the settings dialog, the
_auto_apply_settings path called reconfigure() without first stopping
active recognition. This allowed background audio/transcription threads
to continue using the old engine's native C resources (whisper.cpp model)
while they were being freed by Python's GC, causing a segmentation fault.

Changes:
- Add stop_recognition() guard in reconfigure() itself when the engine
  or model changes and recognition is active — this makes the API safe
  regardless of which caller triggers the reconfiguration
- Add defense-in-depth stop_recognition() call in _auto_apply_settings
  to match the existing pattern in _apply_settings_internal
This commit is contained in:
Jatin K Malik
2026-03-27 11:14:37 -07:00
committed by GitHub
parent 860a9f9ae6
commit 5b53e850dd
2 changed files with 16 additions and 0 deletions
@@ -2073,6 +2073,15 @@ class SpeechRecognitionManager:
if restart_needed:
logger.info("Engine or model changed, re-initializing...")
# Stop any active recognition before switching engines.
# This is critical to prevent segfaults when the old engine's
# native resources (e.g. whisper.cpp C model) are freed while
# a background thread is still using them.
if self.state != RecognitionState.IDLE:
logger.info("Stopping active recognition before engine switch...")
self.stop_recognition()
# When reconfiguring from UI, allow downloads
old_defer = self._defer_download
self._defer_download = not force_download
+7
View File
@@ -1916,6 +1916,13 @@ class SettingsDialog(Gtk.Dialog):
self.config_manager.update_speech_recognition_settings(settings)
self.config_manager.save_settings()
# Stop recognition before reconfiguring to avoid segfaults when
# switching between engines with native resources (e.g. whisper.cpp)
was_running = self.speech_engine.state != RecognitionState.IDLE
if was_running:
self.speech_engine.stop_recognition()
self.speech_engine.reconfigure(**settings)
logger.info("Settings auto-applied successfully")
except Exception as e: