From 55d1c7e2ab9fb675f8f5a6e4c03ff17093a01cff Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 26 Feb 2014 15:45:14 -0500 Subject: [PATCH] background: fix cancellable issue If we have the following sequence: cache.getImageContent({ filename: "foo", cancellable: cancellable1 }); cache.getImageContent({ filename: "foo", cancellable: cancellable2 }); cancellable1.cancel(); Then the second load will complete with "null" as its content, even though it was never cancelled, and we'll see a blank image. Meanwhile, since the second load simply appends to the list of callers for the second load, cancellable2 does absolutely nothing: cancelling it won't stop the load, and it will still receive onFinished handling. To prevent this from happening, give the actual load operation its own Gio.Cancellable, which is "ref-counted" -- only cancel it when all the other possible callers cancel. Based on work from Jasper St. Pierre https://bugzilla.gnome.org/show_bug.cgi?id=722149 --- js/ui/background.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/js/ui/background.js b/js/ui/background.js index 506fe5974..b1eb57a04 100644 --- a/js/ui/background.js +++ b/js/ui/background.js @@ -134,6 +134,21 @@ const BackgroundCache = new Lang.Class({ _attachCallerToFileLoad: function(caller, fileLoad) { fileLoad.callers.push(caller); + + if (!caller.cancellable) + return; + + caller.cancellable.connect(Lang.bind(this, function() { + let idx = fileLoad.callers.indexOf(caller); + fileLoad.callers.splice(idx, 1); + + if (fileLoad.callers.length == 0) { + fileLoad.cancellable.cancel(); + + let idx = this._pendingFileLoads.indexOf(fileLoad); + this._pendingFileLoads.splice(idx, 1); + } + })); }, _loadImageContent: function(params) { @@ -146,6 +161,7 @@ const BackgroundCache = new Lang.Class({ let caller = { monitorIndex: params.monitorIndex, effects: params.effects, + cancellable: params.cancellable, onFinished: params.onFinished }; for (let i = 0; i < this._pendingFileLoads.length; i++) { @@ -160,6 +176,7 @@ const BackgroundCache = new Lang.Class({ let fileLoad = { filename: params.filename, style: params.style, + cancellable: new Gio.Cancellable(), callers: [] }; this._attachCallerToFileLoad(caller, fileLoad);