From 5c0c1b15f87bd5ba4ca1688560553e7c7cd34dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Mon, 2 Oct 2023 14:30:08 +0200 Subject: [PATCH] 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: --- js/ui/screenshot.js | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js index eb561a3b0..77d4c0c6f 100644 --- a/js/ui/screenshot.js +++ b/js/ui/screenshot.js @@ -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); } }