#14230 Fix deadlock when importing wells from OSDU

The GUI thread deadlocked on a non-recursive QMutex during OSDU well
import. The download-completion slots and DataLoadController::onTaskFinished
held a mutex while triggering progress updates, which call
QApplication::processEvents(). That re-enters the event loop and dispatches
another queued parquet-download-complete event for a different well, whose
handler then blocks trying to lock the same mutex.

Release the mutex before emitting taskDone in the OSDU well path and well
log data loaders, and before calling incrementProgress() in onTaskFinished.
The map access that the mutex protects stays inside the locked scope; the
captured ProgressInfo outlives the call (kept alive by blockUntilDone) and
incrementProgress() is thread-safe via self-marshaling to the GUI thread.

Fixes #14230.
This commit is contained in:
Kristian Bendiksen authored and Magne Sjaastad committed 2026-06-18 07:55:04 +02:00
1 parent 576fb32a6e
commit 8209bd3ecf
3 files changed
+34 -15

No files matched your search

@@ -87,11 +87,13 @@ bool RimOsduWellLogDataLoader::isRunnable() const
//--------------------------------------------------------------------------------------------------
void RimOsduWellLogDataLoader::parquetDownloadComplete( const QByteArray& contents, const QString& url, const QString& id )
{
QMutexLocker lock( &m_mutex );
if ( m_wellLogs.find( id ) != m_wellLogs.end() )
int taskId = -1;
{
int taskId = m_taskIds[id];
QMutexLocker lock( &m_mutex );
if ( m_wellLogs.find( id ) == m_wellLogs.end() ) return;
taskId = m_taskIds[id];
RiaLogging::info( std::format( "Parquet download complete. Id: {} Size: {}", id, contents.size() ) );
@@ -109,7 +111,10 @@ void RimOsduWellLogDataLoader::parquetDownloadComplete( const QByteArray& conten
RiaLogging::warning( errorMessage.toStdString() );
}
}
taskDone.send( m_dataType, taskId );
}
// The lock is released above before emitting taskDone. The signal is delivered synchronously and triggers
// progress updates that call QApplication::processEvents(), which can re-enter this slot for another
// well. Holding the non-recursive m_mutex across send() would then deadlock the GUI thread (#14230).
taskDone.send( m_dataType, taskId );
}