Yes, the onDisconnect
event fires in the extension and logs the error to the console. Thanks.
I read that documentation before and again after your response and still cannot tell for sure if it means that onDisconnect
in the extension will fire only if the native application initiated it.
It seems to state that but I’m not certain. In addition, I have no code in the C application that explicitly disconnects or sends an exit failure. It has been commented out.
First, all the code works, that is, the extension sends a message to the C app., which processes the request and sends back a JSON response, which is also written to a local file during testing. The message is received by the extension and written to the console, and, at that point, the C app. remains open and awaiting another message. I know this because, while the browser tab is still open, I cannot delete the .exe file because it is in use, nor can I delete the SQLite database because the extension has an open connection through the C app.
If a character is added to the JSON string such that it is no longer correctly formed, the C app writes the string to the local file without error, but the extension throws the JSON.parse error directly from the onMessage handler, or, I think, before the code of the handler is executed. There is not a JSON.parse in the extension code at this time to generate that error. The order the events appear in the console is, first, the JSON.parse error and then a Disconnected due to an error: An unexpected error occurred
message logged by the onDisconnect
handler.
I think the extension is closing the C application simply because the JSON.parse in the subprocess_common.jsm code receiving the message throws the error before the onMessage handler is invoked.
I think this is the part of the view-source:resource://gre/modules/subprocess/subprocess_common.jsm
code that throws the error, but I cannot see where the last throw e
is caught to see if the connection is closed there.
/**
* Reads exactly `length` bytes from the input stream, and parses them as
* UTF-8 JSON data.
*
* @param {integer} length
* The number of bytes to read.
* @returns {Promise<object>}
*
* @rejects {object}
* May be rejected with an Error object, or an object with similar
* properties. The object will include an `errorCode` property with
* one of the following values if it was rejected for the
* corresponding reason:
*
* - Subprocess.ERROR_END_OF_FILE: The pipe was closed before
* enough input could be read to satisfy the request.
* - Subprocess.ERROR_INVALID_JSON: The data read from the pipe
* could not be parsed as a valid JSON string.
*/
readJSON(length) {
if (!Number.isInteger(length) || length <= 0) {
throw new RangeError("Length must be a positive integer");
}
return this.readString(length).then(string => {
try {
return JSON.parse(string);
} catch (e) {
e.errorCode = SubprocessConstants.ERROR_INVALID_JSON;
throw e;
}
});
}
It may be this code that catches the throw e
; but I don’t know where the Cu.reportError(e) is.
onmessage(event) {
let { msg } = event.data;
let listeners = this.listeners.get(msg) || new Set();
for (let listener of listeners) {
try {
listener(event.data);
} catch (e) {
Cu.reportError(e);
}
}
}