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.
This commit is contained in:
Johan Ström 2012-04-09 21:28:39 +02:00
parent f57eebad74
commit 6670f627a0

View file

@ -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) {