Browse Source

Fix race condition around postponed rt event data pool

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.3.1
falkTX 3 years ago
parent
commit
33a9091413
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 31 additions and 16 deletions
  1. +1
    -1
      .github/workflows/macos-latest.yml
  2. +1
    -1
      .github/workflows/ubuntu-latest.yml
  3. +1
    -1
      source/backend/engine/CarlaEngineRtAudio.cpp
  4. +15
    -10
      source/backend/plugin/CarlaPluginInternal.cpp
  5. +8
    -2
      source/backend/plugin/CarlaPluginInternal.hpp
  6. +5
    -1
      source/utils/RtLinkedList.hpp

+ 1
- 1
.github/workflows/macos-latest.yml View File

@@ -1,4 +1,4 @@
name: C/C++ CI
name: macos latest


on: on:
push: push:


+ 1
- 1
.github/workflows/ubuntu-latest.yml View File

@@ -14,7 +14,7 @@ jobs:
- name: Install extra dependencies - name: Install extra dependencies
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install libasound2-dev liblo-dev libfluidsynth-dev libgl1-mesa-dev libgtk2.0-dev libgtk-3-dev libmagic-dev libpulse-dev libx11-dev pkg-config pyqt5-dev-tools qtbase5-dev
sudo apt-get install libasound2-dev liblo-dev libfluidsynth-dev libgl1-mesa-dev libgtk2.0-dev libgtk-3-dev libmagic-dev libpulse-dev libsndfile1-dev libx11-dev pkg-config pyqt5-dev-tools qtbase5-dev
sudo apt-get install mingw-w64 binutils-mingw-w64-x86-64 g++-mingw-w64-x86-64 sudo apt-get install mingw-w64 binutils-mingw-w64-x86-64 g++-mingw-w64-x86-64
- name: make features - name: make features
run: make features run: make features


+ 1
- 1
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -1073,7 +1073,7 @@ private:


RtMidiEvents() RtMidiEvents()
: mutex(), : mutex(),
dataPool(512, 512),
dataPool("RtMidiEvents", 512, 512),
data(dataPool), data(dataPool),
dataPending(dataPool) {} dataPending(dataPool) {}




+ 15
- 10
source/backend/plugin/CarlaPluginInternal.cpp View File

@@ -509,7 +509,7 @@ const MidiProgramData& PluginMidiProgramData::getCurrent() const noexcept


CarlaPlugin::ProtectedData::ExternalNotes::ExternalNotes() noexcept CarlaPlugin::ProtectedData::ExternalNotes::ExternalNotes() noexcept
: mutex(), : mutex(),
dataPool(32, 152),
dataPool("CarlaPlugin::ProtectedData::ExternalNotes", 32, 152),
data(dataPool) {} data(dataPool) {}


CarlaPlugin::ProtectedData::ExternalNotes::~ExternalNotes() noexcept CarlaPlugin::ProtectedData::ExternalNotes::~ExternalNotes() noexcept
@@ -633,28 +633,30 @@ void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChan
// ProtectedData::PostRtEvents // ProtectedData::PostRtEvents


CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept
: dataPool(512, 512),
: dataPool("CarlaPlugin::ProtectedData::PostRtEvents", 512, 512),
data(dataPool), data(dataPool),
dataPendingRT(dataPool), dataPendingRT(dataPool),
dataMutex(), dataMutex(),
dataPendingMutex() {}
dataPendingMutex(),
poolMutex() {}


CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept
{ {
dataMutex.lock();
dataPendingMutex.lock();
const CarlaMutexLocker cml1(dataMutex);
const CarlaMutexLocker cml2(dataPendingMutex);
const CarlaMutexLocker cml3(poolMutex);


data.clear(); data.clear();
dataPendingRT.clear(); dataPendingRT.clear();

dataMutex.unlock();
dataPendingMutex.unlock();
} }


