screenshot: Also do pipeline fallback on screencast crashes during startup

Since the last commit, we have infrastructure in place in the ScreencastService
to blocklist pipelines which crashed the recorder.

If such a crash happens a few minutes into a screencast, we can't do any better
than telling the user about the problem and encouraging them to try again (with
the faulty pipeline now blocklisted).

If the crash happens while starting the recording though, we can actually do
better: We can try to auto-restart the ScreencastService ourselves, and the
recording might still succeed without the user noticing anything. So retry
that start of the recorder for two more times, and then finally give up.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2976>
This commit is contained in:
Jonas Dreßler 2023-10-02 14:30:08 +02:00
parent b6bfe07137
commit 5c0c1b15f8

View File

@ -1116,6 +1116,11 @@ export const ScreenshotUI = GObject.registerClass({
if (!this._screencastInProgress)
return;
// If the recorder crashed while we're starting it in _startScreencast(),
// let the catch-block there handle the error.
if (this._screencastStarting)
return;
this._screencastFailed(ScreencastPhase.RECORDING,
new GLib.Error(ScreencastErrors, ScreencastError.SERVICE_CRASH,
'Service crashed'));
@ -1947,7 +1952,7 @@ export const ScreenshotUI = GObject.registerClass({
this.emit('screenshot-taken', file);
}
async _startScreencast() {
async _startScreencast(nRetries = 0) {
if (this._windowButton.checked)
return; // TODO
@ -1981,8 +1986,11 @@ export const ScreenshotUI = GObject.registerClass({
// Set this before calling the method as the screen recording indicator
// will check it before the success callback fires.
this._setScreencastInProgress(true);
let retry = false;
try {
this._screencastStarting = true;
const [, path] = await method(
GLib.build_filenamev([
/* Translators: this is the folder where recorded
@ -1998,7 +2006,21 @@ export const ScreenshotUI = GObject.registerClass({
this._screencastPath = path;
} catch (error) {
this._screencastFailed(ScreencastPhase.STARTUP, error);
// Recorder service disconnected without reply -> service crash
// That should have blocklisted the pipeline that caused the crash,
// so try again.
if (error.matches(Gio.DBusError, Gio.DBusError.NO_REPLY) && nRetries < 2)
retry = true;
else
this._screencastFailed(ScreencastPhase.STARTUP, error);
}
delete this._screencastStarting;
if (retry) {
console.log('Screencast service crashed during startup, trying again');
this._setScreencastInProgress(false);
this._startScreencast(nRetries + 1);
}
}