wayland: Handle xdg_wm_base being destroyed before surface role
If a client owns several windows (for example it can be the case with plasmashell) and it crashes, it's possible to encounter the following case: - xdg_wm_base resources are destroyed - xdg_toplevel is destroyed - another xdg_toplevel is destroyed When kwin processes the destruction of the first xdg_toplevel, it may ping the second xdg_toplevel. But the xdg_wm_base is already free()d by that time, so kwin can access already released memory. In order to prevent that, make the associated XdgSurfaceInterface objects inert. Since XdgToplevelInterface and XdgPopupInterface will become useless after destroying XdgSurfaceInterface, make them inert too. As the spec states, it's illegal to destroy a bound xdg_wm_base object while there are still alive xdg surfaces created by it so destroying the surface role objects should be fine.
This commit is contained in:
parent
1f7975e271
commit
16a07d5df2
2 changed files with 14 additions and 4 deletions
|
@ -59,6 +59,12 @@ XdgShellInterfacePrivate *XdgShellInterfacePrivate::get(XdgShellInterface *shell
|
|||
return shell->d.get();
|
||||
}
|
||||
|
||||
void XdgShellInterfacePrivate::xdg_wm_base_destroy_resource(Resource *resource)
|
||||
{
|
||||
const QList<XdgSurfaceInterface *> surfaces = xdgSurfaces.keys(resource);
|
||||
qDeleteAll(surfaces);
|
||||
}
|
||||
|
||||
void XdgShellInterfacePrivate::xdg_wm_base_destroy(Resource *resource)
|
||||
{
|
||||
if (xdgSurfaces.key(resource)) {
|
||||
|
@ -168,8 +174,6 @@ XdgSurfaceInterfacePrivate *XdgSurfaceInterfacePrivate::get(XdgSurfaceInterface
|
|||
|
||||
void XdgSurfaceInterfacePrivate::xdg_surface_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_EMIT q->aboutToBeDestroyed();
|
||||
XdgShellInterfacePrivate::get(shell)->unregisterXdgSurface(q);
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
@ -256,6 +260,11 @@ XdgSurfaceInterface::XdgSurfaceInterface(XdgShellInterface *shell, SurfaceInterf
|
|||
|
||||
XdgSurfaceInterface::~XdgSurfaceInterface()
|
||||
{
|
||||
delete d->toplevel;
|
||||
delete d->popup;
|
||||
|
||||
Q_EMIT aboutToBeDestroyed();
|
||||
XdgShellInterfacePrivate::get(d->shell)->unregisterXdgSurface(this);
|
||||
}
|
||||
|
||||
XdgToplevelInterface *XdgSurfaceInterface::toplevel() const
|
||||
|
@ -342,7 +351,6 @@ void XdgToplevelInterfacePrivate::reset()
|
|||
|
||||
void XdgToplevelInterfacePrivate::xdg_toplevel_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_EMIT q->aboutToBeDestroyed();
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
@ -480,6 +488,7 @@ XdgToplevelInterface::XdgToplevelInterface(XdgSurfaceInterface *surface, ::wl_re
|
|||
|
||||
XdgToplevelInterface::~XdgToplevelInterface()
|
||||
{
|
||||
Q_EMIT aboutToBeDestroyed();
|
||||
}
|
||||
|
||||
XdgShellInterface *XdgToplevelInterface::shell() const
|
||||
|
@ -638,7 +647,6 @@ void XdgPopupInterfacePrivate::reset()
|
|||
|
||||
void XdgPopupInterfacePrivate::xdg_popup_destroy_resource(Resource *resource)
|
||||
{
|
||||
Q_EMIT q->aboutToBeDestroyed();
|
||||
delete q;
|
||||
}
|
||||
|
||||
|
@ -676,6 +684,7 @@ XdgPopupInterface::XdgPopupInterface(XdgSurfaceInterface *surface, SurfaceInterf
|
|||
|
||||
XdgPopupInterface::~XdgPopupInterface()
|
||||
{
|
||||
Q_EMIT aboutToBeDestroyed();
|
||||
}
|
||||
|
||||
SurfaceInterface *XdgPopupInterface::parentSurface() const
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
QMap<quint32, QTimer *> pings;
|
||||
|
||||
protected:
|
||||
void xdg_wm_base_destroy_resource(Resource *resource) override;
|
||||
void xdg_wm_base_destroy(Resource *resource) override;
|
||||
void xdg_wm_base_create_positioner(Resource *resource, uint32_t id) override;
|
||||
void xdg_wm_base_get_xdg_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override;
|
||||
|
|
Loading…
Reference in a new issue