Browse Source

Fix possible race condition on jack disconnect callback

Closes #269
tags/1.9.7
falkTX 10 years ago
parent
commit
2556c4c921
2 changed files with 48 additions and 30 deletions
  1. +44
    -29
      source/backend/engine/CarlaEngineJack.cpp
  2. +4
    -1
      source/utils/CarlaPatchbayUtils.hpp

+ 44
- 29
source/backend/engine/CarlaEngineJack.cpp View File

@@ -1135,33 +1135,40 @@ public:
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fExternalPatchbay) if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fExternalPatchbay)
return CarlaEngine::patchbayDisconnect(connectionId); return CarlaEngine::patchbayDisconnect(connectionId);


for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next())
{
static const ConnectionToId fallback = { 0, 0, 0, 0, 0 };
ConnectionToId connectionToId = { 0, 0, 0, 0, 0 };


const ConnectionToId& connectionToId(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0);
{
const CarlaMutexLocker cml(fUsedConnections.mutex);


if (connectionToId.id == connectionId)
for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next())
{ {
const char* const fullPortNameA = fUsedPorts.getFullPortName(connectionToId.groupA, connectionToId.portA);
CARLA_SAFE_ASSERT_RETURN(fullPortNameA != nullptr && fullPortNameA[0] != '\0', false);
connectionToId = it.getValue(connectionToId);
CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0);


const char* const fullPortNameB = fUsedPorts.getFullPortName(connectionToId.groupB, connectionToId.portB);
CARLA_SAFE_ASSERT_RETURN(fullPortNameB != nullptr && fullPortNameB[0] != '\0', false);
if (connectionToId.id == connectionId)
break;
}
}


if (! jackbridge_disconnect(fClient, fullPortNameA, fullPortNameB))
{
setLastError("JACK operation failed");
return false;
}
if (connectionToId.id == 0 || connectionToId.id != connectionId)
{
setLastError("Failed to find the requested connection");
return false;
}


return true;
}
const char* const fullPortNameA = fUsedPorts.getFullPortName(connectionToId.groupA, connectionToId.portA);
CARLA_SAFE_ASSERT_RETURN(fullPortNameA != nullptr && fullPortNameA[0] != '\0', false);

const char* const fullPortNameB = fUsedPorts.getFullPortName(connectionToId.groupB, connectionToId.portB);
CARLA_SAFE_ASSERT_RETURN(fullPortNameB != nullptr && fullPortNameB[0] != '\0', false);

if (! jackbridge_disconnect(fClient, fullPortNameA, fullPortNameB))
{
setLastError("JACK operation failed");
return false;
} }


setLastError("Failed to find the requested connection");
return false;
return true;
} }


bool patchbayRefresh(const bool external) override bool patchbayRefresh(const bool external) override
@@ -1632,21 +1639,29 @@ protected:
} }
else else
{ {
for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next())
{
static const ConnectionToId fallback = { 0, 0, 0, 0, 0 };
ConnectionToId connectionToId = { 0, 0, 0, 0, 0 };
bool found = false;


const ConnectionToId& connectionToId(it.getValue(fallback));
CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0);
{
const CarlaMutexLocker cml(fUsedConnections.mutex);


if (connectionToId.groupA == portNameToIdA.group && connectionToId.portA == portNameToIdA.port &&
connectionToId.groupB == portNameToIdB.group && connectionToId.portB == portNameToIdB.port)
for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.list.begin2(); it.valid(); it.next())
{ {
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr);
fUsedConnections.list.remove(it);
break;
connectionToId = it.getValue(connectionToId);
CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0);

if (connectionToId.groupA == portNameToIdA.group && connectionToId.portA == portNameToIdA.port &&
connectionToId.groupB == portNameToIdB.group && connectionToId.portB == portNameToIdB.port)
{
found = true;
fUsedConnections.list.remove(it);
break;
}
} }
} }

if (found)
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr);
} }
} }




+ 4
- 1
source/utils/CarlaPatchbayUtils.hpp View File

@@ -18,6 +18,7 @@
#ifndef CARLA_PATCHBAY_UTILS_HPP_INCLUDED #ifndef CARLA_PATCHBAY_UTILS_HPP_INCLUDED
#define CARLA_PATCHBAY_UTILS_HPP_INCLUDED #define CARLA_PATCHBAY_UTILS_HPP_INCLUDED


#include "CarlaMutex.hpp"
#include "LinkedList.hpp" #include "LinkedList.hpp"


#define STR_MAX 0xFF #define STR_MAX 0xFF
@@ -201,10 +202,12 @@ struct ConnectionToId {
struct PatchbayConnectionList { struct PatchbayConnectionList {
uint lastId; uint lastId;
LinkedList<ConnectionToId> list; LinkedList<ConnectionToId> list;
CarlaMutex mutex;


PatchbayConnectionList() noexcept PatchbayConnectionList() noexcept
: lastId(0), : lastId(0),
list() {}
list(),
mutex() {}


void clear() noexcept void clear() noexcept
{ {


Loading…
Cancel
Save