Couldn’t communicate with a helper application

I have two System Network Extensions that implement XPC for communication with app. While testing everything works fine, but from many users I get complains that app doesn't see extensions, even though users manually enable them in System Settings -> Security & Privacy. From logs I can see that app asks to install extension: OSSystemExtensionRequest.activationRequest, then delegate gets request(_ , didFinishWithResult) call with case completed = 0 result. After that when app tries to communicate with extension NSXPCConnection.remoteObjectProxyWithErrorHandler calls callback with Couldn’t communicate with a helper application.

Any suggestions for debugging the issue are welcome!

Replies

What type of Network System Extension do you have? The reason I ask is because the NETunnelProviderSession object contains a method called sendProviderMessage and the provider side has a method called handleAppMessage. So, for any app to provider communication, this would be an option for providers that derive from NETunnelProvider such as NEPacketTunnelProvider and NEAppProxyProvider.

Now, if your Container app wants to communicate with the provider over an XPC connection, then there also is a matter of allow-listing the service so the Sandbox does not restrict this connection. For example, if your app needed to connect to an XPC service for com.example.apple-samplecode.myProject.myProvider, then the follow exception would need to be declared:

<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
	<string>com.example.apple-samplecode.myProject.myProvider</string>
</array>
Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
  • Yes, both are NEPacketTunnelProvider subclasses. But sendProviderMessage is not suitable in our situation, because I have to communicate with it even before I want to start a connection .

    Regarding com.apple.security.temporary-exception.mach-lookup.global-name - app works perfectly wthout it. I still have added it just for tests and nothing changed. The problem arises on some machines all the time you open the app, and on other machines only after reboot. Looks like on Catalina we get this error after each computer restart, on Big Sur and Monterey you have to restart 2-3 times before you get Couldn’t communicate with a helper application on app start. We are doing this check on app start (applicationDidFinishLaunching), maybe that's too early?

Add a Comment

The problem arises on some machines all the time you open the app, and on other machines only after reboot. Looks like on Catalina we get this error after each computer restart, on Big Sur and Monterey you have to restart 2-3 times before you get Couldn’t communicate with a helper application on app start.

Since this is happening on reboot, have you added logging to your provider to make sure that it is active and setup to receive an XPC connection at the point you are expecting to communicate with the provider?

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Since this is happening on reboot, have you added logging to your provider to make sure that it is active and setup to receive an XPC connection at the point you are expecting to communicate with the provider?

From what I understood from documentation, there is nothing to do, because launchd should start it as soon as I start communicating with it using NSXPCConnection(machServiceName: machServiceName, options: []).remoteObjectProxyWithErrorHandler?

I can add logs for sure, but I would like to know it inside the code, to make the app more robust instead of throwing wrong UI on users.

From what I understood from documentation, there is nothing to do, because launchd should start it as soon as I start communicating with it using NSXPCConnection(machServiceName: machServiceName, options: []).remoteObjectProxyWithErrorHandler?

Something is not adding up here.

Regarding:

I have two System Network Extensions that implement XPC for communication with app.

When you mention app here, is this a launch daemon that is run by launchd or is this an actual container app? The reason I am confused is because of this statement:

From logs I can see that app asks to install extension: OSSystemExtensionRequest.activationRequest, then delegate gets request(_ , didFinishWithResult) call with case completed = 0 result.

If you are installing your Network System Extensions via a launch daemon then I would highly recommend that you DO NOT do this and install them with a standard container app that contains a GUI. Installing a System Extension with a launch daemon will lead to endless edge cases and strange bugs.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Sorry, I mean the App with GUI as in container app. What I wanted to say is that as far as I understand from documentation and example code, in the app I just run NSXPCConnection(machServiceName: machServiceName, options: []).remoteObjectProxyWithErrorHandler[...].myWorkingFunction() on an extension that was already installed and approved by user manually in System Preferences -> Security & Privacy, then it should just work. And indeed it works in 99% of the time. Until user restarts his computer and app gets Couldn’t communicate with a helper application error.

Weird, if your Network System Extension request is trying to communicate with a container app, and both sides of the connection are running, i.e., the container app and the Network System Extension, and the container app is providing a Mach Service that is available and the NSXPCConnection(machServiceName: API cannot connect here, then you should either open a TSI or open a bug report with a sample project so this can be further looked at.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com