[iOS 16 Crash] Crash while getting mach port from CFMessagePortRef

I create a local CFMessagePortRef using CFMessagePortCreateLocal and then use CFMachPortGetPort() to try to get the mach port from it like below:

NSString *portIdentifier = [[groupName stringByAppendingString:@"."] stringByAppendingString:sdkId];

NSString *portName = [[portIdentifier stringByAppendingString:@"."] stringByAppendingString:@"mach.port"];

CFMessagePortContext context = {0,(__bridge void *)self,nil,nil,nil};

self.sendPort = CFMessagePortCreateLocal(kCFAllocatorDefault, (__bridge CFStringRef)portName, &callback, &context, false); CFMachPortGetPort(ms->_port);

It works till iOS 15 but crashes on iOS 16. Can anyone help? I have defined below definition of __CFMessagePort:

struct __CFMessagePort {

    CFRuntimeBase _base;

    CFLock_t _lock;

    CFStringRef _name;

    CFMachPortRef _port;        /* immutable; invalidated */

    CFMutableDictionaryRef _replies;

    int32_t _convCounter;

    int32_t _perPID;            /* zero if not per-pid, else pid */

    CFMachPortRef _replyPort;        /* only used by remote port; immutable once created; invalidated */

    CFRunLoopSourceRef _source;        /* only used by local port; immutable once created; invalidated */

    dispatch_source_t _dispatchSource;  /* only used by local port; invalidated */

    dispatch_queue_t _dispatchQ;    /* only used by local port */

    CFMessagePortInvalidationCallBack _icallout;

    CFMessagePortCallBack _callout;    /* only used by local port; immutable */

    CFMessagePortCallBackEx _calloutEx;    /* only used by local port; immutable */

    CFMessagePortContext _context;    /* not part of remote port; immutable; invalidated */

};

Replies

What are you doing with CFMessagePort on iOS? I’m struggling to think of any situation where that’s a good option given iOS’s limitations on IPC.

Regardless, please post a full Apple crash report for this. See Posting a Crash Report for advice on how to do that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Eskimo for your comment. I am using CFMessagePort as IPC mechanism to share an IOSurface between broadcast extension and the main iOS app. I create CFMessagePort communication channel and get the underlying mach port with CFMachPortGetPort. And then transport ioSurface mach port created using IOSurfaceCreateMachPort from broadcast extension to the main app with mach_msg_send. In the main app I get IOSurface back with IOSurfaceLookupFromMachPort. Now that ioSurface is shared between the main app and broadcast extension our main app can get the frames from IOSurface and encode and upload the frames to the server. We are doing this because we have to use vp8 software encoding and we can't do it in extension's 50mb memory limit. There are other reasons as well for why we can't just upload from the extension itself. This works fine till iOS 15. But crashes on iOS 16 at the point where we get the mach port from CFMessagePort with mach_port_t machPort = CFMachPortGetPort(ms->_port);

I have attached the crash report below.

I am also attaching a minimal sample app files to reproduce the crash:

Crash is reproducible just by calling:

let portCommunication = PortCommunication(groupName: "group.ios.mach.port.bug", sdkId: "adsf") where group.ios.mach.port.bug is the app group

Hoping you could help us out. I have also filed a feedback FB11366868 for the same.

If the above is not possible going forward from iOS 16, is there a way to share an IOSurface across main app and the extension? (I know it's possible on Mac with XPC, but not sure if XPC can work iOS yet)

I am using CFMessagePort as IPC mechanism to share an IOSurface between broadcast extension and the main iOS app.

You should open a DTS tech support incident about this. This approach sounds very brittle to me; honestly, I’m surprised it ever worked.

In the very limited situations where we want to support IPC on iOS, we go out of our way to make it easy (for example, the NSFileProviderServiceSource stuff). I’m not super familiar with broadcast extensions, so I don’t know if there’s an equivalent mechanism in that space. A TSI will put you in touch with one of DTS’s graphics specialists, who can give you a definitive answer about whether there’s a supported way to do this.


Oh, wow, I only kinda skimmed your first post and misunderstood why you were posting the struct __CFMessagePort. Looking back at your code I see this:

CFMachPortGetPort(ms->_port);

So, my reading of this is:

  • There’s no API to get a CFMachPort from a CFMessagePort.

  • So you’ve declared your own __CFMessagePort structure.

  • And then use that to get the _port member.

Is that right?

If so, that’s totally unsupported and, yeah, doing stuff like this sets you up for binary compatibility problems in the future.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

how to send correctly IOSurface from Broadcast upload extension?