How to fix Native Host Has Exited error in Chrome browser extension -- Native Messaging
E

3

7

How to fix a "Native host has exited" error in my Chrome browser extension for Mac? The docs here on Native Messaging specifically mention this error towards the bottom, and suggest a likely cause, but it is stated quite generally ("This is most likely initiated from your native messaging host") and it's unclear what to attempt to do to solve this.

The logging output in Terminal (if you launch Chrome from the Mac Terminal you can view logging info) has led me to believe that the process for the native host app is itself is never successfully started. I keep getting:

LaunchProcess: failed to execvp:
/Users/mycomputer1/Documents/myhost.app

However, the actual code that prints "Native host has exited" to the console for the background javascript page is:

function onDisconnected() {
  console.log("Inside onDisconnected(): " + chrome.runtime.lastError.message);
  port = null;
}

The onDisconnected() listener is actually invoked as a result of calling connectNative(), which I've done here according to the documentation:

chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
//var imgdata = JSON.stringify(request.imgdata);
//process it somehow here

    port = chrome.runtime.connectNative("com.allinlearning.ailhost");

    if (port)
    {
       console.log("connectNative() returned a non-null port");
    }
});

I know that connectNative() succeeds at some level bc it returns a valid port. However, connectNative() goes on to attempt to locate the native host app and try to launch it. The docs suggests that the host app is the culprit, somehow initiating the breaking of a "pipe" between Chrome and the native app, although my host app has implemented no communication with stdout or stdin at all. Besides, the Chrome log msg ("LaunchProcess: failed to execvp:") seems to indicate that my Mac app was never even launched successfully.

There's more: some source code I found online (perhaps dated? source file) reveals exactly where this "Native host has exited" msg originates, and an examination suggests why Google Chrome's code is closing things down. In HandleReadResult() a Close() is called supplying the very msg and then closes things in response to a Posix read() returning 0. But what in the wide, wide world of sports am I doing wrong (or not doing at all) in my Mac app to cause this the read to fail? My Mac app is not writing anything to stdout, so how is not-writing-anything causing the read error? Or is all of this misleading me, and execvp's failure to launch my host app the deeper cause? If so, why? It's a plain-jane, barebones Mac app.

Epigone answered 5/1, 2015 at 17:59 Comment(2)
Does your binary has the right permissions to run? I.e. owned by you and the executable bit set (chmod u+x myhost.app). What happens if you just run the program from command line? (and yes, your link is dated. The SVN repo isn't updated any more, take a look at the git repo: chromium.googlesource.com/chromium/src/+/master/chrome/browser/…)Consuelaconsuelo
According to Xcode the "Install Permissions" are u+w,go-w,a+rX. The alternative permissions are the same. Btw, how cd I verify it is owned by me? And yes, I have launched the app successfully from the Terminal with a simple open cmd. Do you have any Xcode-created app that works? If so, perhaps you cd send it to me and I could try it.Epigone
C
1

Your "myhost.app" is not a binary, but a directory (as shown by the X in your u+w,go-w,a+rX permissions).

You have two options:

  1. Do NOT create an App bundle for your command-line program, but a plain command-line application (File > New > Project > Command Line Tool in Xcode (tutorial)).

  2. Specify the path to the binary within the app bundle instead of the bundle itself. You can list all files within app bundle by right-clicking on the .app file and selecting "Show package contents". Or run the following command from the terminal (Console) to list all files within your bundle:

    find /Users/mycomputer1/Documents/myhost.app -type f
    
Consuelaconsuelo answered 5/1, 2015 at 21:41 Comment(1)
I used option 2 and it worked. To be specified for others who might want the details, I simply modified the path section of my manifest so it would point to the binary down in the bundle, like so: ". . . . /myhost.app/Contents/MacOS/myhost"Epigone
G
2

Happened to me on Linux (RHEL 7.6).

To find the root cause, you'll need run your chrome from console (command line), and open the gnome extensions page:

$ /opt/google/chrome/chrome "https://extensions.gnome.org"

Then look in the console, if there are any errors.

For me it was 'chrome-gnome-shell' error due to missing python module named 'gi':

Traceback (most recent call last):
Traceback (most recent call last):
  File "/usr/bin/chrome-gnome-shell", line 16, in <module>
    from gi.repository import GLib, Gio
ModuleNotFoundError: No module named 'gi'

To fix it I had to install PyGObject:

$ sudo yum install python36-gobject.x86_64
# or directly with pip: pip3 install PyGObject

Once completed installation, go back to https://extensions.gnome.org (might need to close and reopen Chrome) - Now it shows no error, and works great.

Genesia answered 4/7, 2019 at 8:47 Comment(0)
C
1

Your "myhost.app" is not a binary, but a directory (as shown by the X in your u+w,go-w,a+rX permissions).

You have two options:

  1. Do NOT create an App bundle for your command-line program, but a plain command-line application (File > New > Project > Command Line Tool in Xcode (tutorial)).

  2. Specify the path to the binary within the app bundle instead of the bundle itself. You can list all files within app bundle by right-clicking on the .app file and selecting "Show package contents". Or run the following command from the terminal (Console) to list all files within your bundle:

    find /Users/mycomputer1/Documents/myhost.app -type f
    
Consuelaconsuelo answered 5/1, 2015 at 21:41 Comment(1)
I used option 2 and it worked. To be specified for others who might want the details, I simply modified the path section of my manifest so it would point to the binary down in the bundle, like so: ". . . . /myhost.app/Contents/MacOS/myhost"Epigone
K
1

Your native app and chrome communicate through the console, which in most cases is hidden. If your app uses the console for something more than communicating with chrome (e.g. executing a system command) chrome WILL catch that and interpret it as a bad response from your app and close the connection between them.

So you are advised to use one of the following workarounds:

  • Don't use the (same) console for running anything other than your communication with chrome
  • Buffer your console output instead of sending it to stdout

One more thing to notice is that in some languages (e.g. php) some commands (e.g. preg_match) seem to don't have any output as they manipulate data based on their arguments, BUT they do return a result (e.g. true/false) and if you don't suppress that result (@function() in php) or save it to a variable then it goes to stdout and causes chrome to disconnect.

Sorry if not directly relevant to the question but I hope this helps some people as this question shows way up on the search results. Myself, I struggled with such a problem for a good sum of hours.

Kutch answered 30/5, 2019 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.