gnome-shell/js/ui/windowAttentionHandler.js
Cosimo Cecchi 6359d6ef30 windowAttentionHandler: disconnect signals before destruction
The 'destroy' signal is emitted at the end of the destroy() method.
However the implementation of destroy() can end up emitting one of the
signals we connect to on the window, causing us to re-enter destroy
from its callback.
That will in turn lead to some objects getting disposed twice, which
produces a stack trace like the following one.

This commit fixes the issue by overriding the destroy() method instead
of connecting to the signal, which allows us to disconnect the signal
handlers from the window at an earlier time and avoid re-entrancy.

--

gnome-shell[1082]: Object Gio.Settings (0x7f0af8143f00), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
org.gnome.Shell.desktop[1082]: #0   5627f9e801a8 i   resource:///org/gnome/shell/ui/messageTray.js:238 (7f0aefa9eca0 @ 22)
org.gnome.Shell.desktop[1082]: #1   5627f9e80108 i   resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
org.gnome.Shell.desktop[1082]: #2   5627f9e80070 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
org.gnome.Shell.desktop[1082]: #3   7fffa69fbfc0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #4   5627f9e7ffe0 i   resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
org.gnome.Shell.desktop[1082]: #5   5627f9e7ff38 i   resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
org.gnome.Shell.desktop[1082]: #6   5627f9e7fe80 i   resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
org.gnome.Shell.desktop[1082]: #7   5627f9e7fde8 i   resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
org.gnome.Shell.desktop[1082]: #8   7fffa69ff8e0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #9   7fffa69ff9d0 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #10   5627f9e7fd58 i   resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
org.gnome.Shell.desktop[1082]: #11   5627f9e7fcb8 i   resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
org.gnome.Shell.desktop[1082]: #12   5627f9e7fc28 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
org.gnome.Shell.desktop[1082]: #13   5627f9e7fb80 i   resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
org.gnome.Shell.desktop[1082]: #14   5627f9e7fad0 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
org.gnome.Shell.desktop[1082]: #15   5627f9e7fa58 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
org.gnome.Shell.desktop[1082]: #16   7fffa6a03350 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #17   5627f9e7f9d0 i   resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
org.gnome.Shell.desktop[1082]: #18   5627f9e7f950 i   resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
org.gnome.Shell.desktop[1082]: #19   7fffa6a048f0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
org.gnome.Shell.desktop[1082]: #0   5627f9e801a8 i   resource:///org/gnome/shell/ui/messageTray.js:239 (7f0aefa9eca0 @ 42)
org.gnome.Shell.desktop[1082]: #1   5627f9e80108 i   resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
org.gnome.Shell.desktop[1082]: #2   5627f9e80070 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
org.gnome.Shell.desktop[1082]: #3   7fffa69fbfc0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #4   5627f9e7ffe0 i   resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
org.gnome.Shell.desktop[1082]: #5   5627f9e7ff38 i   resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
org.gnome.Shell.desktop[1082]: #6   5627f9e7fe80 i   resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
org.gnome.Shell.desktop[1082]: #7   5627f9e7fde8 i   resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
org.gnome.Shell.desktop[1082]: #8   7fffa69ff8e0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #9   7fffa69ff9d0 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #10   5627f9e7fd58 i   resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
org.gnome.Shell.desktop[1082]: #11   5627f9e7fcb8 i   resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
org.gnome.Shell.desktop[1082]: #12   5627f9e7fc28 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
org.gnome.Shell.desktop[1082]: #13   5627f9e7fb80 i   resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
org.gnome.Shell.desktop[1082]: #14   5627f9e7fad0 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
org.gnome.Shell.desktop[1082]: #15   5627f9e7fa58 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
org.gnome.Shell.desktop[1082]: #16   7fffa6a03350 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #17   5627f9e7f9d0 i   resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
org.gnome.Shell.desktop[1082]: #18   5627f9e7f950 i   resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
org.gnome.Shell.desktop[1082]: #19   7fffa6a048f0 b   self-hosted:979 (7f0aefa515e0 @ 440)
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed
gnome-shell[1082]: Object Gio.Settings (0x7f0af8161750), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
2019-05-27 08:35:56 -07:00

105 lines
3.6 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
var WindowAttentionHandler = class {
constructor() {
this._tracker = Shell.WindowTracker.get_default();
this._windowDemandsAttentionId = global.display.connect('window-demands-attention',
this._onWindowDemandsAttention.bind(this));
this._windowMarkedUrgentId = global.display.connect('window-marked-urgent',
this._onWindowDemandsAttention.bind(this));
}
_getTitleAndBanner(app, window) {
let title = app.get_name();
let banner = _("“%s” is ready").format(window.get_title());
return [title, banner]
}
_onWindowDemandsAttention(display, window) {
// We don't want to show the notification when the window is already focused,
// because this is rather pointless.
// Some apps (like GIMP) do things like setting the urgency hint on the
// toolbar windows which would result into a notification even though GIMP itself is
// focused.
// We are just ignoring the hint on skip_taskbar windows for now.
// (Which is the same behaviour as with metacity + panel)
if (!window || window.has_focus() || window.is_skip_taskbar())
return;
let app = this._tracker.get_window_app(window);
let source = new Source(app, window);
Main.messageTray.add(source);
let [title, banner] = this._getTitleAndBanner(app, window);
let notification = new MessageTray.Notification(source, title, banner);
notification.connect('activated', () => {
source.open();
});
notification.setForFeedback(true);
source.notify(notification);
source.signalIDs.push(window.connect('notify::title', () => {
let [title, banner] = this._getTitleAndBanner(app, window);
notification.update(title, banner);
}));
}
};
var Source = class WindowAttentionSource extends MessageTray.Source {
constructor(app, window) {
super(app.get_name());
this._window = window;
this._app = app;
this.signalIDs = [];
this.signalIDs.push(this._window.connect('notify::demands-attention',
this._sync.bind(this)));
this.signalIDs.push(this._window.connect('notify::urgent',
this._sync.bind(this)));
this.signalIDs.push(this._window.connect('focus',
() => { this.destroy(); }));
this.signalIDs.push(this._window.connect('unmanaged',
() => { this.destroy(); }));
}
_sync() {
if (this._window.demands_attention || this._window.urgent)
return;
this.destroy();
}
_createPolicy() {
if (this._app && this._app.get_app_info()) {
let id = this._app.get_id().replace(/\.desktop$/,'');
return new MessageTray.NotificationApplicationPolicy(id);
} else {
return new MessageTray.NotificationGenericPolicy();
}
}
createIcon(size) {
return this._app.create_icon_texture(size);
}
destroy(params) {
for (let i = 0; i < this.signalIDs.length; i++)
this._window.disconnect(this.signalIDs[i]);
this.signalIDs = [];
super.destroy(params);
}
open() {
Main.activateWindow(this._window);
}
};