MaxKellermann@ correctly pointed out the SIGTERM signal handler was not safe, and

may result in deadlock. Updated code to avoid allocations and just set
the quit flag. Required minor surgery to IMessageQueue and impl to add
a timeout to WaitAndDispatch().
This commit is contained in:
Casey Langen 2018-01-30 09:21:04 -08:00
parent b18ed5ab18
commit 0fdb83d643
4 changed files with 20 additions and 13 deletions

View File

@ -50,7 +50,7 @@ namespace musik {
virtual void Debounce(IMessagePtr message, int64_t delayMs = 0) = 0;
virtual void RegisterForBroadcasts(IMessageTargetPtr target) = 0;
virtual void UnregisterForBroadcasts(IMessageTarget *target) = 0;
virtual void WaitAndDispatch() = 0;
virtual void WaitAndDispatch(int64_t timeoutMillis = -1) = 0;
virtual void Dispatch() = 0;
};
}

View File

@ -36,6 +36,7 @@
#include "MessageQueue.h"
#include <algorithm>
#include <chrono>
using namespace std::chrono;
using namespace musik::core::runtime;
@ -46,21 +47,30 @@ MessageQueue::MessageQueue() {
this->nextMessageTime.store(1);
}
void MessageQueue::WaitAndDispatch() {
void MessageQueue::WaitAndDispatch(int64_t timeoutMillis) {
{
LockT lock(this->queueMutex);
if (this->queue.size()) {
auto waitTime =
auto waitTime = duration_cast<milliseconds>(
this->queue.front()->time -
system_clock::now().time_since_epoch();
system_clock::now().time_since_epoch());
if (timeoutMillis >= 0 && waitTime.count() > timeoutMillis) {
waitTime = milliseconds(timeoutMillis);
}
if (waitTime.count() > 0) {
waitForDispatch.wait_for(lock, waitTime);
}
}
else {
waitForDispatch.wait(lock);
if (timeoutMillis >= 0) {
waitForDispatch.wait_for(lock, milliseconds(timeoutMillis));
}
else {
waitForDispatch.wait(lock);
}
}
}

View File

@ -56,7 +56,7 @@ namespace musik { namespace core { namespace runtime {
virtual void Debounce(IMessagePtr message, int64_t delayMs = 0);
virtual void RegisterForBroadcasts(IMessageTargetPtr target);
virtual void UnregisterForBroadcasts(IMessageTarget *target);
virtual void WaitAndDispatch();
virtual void WaitAndDispatch(int64_t timeoutMillis = -1);
virtual void Dispatch();
protected:

View File

@ -24,22 +24,18 @@ using namespace musik::core;
using namespace musik::core::audio;
using namespace musik::core::runtime;
#define MESSAGE_QUEUE_TIMEOUT_MS 500
#ifdef __linux__
#define LOCKFILE "/var/lock/musikcubed.lock"
#else
#define LOCKFILE "/tmp/musikcubed.lock"
#endif
static MessageQueue messageQueue;
static volatile bool quit = false;
static void sigtermHandler(int signal) {
quit = true;
/* pump a dummy message in the queue so it wakes up
immediately and goes back to the top of the loop, where
the quit flag will be processed */
messageQueue.Broadcast(Message::Create(nullptr, 0));
}
static bool exitIfRunning() {
@ -103,6 +99,7 @@ int main() {
debug::init();
MessageQueue messageQueue;
MasterTransport transport;
auto library = LibraryFactory::Libraries().at(0);
auto prefs = Preferences::ForComponent(prefs::components::Settings);
@ -117,7 +114,7 @@ int main() {
}
while (!quit) {
messageQueue.WaitAndDispatch();
messageQueue.WaitAndDispatch(MESSAGE_QUEUE_TIMEOUT_MS);
}
remove(LOCKFILE);