HIDManager 奇怪的 CFRunLoop 终止
我已经创建了设备匹配和设备删除回调,并且需要运行 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 );
I've created device matching and device removal callbacks, And need to run CFRunLoop to get those callbacks invoked whenever device plugged in and removed.
But the problem is, DeviceMatching callback takes a lot of processing time and depends on device to be attached, So I want to detect if device is removed by running the CFRunLoop for a limited time, and With that the device removal callback happens.
But, It works for 2 times and then it throws 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();
Device Add Callback
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
}
Device Removal Callback:
static void Handle_RemovalCallback( void* inContext,IOReturn inResult,
void* inSender, IOHIDDeviceRef inIOHIDDeviceRef) {
//NOW THIS GET's INVOKED, after keeping in run loop
}
Following is the code for generating matchingCFDictRef
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 );
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如何生成
matchingCFDictRef
?尽管正常约定建议 IOHIDManager 应保留或复制它,但也可能并非如此。我现在会尝试取出CFRelease
看看是否会有所改善。CFGetTypeID
中的崩溃表明它正在尝试使用已释放的 CF 对象。您可以采取一些措施来尝试调试它是哪一个:CFGetType
的参数。请参阅检查 Obj-C 参数gdb 获取正确的寄存器,具体取决于您的处理器。 (此页面用于 ObjC 并不重要;您只需要与arg0
相关的整体。)How do you generate
matchingCFDictRef
? Though normal conventions would suggest that IOHIDManager should retain or copy it, it's possible that it isn't. I would try taking out theCFRelease
for now and see if that improves things.The crash in
CFGetTypeID
indicates that it is trying to work with a CF object that has been freed. A few things you can do to try to debug which one it is:CFGetType
. See Inspecting Obj-C parameters in gdb for the correct register depending on your processor. (It doesn't matter that this page is for ObjC; you just want the entires related toarg0
.)以下是生成匹配CFDictRef的代码
现在,我看到不同的堆栈跟踪,从CFRunLoop调用,尽管我仍然在符号中看到GetTypeID,但
我发现它在0x00007fff85344080 <处中断;+0029> mov (%rdi),%rax, for IOHIDDeviceScheduleWithRunLoop ( 请使用 0x00007fff85344080 搜索)
在参考文档的帮助下,我看到它是第一个参数,表示 tIOHIDManagerRef,我创建了 IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate (kCFAllocatorDefault,kIOHIDOptionsTypeNone );
但是,如何从上面的堆栈跟踪中查看它的地址?
Following is the code for generating matchingCFDictRef
Now, I see different stack trace, called from CFRunLoop, Though I still see the GetTypeID in the symbols
I see that it is breaking at 0x00007fff85344080 <+0029> mov (%rdi),%rax, for IOHIDDeviceScheduleWithRunLoop ( Please search with 0x00007fff85344080)
With the help of reference document, I see it is the first argument which means tIOHIDManagerRef, which I create IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
But, How to see the address of it, from above stack trace ?