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:
parent
f57eebad74
commit
6670f627a0
1 changed files with 11 additions and 2 deletions
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue