From 4065a6691f35913dd7deb5e87b0f67bb12c20672 Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Thu, 30 Jul 2026 17:58:29 +0100 Subject: [PATCH 1/3] Fixes for a crash suggested by AI in #3845 --- src/client.cpp | 3 +-- src/clientdlg.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index fb9bab5478..b62a541f41 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -853,7 +853,7 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) // audio device notifications can come at any time and they are in a // different thread, therefore we need a mutex here - MutexDriverReinit.lock(); + QMutexLocker locker ( &MutexDriverReinit ); { // in older QT versions, enums cannot easily be used in signals without // registering them -> workaroud: we use the int type and cast to the enum @@ -888,7 +888,6 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) Sound.Start(); } } - MutexDriverReinit.unlock(); // inform GUI about the sound card device change emit SoundDeviceChanged ( strError ); diff --git a/src/clientdlg.cpp b/src/clientdlg.cpp index b102c34724..9c3455e477 100644 --- a/src/clientdlg.cpp +++ b/src/clientdlg.cpp @@ -866,7 +866,7 @@ void CClientDlg::OnCLVersionAndOSReceived ( CHostAddress InetAddr, COSUtil::EOpS { // show the label and hide it after one minute again lblUpdateCheck->show(); - QTimer::singleShot ( 60000, [this]() { lblUpdateCheck->hide(); } ); + QTimer::singleShot ( 60000, this, [this]() { lblUpdateCheck->hide(); } ); } #endif } From 3abd4f637a65b23df1f0a0b424f706d432d2ae78 Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Fri, 31 Jul 2026 22:54:24 +0100 Subject: [PATCH 2/3] Catch exception when initialising sound device --- src/client.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index b62a541f41..f3b83a89a7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -738,6 +738,8 @@ void CClient::SetAudioChannels ( const EAudChanConf eNAudChanConf ) QString CClient::SetSndCrdDev ( const QString strNewDev ) { + QString strError = ""; + // if client was running then first // stop it and restart again after new initialization const bool bWasRunning = Sound.IsRunning(); @@ -746,16 +748,23 @@ QString CClient::SetSndCrdDev ( const QString strNewDev ) Sound.Stop(); } - const QString strError = Sound.SetDev ( strNewDev ); + try + { + strError = Sound.SetDev ( strNewDev ); - // init again because the sound card actual buffer size might - // be changed on new device - Init(); + // init again because the sound card actual buffer size might + // be changed on new device + Init(); - if ( bWasRunning ) + if ( bWasRunning ) + { + // restart client + Sound.Start(); + } + } + catch ( const CGenErr& generr ) { - // restart client - Sound.Start(); + strError = generr.GetErrorText(); } // in case of an error inform the GUI about it @@ -854,6 +863,7 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) // audio device notifications can come at any time and they are in a // different thread, therefore we need a mutex here QMutexLocker locker ( &MutexDriverReinit ); + try { // in older QT versions, enums cannot easily be used in signals without // registering them -> workaroud: we use the int type and cast to the enum @@ -888,6 +898,10 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) Sound.Start(); } } + catch ( const CGenErr& generr ) + { + strError = generr.GetErrorText(); + } // inform GUI about the sound card device change emit SoundDeviceChanged ( strError ); From d6855af5748998ab79a40f4926c200960211e54d Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Sat, 1 Aug 2026 14:09:39 +0100 Subject: [PATCH 3/3] Add explanatory comment to each new try block --- src/client.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index f3b83a89a7..f069208da7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -748,6 +748,8 @@ QString CClient::SetSndCrdDev ( const QString strNewDev ) Sound.Stop(); } + // Jamulus sound drivers for different platforms may throw CGenErr exception + // on error condition. Catch it here as exceptions must not escape from a Qt slot. try { strError = Sound.SetDev ( strNewDev ); @@ -863,6 +865,9 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) // audio device notifications can come at any time and they are in a // different thread, therefore we need a mutex here QMutexLocker locker ( &MutexDriverReinit ); + + // Jamulus sound drivers for different platforms may throw CGenErr exception + // on error condition. Catch it here as exceptions must not escape from a Qt slot. try { // in older QT versions, enums cannot easily be used in signals without