Electron recovery after crash on render process - electron

I'm building an electron app that must reload the render process window if a crash happens.
Currently I can restart the app from the main process
app.relaunch();
app.quit();
But I cannot detect the window crashing.
I tried using the
win.on('unresponsive', () => { ... } );
But the event is not getting generated when I crash the process.
To crash the process I tried:
invoking the process.crash()
using all the available memory.
Both ways successfully crash the process but again, I cannot find a way to detect it.
I tried also using, from the render process, the window.onerror(...) and sending via IPC to the main process a message when the crash is detected, but this seems not to work as well.

You should be looking for the 'crashed' event in webContents. Check https://electronjs.org/docs/api/web-contents#event-crashed
For example put something like this in main process:
win.webContents.on('crashed', (e) => {
app.relaunch();
app.quit()
});

maybe look into "pm2-windows-service" which can install your app as windows service and watch if it crashes, to restart it
https://www.npmjs.com/package/pm2-windows-service
also electron has app.setLoginItemSettings({ openAtLogin: true }); but that does not guard for crash, only provide automatic app start at windows login

Related

Firestore local cache is stale when returning to mobile app - can I force a re-sync?

I'm watching a cloud firestore list for changes using query.onSnapshop in a react-native-firestore app, currently testing on iOS.
While my app is in the foreground, I can make data changes elsewhere (eg. in my companion web app) and the mobile app immediately updates as expected. Usually, if I make changes while the app is closed or offline, they get picked up no problem once it is re-opened or comes online again. Happy days.
However, sometimes, when the app is in the background (not closed, just some other apps have been used in the meantime), I'll make a change elsewhere (eg. add/delete a record which meets the query's criteria), then when I come back to the app, the list does not change - eg. it contains deleted records, or doesn't contain the new ones. Nothing I do on the app can change this - it remains out-of-sync, even if I make local changes, like editing one of the records (even a deleted one). Changing network conditions also does nothing (eg. switching airplane mode off/on again).
The only way the list will get back in sync is if I make another change elsewhere, while the app is still in the foreground, or if I force-close the app and re-open it again.
The issue seems to occur when connecting to both the emulator, and the actual firestore.
I don't think I'm doing anything fancy. Basically following the examples in the documentation:
import React, { useEffect, useState } from 'react';
import firestore from '#react-native-firebase/firestore';
const MyAssignments = (props) => {
const [records, setRecords] = useState([])
useEffect(() => {
const onSnapshot = (snapshot) => {
console.log(snapshot) // this IS triggered but data is stale
setRecords(snapshot)
}
return firestore()
.collection('assignments')
.where('assignedTo', 'array-contains', props.userId)
.onSnapshot(onSnapshot, console.error);
}, [props.userId]);
// render the list
return ...
}
I'm not sure if this is a general firestore issue, a react-native-firebase issue, an issue with the underlying firebase ios SDK, or just my own misunderstanding?
In either case, is there a way to force the local cache to re-sync programatically, ideally when the app regains focus? Or has anyone solved a similar issue or have any ideas what to try next?
Edit 1: Note the code example above is slightly simplified for readability, as parts are spread across a few files and typed with typescript. In reality, I'm using crashlytics.recordError(e) for error handling in production, but console logging, as above, in development.
Edit 2: To debug, I've tried the following:
Switch on debug logging:
import firebase from '#react-native-firebase/app';
firebase.firestore.setLogLevel('debug');
However, this gave no extra logs in my javascript console.
I found I could view native device logs by following this guide and then filtering for Firebase, like so: idevicesyslog --match Firebase
This still shows very few logs, so I don't think debug logging is switched on properly. However, it does log this error every time I foreground the app:
<Notice>: 8.9.1 - [Firebase/Firestore][I-FST000001] WatchStream (10c244d58) Stream error: 'Unavailable: Network connectivity changed'
This error happens every time though. Even when the onSnapshot successfully picks up changes

handle quit on electronjs application