void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept
{ {
CARLA_SAFE_ASSERT_INT_RETURN(dataPendingMutex.tryLock(), e.type,); CARLA_SAFE_ASSERT_INT_RETURN(dataPendingMutex.tryLock(), e.type,);
dataPendingRT.append(e);
{
const CarlaMutexLocker cml(poolMutex);
dataPendingRT.append(e);
}
dataPendingMutex.unlock(); dataPendingMutex.unlock();
} }


@@ -664,7 +666,10 @@ void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept


if (cmtl.wasLocked() && dataPendingRT.isNotEmpty() && dataMutex.tryLock()) if (cmtl.wasLocked() && dataPendingRT.isNotEmpty() && dataMutex.tryLock())
{ {
dataPendingRT.moveTo(data, true);
{
const CarlaMutexLocker cml(poolMutex);
dataPendingRT.moveTo(data, true);
}
dataMutex.unlock(); dataMutex.unlock();
} }
} }


+ 8
- 2
source/backend/plugin/CarlaPluginInternal.hpp View File

@@ -329,9 +329,11 @@ struct CarlaPlugin::ProtectedData {


struct Access { struct Access {
Access(PostRtEvents& e) Access(PostRtEvents& e)
: data2(e.dataPool)
: data2(e.dataPool),
poolMutex(e.poolMutex)
{ {
const CarlaMutexLocker cml(e.dataMutex);
const CarlaMutexLocker cml1(e.dataMutex);
const CarlaMutexLocker cml2(e.poolMutex);


if (e.data.isNotEmpty()) if (e.data.isNotEmpty())
e.data.moveTo(data2, true); e.data.moveTo(data2, true);
@@ -339,6 +341,8 @@ struct CarlaPlugin::ProtectedData {


~Access() ~Access()
{ {
const CarlaMutexLocker cml(poolMutex);

data2.clear(); data2.clear();
} }


@@ -354,6 +358,7 @@ struct CarlaPlugin::ProtectedData {


private: private:
RtLinkedList<PluginPostRtEvent> data2; RtLinkedList<PluginPostRtEvent> data2;
CarlaMutex& poolMutex;
}; };


private: private:
@@ -361,6 +366,7 @@ struct CarlaPlugin::ProtectedData {
RtLinkedList<PluginPostRtEvent> data, dataPendingRT; RtLinkedList<PluginPostRtEvent> data, dataPendingRT;
CarlaMutex dataMutex; CarlaMutex dataMutex;
CarlaMutex dataPendingMutex; CarlaMutex dataPendingMutex;
CarlaMutex poolMutex;


CARLA_DECLARE_NON_COPY_CLASS(PostRtEvents) CARLA_DECLARE_NON_COPY_CLASS(PostRtEvents)




+ 5
- 1
source/utils/RtLinkedList.hpp View File

@@ -38,8 +38,9 @@ public:
class Pool class Pool
{ {
public: public:
Pool(const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept
Pool(const char* const poolName, const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept
: kDataSize(sizeof(typename AbstractLinkedList<T>::Data)), : kDataSize(sizeof(typename AbstractLinkedList<T>::Data)),
kPoolName(carla_strdup_safe(poolName)),
fHandle(nullptr) fHandle(nullptr)
{ {
rtsafe_memory_pool_create(&fHandle, nullptr, kDataSize, minPreallocated, maxPreallocated); rtsafe_memory_pool_create(&fHandle, nullptr, kDataSize, minPreallocated, maxPreallocated);
@@ -50,9 +51,11 @@ public:
{ {
if (fHandle != nullptr) if (fHandle != nullptr)
{ {
carla_debug("Destroying %s", kPoolName);
rtsafe_memory_pool_destroy(fHandle); rtsafe_memory_pool_destroy(fHandle);
fHandle = nullptr; fHandle = nullptr;
} }
delete[] kPoolName;
} }


void* allocate_atomic() const noexcept void* allocate_atomic() const noexcept
@@ -84,6 +87,7 @@ public:


private: private:
const std::size_t kDataSize; const std::size_t kDataSize;
const char* const kPoolName;


mutable RtMemPool_Handle fHandle; mutable RtMemPool_Handle fHandle;




Loading…
Cancel
Save