From 6670f627a0237961e4cca42a29db2c9b8dd8b2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Str=C3=B6m?= Date: Mon, 9 Apr 2012 21:28:39 +0200 Subject: [PATCH] Race-fix for OSX ControllerListener. If the destructor was called very close (in time) after the constructor was called, we'd get a race where gRunLoop was not inited properly, and when trying to release it we crashed with EXC_BAD_ACCESS. An example when this would happen is if the user SIGINTs while starting up. The ControllerManager can be quite slow (seconds) to init sometimes, and if we'd SIGINT while waiting for it, the ControllerListener ctor would be called after, the mainloop would be skipped, and then the dtor would be called -> triggering crash. --- telldus-core/service/ControllerListener_mac.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index c042b0db..bf2af63a 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -21,6 +21,7 @@ public: CFRunLoopRef gRunLoop; io_iterator_t gAddedIter; TelldusCore::EventRef event; + bool running; void addUsbFilter(int vid, int pid); static void DeviceAdded(void *refCon, io_iterator_t iterator); @@ -32,11 +33,16 @@ ControllerListener::ControllerListener(TelldusCore::EventRef event) { d = new PrivateData; d->event = event; + d->running = true; + d->gRunLoop = NULL; this->start(); } ControllerListener::~ControllerListener() { - CFRunLoopStop(d->gRunLoop); + d->running = false; + if(d->gRunLoop != NULL) + CFRunLoopStop(d->gRunLoop); + this->wait(); delete d; } @@ -53,7 +59,10 @@ void ControllerListener::run() { d->addUsbFilter(0x1781, 0x0c30); d->addUsbFilter(0x1781, 0x0c31); - CFRunLoopRun(); + // Race check, if destructor was called really close to thread init, + // running might have gone false. Make sure we don't get stuck + if(d->running) + CFRunLoopRun(); } void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) {