Notes on child processes on Mac OS X


#1

After experiencing several issues in relation with child processes on Mac OS X, some of which were so strange that I could not for the life of me figure out WTF was going on, I want to share my findings to everybody’s benefit here. Take these as dos and donts:

  1. Dont attempt IPC between child processes. That is, if you fork a new process from your host or plugin directly, Mac OS will mess with our IP connections in a way that is beyond human reason. You will see killed processes still accepting connections(!) and such. Zombie sockets. Beware.

  2. Dont attempt to scan or host plugins in a child process. You will see many plugins crash (incl. the whole new NI product line). Whether that is a Mac OS “feature”, or simply due to anti-piracy hacks of the plugin vendors, I don’t know.

  3. There are other artifacts I remember from earlier projects, e.g. fonts not showing up in bold face where they should and such. This and similar minor oddities occur when you do not start your process correctly (no matter if it’s a child process or not).

If you want to do 1 or 2, you need to launch your “child” process as a totally separate process. You also cannot start the executable inside your app bundle directly. Although that will run and look fine, it will still crash plugins. You must launch the app with “open MyApp.app” from a shell, or you’re out of luck. It boils down to that launchd (or the Finder) need to prepare your process in order to make it a fully functional Mac OS X program. Don’t take the bare Unix route.

I vaguely remember there is a Cocoa API for launch services. It might be better than using /usr/bin/open, but I haven’t checked that yet. I’m glad I finally got my multi-process application running.

Ah, and you can’t pass command line arguments to “open”, of course :expressionless: Happy hacking!

Hopefully that is helpful!


#2

Wow. Thanks for sharing!


#3

Since this is 6 years old: is this still the current state of knowledge? E.g. in Tracktion, do you use a child process or a completely separate process for scanning?


#4

Bumpe-di-bump?


#5

I have not tried again since. Still using startAsProcess() for plugin scanning and fetching results from XML files written by the scanner. It is quite possible that macOS has changed in this regard, but actually separating the scanning as much from your host as possible is a good thing to do.


#6

In Tracktion/Waveform we use the “juce_ConnectChildProcess.h” classes which internally use a ChildProcess. Everything seems to work fine so far so maybe macOS has improved in this regard?