helper app dyld crash when using Xcode debugger

When I'm running my Mac app in the Xcode debugger, and it launches a helper app, the helper crashes with a dyld error. This does not happen if I am not debugging.

Termination Reason:    Namespace DYLD, Code 1 Library missing
Library not loaded: @rpath/Cal3D.framework/Versions/A/Cal3D
Referenced from: <3C1A67BA-5545-31A2-86C5-77104B0194FE> /Volumes/VOLUME/*/SBEngineLib4.framework/Versions/A/SBEngineLib4

The frameworks SBEngineLib4.framework and Cal3D.framework exist in the main app. The helper app does not contain any frameworks, but does contain dylib versions of those frameworks, which I suppose is confusing things somehow.

Replies

Is this helper app nested within your main app?

When I'm running my Mac app in the Xcode debugger

That means you selected your main app’s scheme and chose Product > Run, right? So you’re debugging the main app and hit this problem when the main app tries to run the helper app.

Is any of this stuff sandboxed?

If not, do you have the hardened runtime enabled?

Is the main app running the helper as a child process (fork then exec*, or posix_spawn, or NSTask, or Process, or similar). Or as an independent app (NSWorkspace, or Launch Services, or similar)?

Share and Enjoy

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

Is this helper app nested within your main app?

No.

That means you selected your main app’s scheme and chose Product > Run, right? So you’re debugging the main app and hit this problem when the main app tries to run the helper app.

Correct.

Is any of this stuff sandboxed?

No.

If not, do you have the hardened runtime enabled?

Hardened runtime is enabled for the main app, not the helper.

Is the main app running the helper as a child process (fork then exec*, or posix_spawn, or NSTask, or Process, or similar). Or as an independent app (NSWorkspace, or Launch Services, or similar)?

Running as an independent app using -[NSWorkspace openApplicationAtURL:configuration:completionHandler:]. The configuration includes an additional argument.

I tried re-signing the helper with the hardened runtime, and then it won't launch at all. Trying to launch it in Terminal shows

Runtime error 217 at 000000011003B572

Googling "runtime error 217" just shows Windows errors.

Aha! When I re-signed the helper app using the hardened runtime and an entitlements file that sets com.apple.security.cs.allow-unsigned-executable-memory to YES, then the helper runs even when I'm debugging. I don't know why it needs that entitlement, but it probably has something to do with the helper was built using the FireMonkey framework, not Xcode. So, thanks for asking about hardened runtime.

Glad to hear you’re making progress.

I’m concerned about the combination of this:

Is this helper app nested within your main app?

No.

and this:

The frameworks SBEngineLib4.framework and Cal3D.framework exist in the main app.

Having one app load frameworks out of an ‘unrelated’ app is a tricky business. It’ll work but:

Share and Enjoy

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

The frameworks SBEngineLib4.framework and Cal3D.framework exist in the main app.

Having one app load frameworks out of an ‘unrelated’ app is a tricky business.

Perhaps I wasn't clear, but I definitely wasn't trying to have one app load frameworks out of another app. The main app contains private frameworks just for its own use, and the helper contains dylibs for its own use. It's just under this debugging situation that things somehow got confused.

One thing to watch out for during development is that Xcode:

  • Builds all your apps and frameworks into your Products/Debug directory

  • Set up a dynamic linker environment variable to force your apps to look for framework in that same directory

This is great when you’re building an app with a completely separate framework, which is historically how this sort of thing was done. However, it causes grief for folks building an app with an embedded framework because you end up loading the framework from Products/Debug rather than the one from Products/Debug/MyApp.app/Contents/Frameworks. Most of the time that doesn’t matter but it can trigger weird issues if you’re loading an XPC service from that framework, or you have specific sandbox contraints, and so on.

If this is causing me grief I set things up so that I copy my app to a different directory and debug it from that. I explain how to do that — for very different reasons — in Debugging a Network Extension Provider.

Share and Enjoy

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

One thing to watch out for during development is that Xcode:

  • Builds all your apps and frameworks into your Products/Debug directory
  • Set up a dynamic linker environment variable to force your apps to look for framework in that same directory

I have specified legacy build locations in my project, so that the app and frameworks are built in different directories.