fix: QThread crash on iPod connect and device detection — proper wait() lifecycle
Root cause: QThread C++ destructor ran while underlying OS thread was still terminating. The pattern of checking isRunning() and using short timeouts (wait(3000/5000)) left a window where the Python reference was dropped and Shiboken destroyed the C++ object before the thread fully exited. Fixes: - Remove all self.finished.connect(self.deleteLater) — unsafe, deleteLater from within run() or from worker thread races with thread termination - _cleanup_worker: always call wait() (no timeout) before nulling the Python reference — guarantees OS thread is fully dead - Add _is_worker_running() helper with try/except RuntimeError guard to safely check stale C++ objects - DeviceMonitor._poll/stop/wait: use wait() with no timeout - closeEvent: guard isRunning() with try/except RuntimeError
This commit is contained in:
+13
-5
@@ -957,7 +957,7 @@ class LibraryTab(QWidget):
|
||||
)
|
||||
return
|
||||
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
if self._is_worker_running():
|
||||
QMessageBox.information(self, "Info", "Please wait for the current task to finish")
|
||||
return
|
||||
|
||||
@@ -1025,7 +1025,7 @@ class LibraryTab(QWidget):
|
||||
QMessageBox.warning(self, "Error", "No iPod device mounted. Go to iPod tab and mount first.")
|
||||
return
|
||||
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
if self._is_worker_running():
|
||||
QMessageBox.information(self, "Info", "Please wait for the current task to finish")
|
||||
return
|
||||
|
||||
@@ -1070,7 +1070,7 @@ class LibraryTab(QWidget):
|
||||
QMessageBox.warning(self, "Error", "No iPod device mounted.")
|
||||
return
|
||||
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
if self._is_worker_running():
|
||||
QMessageBox.information(self, "Info", "Please wait for the current task to finish")
|
||||
return
|
||||
|
||||
@@ -1140,10 +1140,18 @@ class LibraryTab(QWidget):
|
||||
|
||||
def _cleanup_worker(self):
|
||||
if self.worker_thread:
|
||||
self.worker_thread.wait(3000)
|
||||
self.worker_thread.deleteLater()
|
||||
self.worker_thread.quit()
|
||||
self.worker_thread.wait()
|
||||
self.worker_thread = None
|
||||
|
||||
def _is_worker_running(self):
|
||||
if self.worker_thread:
|
||||
try:
|
||||
return self.worker_thread.isRunning()
|
||||
except RuntimeError:
|
||||
self.worker_thread = None
|
||||
return False
|
||||
|
||||
def on_device_mounted(self, mount_point: str):
|
||||
self._current_mount_point = mount_point
|
||||
self.library_progress.setVisible(True)
|
||||
|
||||
Reference in New Issue
Block a user