-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Queue macOS input reports so that large responses aren't dropped #84
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
if (_readHandle.IsAllocated) | ||
{ | ||
_readHandle.Free(); | ||
} | ||
|
||
if (_pinnedReportsQueue.IsAllocated) | ||
{ | ||
_pinnedReportsQueue.Free(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
This addresses a bug where if a YubiKey command would result in multiple input reports being generated, we would get the callbacks but drop the results on the floor. This would generally result in the runloop timing out because we already had received the report via the callback but had no way of caching it.
b8eefbc
to
06edf90
Compare
Test Results: Windows 2 files 2 suites 2s ⏱️ Results for commit 5c10887. ♻️ This comment has been updated with latest results. |
Test Results: Ubuntu 2 files 2 suites 5s ⏱️ Results for commit 5c10887. ♻️ This comment has been updated with latest results. |
Test Results: MacOS 2 files 2 suites 1s ⏱️ Results for commit 5c10887. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Description
This has been a longstanding bug in the SDK that has been haunting me since the FIDO device code was originally written. Apple's documentation on how async input reports are intended to work are about as clear as mud. But with some extra (temporary) debug logging I was able to finally reproduce the issue with enough visibility into what was actually happening. The implementation used by our own
libfido2
library now makes a lot more sense as well.Fundamentally, we were just using the
IOHIDDeviceRegisterInputReportCallback
and its corresponding callback incorrectly. The read buffer that we supply during the registration is just meant to be a place for macOS to cache the report data... I guess? The intended use still is not super clear to me.But what was clear from the logs is that the report callback was getting called faster than we were calling GetReport to read said reports. And since we previously did not queue up any of the reports until they were read, it resulted in reports either getting dropped, or arriving before we ran the IO runloop. That would usually result in the
CFRunLoopRunInMode
call inside ofGetReport
to timeout. Not because the YubiKey was taking a long time, but because the report already came and went and we missed it.So now, we pass a
ConcurrentQueue
into the native callback via aGCHandle
. We queue the report that we see in the callback so that whenGetReport
is eventually called, we will have the report. We first attempt to read straight from the queue, and if there's nothing there, we run the runloop which should then cause macOS to read from the YubiKey. This behavior now much more closely matcheslibfido2
.Fixes (internal issue)
Type of change
Please delete options that are not relevant.
How has this been tested?
Ran some local FIDO2 tests as well as real-world use cases using our internally dependent software.
Test configuration:
Checklist:
dotnet format
to format my code