HIDManager Wierd CFRunLoop Termination - PullRequest
       12

HIDManager Wierd CFRunLoop Termination

1 голос
/ 07 февраля 2012

Я создал соответствующие обратные вызовы устройств и удаление устройств, и мне нужно запустить CFRunLoop, чтобы эти обратные вызовы вызывались всякий раз, когда устройство подключалось и удалялось.

Но проблема в том, что обратный вызов DeviceMatching занимает много времени обработки и зависит от подключаемого устройства, поэтому я хочу определить, удалено ли устройство, запустив CFRunLoop в течение ограниченного времени, и с этим происходит обратный вызов удаления устройства. .

Но, он работает 2 раза, а затем выдает exe_bad_access.


  IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
  if( matchingCFDictRef ) {
        CFRelease( matchingCFDictRef );
  }
  IOHIDManagerRegisterDeviceMatchingCallback(tIOHIDManagerRef,
                                                 Handle_DeviceMatchingCallback,NULL);
  IOHIDManagerRegisterDeviceRemovalCallback(tIOHIDManagerRef, Handle_RemovalCallback, NULL);

  IOHIDManagerScheduleWithRunLoop(tIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
      CFRunLoopRun();

Устройство Добавить обратный вызов

static void Handle_DeviceMatchingCallback(void* inContext, IOReturn inResult, 
                             void* inSender, IOHIDDeviceRef  inIOHIDDeviceRef) {
      //DO SOME HEAVY PROCESSING

      //NOW WE NEED TO CHECK IF DEVICE IS STILL CONNECTED
     [[NSRunLoop currentRunLoop]  runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];

      //DO POST PROCESSING

}

Обратный вызов для удаления устройства:

static void Handle_RemovalCallback( void* inContext,IOReturn  inResult,
                        void*  inSender, IOHIDDeviceRef inIOHIDDeviceRef) {
     //NOW THIS GET's INVOKED, after keeping in run loop

}

Ниже приведен код для генерации соответствия CFDictRef

CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    CFNumberRef vendorIDCFNumRef  = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &vendorId );
    CFNumberRef productIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &productId );

    CFDictionarySetValue( matchDict, CFSTR( kIOHIDVendorIDKey  ), vendorIDCFNumRef );
    CFDictionarySetValue( matchDict, CFSTR( kIOHIDProductIDKey ), productIDCFNumRef );

    CFRelease( vendorIDCFNumRef );
    CFRelease( productIDCFNumRef );

Ответы [ 2 ]

1 голос
/ 07 февраля 2012

Как вы генерируете matchingCFDictRef?Хотя обычные соглашения предполагают, что IOHIDManager должен сохранить или скопировать его, вполне возможно, что это не так.Я попытался бы сейчас извлечь CFRelease и посмотреть, улучшит ли это что-то.

Сбой в CFGetTypeID указывает, что он пытается работать с освобожденным объектом CF.Несколько вещей, которые вы можете сделать, чтобы попытаться отладить, какая из них:

  • Включите NSZombie .Это может работать, даже если это объект CF (многие объекты CF являются бесплатными мостовыми соединениями и будут работать).
  • В отладчике установите для параметра значение CFGetType.Смотрите Проверка параметров Obj-C в gdb для правильного регистра в зависимости от вашего процессора.(Неважно, что эта страница для ObjC; вы просто хотите, чтобы все, что связано с arg0.)
0 голосов
/ 07 февраля 2012

Ниже приведен код для генерации matchCFDictRef

CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    CFNumberRef vendorIDCFNumRef  = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &vendorId );
    CFNumberRef productIDCFNumRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &productId );

    CFDictionarySetValue( matchDict, CFSTR( kIOHIDVendorIDKey  ), vendorIDCFNumRef );
    CFDictionarySetValue( matchDict, CFSTR( kIOHIDProductIDKey ), productIDCFNumRef );

    CFRelease( vendorIDCFNumRef );
    CFRelease( productIDCFNumRef );

Теперь я вижу другую трассировку стека, вызванную из CFRunLoop , хотя я все еще вижу GetTypeID в символах

0x00007fff8534407a  <+0023>  jne    0x7fff8534409f <IOHIDDeviceScheduleWithRunLoop+60>
0x00007fff8534407c  <+0025>  mov    0x18(%rdi),%rdi
0x00007fff85344080  <+0029>  mov    (%rdi),%rax
0x00007fff85344083  <+0032>  lea    0x58(%r12),%rsi
0x00007fff85344088  <+0037>  callq  *0x40(%rax)
0x00007fff8534408b  <+0040>  test   %eax,%eax
0x00007fff8534408d  <+0042>  jne    0x7fff85344148 <IOHIDDeviceScheduleWithRunLoop+229>
0x00007fff85344093  <+0048>  cmpq   $0x0,0x58(%r12)
0x00007fff85344099  <+0054>  je     0x7fff85344148 <IOHIDDeviceScheduleWithRunLoop+229>
0x00007fff8534409f  <+0060>  mov    0x58(%r12),%rdi
0x00007fff853440a4  <+0065>  callq  0x7fff85368f36 <dyld_stub_CFGetTypeID>
0x00007fff853440a9  <+0070>  mov    %rax,%rbx
0x00007fff853440ac  <+0073>  callq  0x7fff85369008 <dyld_stub_CFRunLoopSourceGetTypeID>
0x00007fff853440b1  <+0078>  cmp    %rax,%rbx
0x00007fff853440b4  <+0081>  jne    0x7fff853440cc <IOHIDDeviceScheduleWithRunLoop+105>

Я вижу, что он ломается при 0x00007fff85344080 <+0029> mov (% rdi),% rax , для IOHIDDeviceScheduleWithRunLoop (Пожалуйста, выполните поиск по 0x00007fff85344080)

С помощью справочного документа, я вижу, что это первый аргумент, который означает tIOHIDManagerRef, который я создаю IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate (kCFAllocatorDefault, kIOHIDOptionsTypeNone);

Но как это увидеть, как увидетьвыше трассировки стека?

...