Skip to content
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

Apple recommends against direct use of Mach #309

Open
mwcampbell opened this issue Jan 30, 2023 · 6 comments
Open

Apple recommends against direct use of Mach #309

mwcampbell opened this issue Jan 30, 2023 · 6 comments

Comments

@mwcampbell
Copy link

While trying to understand the security implications of using Mach message ports, I found the following in this Apple documentation page:

Note: Apple does not support Mach functions for use by external developers and does not guarantee the binary compatibility from one operating system release to the next of code that calls Mach directly. Therefore, Apple recommends against the use of Mach functions by applications. You should use higher-level APIs whenever possible, and call BSD when a low-level interface is required.

So I wonder if it would be better to use Unix domain sockets instead.

@glyn
Copy link
Contributor

glyn commented Feb 6, 2025

@jdm @mrobinson @sagudev I'd be interested in your thoughts about the wisdom of switching to Unix domain sockets for macOS.

Possible advantages:

  1. Improve consistency between macOS and Unix platforms: Inconsistent behaviour of one-shot servers on macOS and Linux #378, IpcReceiver hangs indefinitely on MacOS when other process ends #266.
  2. Avoid the risk of binary incompatibility identified in the OP.
  3. Mach ports doesn't seem to be open source (I'm assuming, but haven't managed to confirm, that the BSD foundations of macOS are open source), so we are critically dependent on its documentation.
  4. The Mach ports based code in ipc-channel looks tricky to maintain. Was this code developed from the Mach port docs alone or was there inside knowledge? For example, select() has an unsafe block over 100 lines long.

Possible disadvantage:

  1. The BSD support may be starting to rot: Build fails on FreeBSD: error[E0425]: cannot find value POLLRDHUP in crate libc #337.
  2. What was the rationale for using Mach ports in the first place? Are there significant advantages over Unix domain sockets?

Unknowns:

  1. Would performance be better, worse, or what?
  2. Would it matter if Unix sockets performed worse than Mach ports on macOS, given that Unix performance is gated by Unix sockets performance?
  3. The Unix socket design may eventually need overhauling: Receiving an ipc channel uses an fd #240. So depending on this for another platform would increase the risk of an overhaul.

@mrobinson
Copy link
Member

mrobinson commented Feb 6, 2025

Would it matter if Unix sockets performed worse than Mach ports on macOS, given that Unix performance is gated by Unix sockets performance?

I think it would be an unacceptable trade off to accept a performance degradation in order to stop using mach ports. Despite the recommendation listed above, mach ports are used by all browser engines and are also an effective way to send IOSurfaces across process boundaries -- something we will likely need for Servo in the future.

@glyn
Copy link
Contributor

glyn commented Feb 6, 2025

Would it matter if Unix sockets performed worse than Mach ports on macOS, given that Unix performance is gated by Unix sockets performance?

I think it would be an unacceptable trade off to accept a perform degradation in order to stop using mach ports.

I see. If I interpret the rest of the comment correctly, it sounds like you may not be in favour of switching from Mach ports to Unix domain sockets even if sockets performed the same or better than Mach ports. Right?

Despite the recommendation listed above, Mach ports are used by all browser engines

That's an interesting data point, thanks. Good to know there's a precedent. Also, Webkit IPC has some similar code to the macOS support in this repository, so that's useful for comparison.

and are also an effective way to send IOSurfaces across process boundaries -- something we will likely need for Servo in the future.

It seems IOSurfaces are Apple-specific, so would it make sense to pass IOSurfaces between processes via ipc-channel rather than using Mach ports directly? (I'm wondering whether the platform abstraction will ultimately belong higher up, above IOSurfaces.)

@mrobinson
Copy link
Member

I see. If I interpret the rest of the comment correctly, it sounds like you may not be in favour of switching from Mach ports to Unix domain sockets even if sockets performed the same or better than Mach ports. Right?

If there was a performance benefit to using Unix domain sockets on macOS, I think that would be a different conversation. These are all sort of hypothetical scenarios though. I think seeing actual numbers are pretty important for making these kind of decisions.

It seems IOSurfaces are Apple-specific, so would it make sense to pass IOSurfaces between processes via ipc-channel rather than using Mach ports directly? (I'm wondering whether the platform abstraction will ultimately belong higher up, above IOSurfaces.)

It's unclear whether we'd pass IOSurfaces via ipc-channel or mach surfaces directly in Servo, but in either case, I imagine we'd probably have to use mach ports one way or another.

@glyn
Copy link
Contributor

glyn commented Feb 6, 2025

I see. If I interpret the rest of the comment correctly, it sounds like you may not be in favour of switching from Mach ports to Unix domain sockets even if sockets performed the same or better than Mach ports. Right?

If there was a performance benefit to using Unix domain sockets on macOS, I think that would be a different conversation. These are all sort of hypothetical scenarios though. I think seeing actual numbers are pretty important for making these kind of decisions.

Agreed. I was just trying to get to the rationale for Mach ports.

It seems IOSurfaces are Apple-specific, so would it make sense to pass IOSurfaces between processes via ipc-channel rather than using Mach ports directly? (I'm wondering whether the platform abstraction will ultimately belong higher up, above IOSurfaces.)

It's unclear whether we'd pass IOSurfaces via ipc-channel or mach surfaces directly in Servo, but in either case, I imagine we'd probably have to use mach ports one way or another.

Did you mean "or mach ports directly in Servo"? If that direction was chosen, then there wouldn't appear to be any IOSurfaces requirements for ipc-channel.

@glyn
Copy link
Contributor

glyn commented Feb 11, 2025

I tried a quick spike of using UNIX sockets instead of Mach ports, but there are some basic missing features that would take some effort to replicate. Apart from libc::POLLRDHUP, and libc::off_t not being available, there are two other significant omissions:

  1. libc::memfd_create is not supported. I copied1 some code to simulate it, but wasn't convinced this was correct.
  2. socketpair() does not support SOCK_SEQPACKET for the AF_UNIX domain. I tried substituting SOCK_DGRAM but this didn't end well (see below).

The tests big_data* fail with errno 54 (ERRCONNRESET) on a send. It appears that the receiver closes the connection before all the sent data was received. I presume this is related to item 2 above.

If anyone else is motivated to continue the spike, please do, but failing that, I suggest we close this issue.

Footnotes

  1. the code came from a stack overflow answer which, according to the history is under a CC BY-SA 3.0 license. I would expect to rewrite code from a spike, but I mention the license in case anyone is tempted to reuse the code as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants