uvc-util
uvc-util copied to clipboard
Crash When Compiled on macOS >= Monterey (12.0) but Run On Older Versions of macOS
In UVCController.m there is the following conditional compile:
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 120000) // Before macOS 12 Monterey
#define kIOMainPortDefault kIOMasterPortDefault
#endif
The problem with this, is that the value of kIOMainPortDefault (>= macOS 12.0) doesn't seem to be the same as kIOMasterPortDefault (< macOS 12.0). When the code is compiled on a system running Monterey or later, but then later run on an older operating system, calls like IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &deviceIter)
crash.
To address this, I created a static function that uses @available to return the correct value.
static mach_port_t GetMachMainPortDefault() { if (@available(macOS 12.0, *)) { return kIOMainPortDefault; } else { return kIOMasterPortDefault; } }
If you then replace all instances of kIOMainPortDefault with GetMachMainPortDefault(), the code will not crash as described above.
Is the @available()
syntax compatible with older releases? The @available()
syntax introduces a collection of additional functions into the linked binary that implement the version/platform checks. I found anecdotal evidence in a forum that building with @available()
against the 10.12 SDK and trying to use that binary on 10.11 will also not work.
You'd still need the macro defining kIOMainPortDefault for builds against older SDKs where that constant was not present, because your suggested function must be able to find both constants.
I don't have the time or access to older Mac OS releases right now to test your alteration. Perhaps you could fork a copy, confirm that the @available()
syntax is available across a wide enough swathe of Mac OS releases and works when a newer SDK is run on an older release, and an older SDK run on a newer release works as expected, too. If you can do that and create a pull request I'll happily review your testing results and roll the change into the code.
Thanks for the quick response. Well, my code needs to go back only to macOS Mojave (10.14) and the @available function works there; I also would not have time to investigate earlier versions of macOS. That said, I have tested the change suggested above on Mojave and macOS Monterey 12.0 now. The code works and no longer crashes on Mojave, and continues to work on Monterey without issue. We will be testing with other operating systems imminently, and I can report back.
RE: "You'd still need the macro defining kIOMainPortDefault for builds against older SDKs where that constant was not present, because your suggested function must be able to find both constants." Good point... you're right about that. I build on Monterey, so I didn't think this.
Here's a modified version that deals with compiling on older versions of macOS
tatic mach_port_t
GetMachMainPortDefault()
{
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 120000)
if (@available(macOS 12.0, *)) {
return kIOMainPortDefault;
} else {
return kIOMasterPortDefault;
}
#else
return kIOMasterPortDefault;
#endif
}
I tracked down some official documentation about the @available()
functionality. Also found in the changelog for Apple's swift repository the @available()
functionality showed up in 2015-09-17 (Xcode 7.0). The release of 10.11 (El Capitan) coincides with that date, so your latest function definition is probably the right choice for gating the @available()
usage and remaining compatible as far back as possible release-wise.
I look forward to your testing summary, thanks!
I've prepped the mach default port fix in the 2a0b3a8ad8adb2708595fbfe8a5b93de83e72721 commit.