I've got an electron app that manages data on quit. now, I've one option for that like if electron app quits manually by the user it should manage the state of ongoing data like that till now has app recorded should be stored in a local database and then the app should quit but If app quit unexpectedly then it should also check if data is not uploaded into live DB then first update it in local and then sync it with live.
highlights of question:
it should save the data if the app quits unexpectedly.
it should sync the data to live if the user manually quits the app.
If anyone has any idea to do that in simple steps without and breakage it would be very helpful for me. thanks in advance.
it should sync the data to live if the user manually quits the app.
Yes. You can easily do lot of things thanks to app event like that :
app.on('window-all-closed', () => {
// put what you want here
app.quit()
})
You also have this event, perhaps help you:
process.on("uncaughtException", (err) => {
const messageBoxOptions = {
type: "error",
title: "Error in Main process",
message: "Something failed"
};
dialog.showMessageBox(messageBoxOptions);
throw err;
});

Prevent electron app shutdown until cleanup complete

I'm trying to have my electron app do a bunch of cleanup when the app is quit (terminate a few processes, delete some temp files, etc). I am triggering the cleanUp function with the before-quit event. If my computer is running fast, these cleanup operations complete before the app is quit, but if the computer is running slow, the cleanUp function sometimes only executes partially.
Is there a way that I can prevent the app from fully quitting before my cleanUp function has been fully executed?
app.on('before-quit', async () => {
try {
await cleanUp();
} catch (err) {
console.error(err);
}
});
As you can read in the before-quit docs, you can use event.preventDefault() inside the before-quit event handler to prevent the app from terminating.
Your cleanup code can then run unimpeded. At the end of the cleanup, close the app programmatically.
To make sure that before-quit will not block app termination at that time, you probably want to keep track of the current state of the app. You may want to allow the app to terminate inside before-quit if the cleanup code has completed. That means: execute event.preventDefault() only if the cleanup has not been completed yet.
It's probably wise to inform the user about the state of the app: display "shutting down" or something similar, so that it is clear that the app is no longer functional.

The app hanging if you try to close a connection

I'm using Swift 3 with a WebRTC pod called "PodRTC".
If I open a connection, close and open another works perfect. But if I have an open connection for some unfortunate reason I try to created new par connection, the app blockeding. Or the opposite, if you try to close a connection that is not open the app also hangs.
These hanging happen randomly, but always when I call a "close" method. Here is an example:
private func prepareNewPeer() {
if let peer = self.peer, peer.responds(to: #selector(RTCPeerConnection.close)) {
do {
peer.close()
}
}
self.chatChannel = nil
self.peer = nil
....
The application simply hangs, but neither does it generate errors. Apparently, it does not loop because processing is low. It looks like some bug inside the library.
This happens in the .close () method call. I tried to protect the method in every way, but to no avail.
OBS: It is worth mentioning that sometimes it is not just the app that hangs but the entire operating system. I can not play anything else until I compile a new version with Xcode or reboot the phone or wait a few minutes.
To interrupt the app using Xcode's "Pause program execution" button and see what's happening on the various threads:
The line in my code that stopped, was ".close()" and previous comment.

Electron dying without any information, what now?

The app I'm building, when I compile it for distribution packing it with electron-builder, every now and then, dies, showing a blank screen and a disconnected devtools:
Any ideas what's going on or how to start figuring out what's happening here?
Listen for the uncaughtException event and log any error that you get. This will give you insight into what is happening. Then perform any cleanup if necessary and relaunch the app if desired. This allows your app to "recover" from crashes if it is intended to be long-running.
//handle crashes and kill events
process.on('uncaughtException', function(err) {
//log the message and stack trace
fs.writeFileSync('crash.log', err + "\n" + err.stack);
//do any cleanup like shutting down servers, etc
//relaunch the app (if you want)
app.relaunch({args: []});
app.exit(0);
});
You can also listen to the SIGTERM event to see if your application is being killed off, and also gracefully shutdown servers, restart, etc.
process.on('SIGTERM', function() {
fs.writeFileSync('shutdown.log', "Received SIGTERM signal");
//do any cleanup like shutting down servers, etc
//relaunch the app (if you want)
app.relaunch({args: []});
app.exit(0);
});
This can be caused by several different serious faults in the renderer process (out of memory, for example). To fix it, you really have to get your hands on the error.
See https://www.electronjs.org/docs/tutorial/application-debugging#v8-crashes for more details. Specifically, I would recommend settings the ELECTRON_ENABLE_LOGGING environment variable to true before launching the electron process, this should result in the error showing up in the console from which you launch the main process (NOT the chrome devtools console).

Resources