Browse Source

Better handling of plugin-bridge timeouts

tags/1.9.6
falkTX 10 years ago
parent
commit
245af25738
7 changed files with 87 additions and 49 deletions
  1. +27
    -5
      source/backend/engine/CarlaEngineBridge.cpp
  2. +49
    -31
      source/backend/plugin/CarlaPluginBridge.cpp
  3. +1
    -1
      source/jackbridge/JackBridge.hpp
  4. +6
    -8
      source/jackbridge/JackBridge2.cpp
  5. +2
    -2
      source/jackbridge/JackBridgeExport.cpp
  6. +1
    -1
      source/jackbridge/JackBridgeExport.hpp
  7. +1
    -1
      source/utils/CarlaBridgeUtils.hpp

+ 27
- 5
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -168,11 +168,11 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
return jackbridge_sem_post(&data->sem.client);
}

bool waitForServer(const uint secs) noexcept
bool waitForServer(const uint secs, bool* const timedOut) noexcept
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);

return jackbridge_sem_timedwait(&data->sem.server, secs);
return jackbridge_sem_timedwait(&data->sem.server, secs, timedOut);
}

PluginBridgeRtClientOpcode readOpcode() noexcept
@@ -270,8 +270,8 @@ struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer>

BridgeNonRtServerControl() noexcept
: mutex(),
filename(),
data(nullptr)
filename(),
data(nullptr)
{
carla_zeroChar(shm, 64);
jackbridge_shm_init(shm);
@@ -1178,10 +1178,19 @@ public:
protected:
void run() override
{
bool timedOut, quitReceived = false;

for (; ! shouldThreadExit();)
{
if (! fShmRtClientControl.waitForServer(5))
if (! fShmRtClientControl.waitForServer(5, &timedOut))
{
/*
* As a special case we ignore timeouts for plugin bridges.
* Some big Windows plugins (Kontakt, FL Studio VST) can time out when initializing or doing UI stuff.
* If any other error happens the plugin bridge is stopped.
*/
if (timedOut) continue;

carla_stderr2("Bridge timed-out, final post...");
fShmRtClientControl.postClient();
carla_stderr2("Bridge timed-out, done.");
@@ -1400,6 +1409,7 @@ protected:
}

case kPluginBridgeRtClientQuit:
quitReceived = true;
signalThreadShouldExit();
break;
}
@@ -1410,6 +1420,18 @@ protected:
}

callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);

if (! quitReceived)
{
const char* const message("Plugin bridge error, process thread has stopped");
const std::size_t messageSize(std::strlen(message));

const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
fShmNonRtServerControl.writeUInt(messageSize);
fShmNonRtServerControl.writeCustomData(message, messageSize);
fShmNonRtServerControl.commitWrite();
}
}

// called from process thread above


+ 49
- 31
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -242,13 +242,13 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
setRingBuffer(nullptr, false);
}

bool waitForClient(const uint secs) noexcept
bool waitForClient(const uint secs, bool* const timedOut) noexcept
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);

jackbridge_sem_post(&data->sem.server);

return jackbridge_sem_timedwait(&data->sem.client, secs);
return jackbridge_sem_timedwait(&data->sem.client, secs, timedOut);
}

void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
@@ -741,6 +741,7 @@ public:
fInitError(false),
fSaved(false),
fTimedOut(false),
fTimedError(false),
fLastPongCounter(-1),
fBridgeBinary(),
fBridgeThread(engine, this),
@@ -786,7 +787,7 @@ public:
fShmRtClientControl.commitWrite();

if (! fTimedOut)
fShmRtClientControl.waitForClient(3);
waitForClient("stopping", 3);
}

fBridgeThread.stopThread(3000);
@@ -1317,6 +1318,8 @@ public:

void activate() noexcept override
{
CARLA_SAFE_ASSERT_RETURN(! fTimedError,);

{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

@@ -1324,18 +1327,17 @@ public:
fShmNonRtClientControl.commitWrite();
}

bool timedOut = true;
fTimedOut = false;

try {
timedOut = waitForClient(1);
waitForClient("activate", 2);
} CARLA_SAFE_EXCEPTION("activate - waitForClient");

if (! timedOut)
fTimedOut = false;
}

void deactivate() noexcept override
{
CARLA_SAFE_ASSERT_RETURN(! fTimedError,);

{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

@@ -1343,14 +1345,11 @@ public:
fShmNonRtClientControl.commitWrite();
}

bool timedOut = true;
fTimedOut = false;

try {
timedOut = waitForClient(1);
waitForClient("deactivate", 2);
} CARLA_SAFE_EXCEPTION("deactivate - waitForClient");

if (! timedOut)
fTimedOut = false;
}

void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
@@ -1358,7 +1357,7 @@ public:
// --------------------------------------------------------------------------------------------------------
// Check if active

if (fTimedOut || ! pData->active)
if (fTimedOut || fTimedError || ! pData->active)
{
// disable any output sound
for (uint32_t i=0; i < pData->audioOut.count; ++i)
@@ -1599,6 +1598,7 @@ public:

bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames)
{
CARLA_SAFE_ASSERT_RETURN(! fTimedError, false);
CARLA_SAFE_ASSERT_RETURN(frames > 0, false);

if (pData->audioIn.count > 0)
@@ -1673,10 +1673,12 @@ public:
fShmRtClientControl.commitWrite();
}

if (! waitForClient(2))
waitForClient("process", 1);

if (fTimedOut)
{
pData->singleMutex.unlock();
return true;
return false;
}

for (uint32_t i=0; i < fInfo.aOuts; ++i)
@@ -1763,7 +1765,7 @@ public:
fShmNonRtClientControl.commitWrite();
}

fShmRtClientControl.waitForClient(1);
waitForClient("buffersize", 1);
}

void sampleRateChanged(const double newSampleRate) override
@@ -1775,7 +1777,7 @@ public:
fShmNonRtClientControl.commitWrite();
}

fShmRtClientControl.waitForClient(1);
waitForClient("samplerate", 1);
}

void offlineModeChanged(const bool isOffline) override
@@ -1786,7 +1788,7 @@ public:
fShmNonRtClientControl.commitWrite();
}

fShmRtClientControl.waitForClient(1);
waitForClient("offline", 1);
}

// -------------------------------------------------------------------
@@ -2273,10 +2275,20 @@ public:
carla_zeroChar(error, errorSize+1);
fShmNonRtServerControl.readCustomData(error, errorSize);

pData->engine->setLastError(error);
if (fInitiated)
{
pData->engine->callback(ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0.0f, error);

fInitError = true;
fInitiated = true;
// just in case
pData->engine->setLastError(error);
fInitError = true;
}
else
{
pData->engine->setLastError(error);
fInitError = true;
fInitiated = true;
}
} break;
}
}
@@ -2453,6 +2465,7 @@ private:
bool fInitError;
bool fSaved;
bool fTimedOut;
bool fTimedError;

int32_t fLastPongCounter;

@@ -2505,21 +2518,26 @@ private:

fShmRtClientControl.commitWrite();

waitForClient();
waitForClient("resize-pool");
}

bool waitForClient(const uint secs = 5)
void waitForClient(const char* const action, const uint secs = 5)
{
CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false);
CARLA_SAFE_ASSERT_RETURN(! fTimedOut,);
CARLA_SAFE_ASSERT_RETURN(! fTimedError,);

if (! fShmRtClientControl.waitForClient(secs))
if (fShmRtClientControl.waitForClient(secs, &fTimedOut))
return;

if (fTimedOut)
{
carla_stderr("waitForClient() timeout here");
fTimedOut = true;
return false;
carla_stderr("waitForClient(%s) timeout here", action);
}
else
{
fTimedError = true;
carla_stderr("waitForClient(%s) error while waiting", action);
}

return true;
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)


+ 1
- 1
source/jackbridge/JackBridge.hpp View File

@@ -393,7 +393,7 @@ __cdecl bool jackbridge_set_property_change_callback(jack_client_t* client, Jack
__cdecl bool jackbridge_sem_init(void* sem) noexcept;
__cdecl void jackbridge_sem_destroy(void* sem) noexcept;
__cdecl bool jackbridge_sem_post(void* sem) noexcept;
__cdecl bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept;
__cdecl bool jackbridge_sem_timedwait(void* sem, uint secs, bool* timedOut) noexcept;

__cdecl bool jackbridge_shm_is_valid(const void* shm) noexcept;
__cdecl void jackbridge_shm_init(void* shm) noexcept;


+ 6
- 8
source/jackbridge/JackBridge2.cpp View File

@@ -55,20 +55,18 @@ bool jackbridge_sem_post(void* sem) noexcept
#endif
}

bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept
bool jackbridge_sem_timedwait(void* sem, uint secs, bool* timedOut) noexcept
{
CARLA_SAFE_ASSERT_RETURN(timedOut != nullptr, false);
#ifdef JACKBRIDGE_DUMMY
return false;
#else
if (carla_sem_timedwait((sem_t*)sem, secs))
{
*timedOut = false;
return true;
/*
* As a sspecial case we ignore timeouts for plugin bridges.
* Some big Windows plugins (Kontakt, FL Studio VST) can time out when initializing.
* If any other error happens the plugin bridge is stopped.
*/
if (errno == ETIMEDOUT)
return true;
}
*timedOut = (errno == ETIMEDOUT);
return false;
#endif
}


+ 2
- 2
source/jackbridge/JackBridgeExport.cpp View File

@@ -540,9 +540,9 @@ bool jackbridge_sem_post(void* sem) noexcept
return getBridgeInstance().sem_post_ptr(sem);
}

bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept
bool jackbridge_sem_timedwait(void* sem, uint secs, bool* timedOut) noexcept
{
return getBridgeInstance().sem_timedwait_ptr(sem, secs);
return getBridgeInstance().sem_timedwait_ptr(sem, secs, timedOut);
}

bool jackbridge_shm_is_valid(const void* shm) noexcept


+ 1
- 1
source/jackbridge/JackBridgeExport.hpp View File

@@ -109,7 +109,7 @@ typedef bool (__cdecl *jackbridgesym_set_property_change_callback)(jack_client_t
typedef bool (__cdecl *jackbridgesym_sem_init)(void* sem);
typedef void (__cdecl *jackbridgesym_sem_destroy)(void* sem);
typedef bool (__cdecl *jackbridgesym_sem_post)(void* sem);
typedef bool (__cdecl *jackbridgesym_sem_timedwait)(void* sem, uint secs);
typedef bool (__cdecl *jackbridgesym_sem_timedwait)(void* sem, uint secs, bool* timedOut);
typedef bool (__cdecl *jackbridgesym_shm_is_valid)(const void* shm);
typedef void (__cdecl *jackbridgesym_shm_init)(void* shm);
typedef void (__cdecl *jackbridgesym_shm_attach)(void* shm, const char* name);


+ 1
- 1
source/utils/CarlaBridgeUtils.hpp View File

@@ -105,7 +105,7 @@ enum PluginBridgeNonRtServerOpcode {
kPluginBridgeNonRtServerReady,
kPluginBridgeNonRtServerSaved,
kPluginBridgeNonRtServerUiClosed,
kPluginBridgeNonRtServerError
kPluginBridgeNonRtServerError // uint/size, str[]
};

// -----------------------------------------------------------------------


Loading…
Cancel
Save