[server] Don't destroy ShadowInterface when SurfaceInterface gets destroyed

Summary:
Unlike the other cases this one is not as dangerous as the shadow
protocol doesn't have a destructor request (yet).

Once that is added the problem would be the same: destroying the
ShadowInterface when the parent SurfaceInterface gets destroyed would
result in a protocol error on client side.

Reviewers: #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1711
This commit is contained in:
Martin Gräßlin 2016-05-30 11:21:12 +02:00
parent 33e802913f
commit 1f48daea1e
2 changed files with 47 additions and 8 deletions

View file

@ -45,6 +45,7 @@ private Q_SLOTS:
void testCreateShadow();
void testShadowElements();
void testSurfaceDestroy();
private:
Display *m_display = nullptr;
@ -266,5 +267,51 @@ void ShadowTest::testShadowElements()
QVERIFY(!serverShadow->left());
}
void ShadowTest::testSurfaceDestroy()
{
using namespace KWayland::Client;
using namespace KWayland::Server;
QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated);
QVERIFY(serverSurfaceCreated.isValid());
QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
QVERIFY(serverSurfaceCreated.wait());
auto serverSurface = serverSurfaceCreated.first().first().value<SurfaceInterface*>();
QSignalSpy shadowChangedSpy(serverSurface, &SurfaceInterface::shadowChanged);
QVERIFY(shadowChangedSpy.isValid());
QScopedPointer<Shadow> shadow(m_shadow->createShadow(surface.data()));
shadow->commit();
surface->commit(Surface::CommitFlag::None);
QVERIFY(shadowChangedSpy.wait());
auto serverShadow = serverSurface->shadow();
QVERIFY(serverShadow);
// destroy the parent surface
QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed);
QVERIFY(surfaceDestroyedSpy.isValid());
QSignalSpy shadowDestroyedSpy(serverShadow, &QObject::destroyed);
QVERIFY(shadowDestroyedSpy.isValid());
QSignalSpy clientDisconnectedSpy(serverSurface->client(), &ClientConnection::disconnected);
QVERIFY(clientDisconnectedSpy.isValid());
surface.reset();
QVERIFY(surfaceDestroyedSpy.wait());
QVERIFY(shadowDestroyedSpy.isEmpty());
// destroy the shadow
shadow.reset();
// shadow protocol doesn't have a destroy callback yet, so also disconnect
m_connection->deleteLater();
m_connection = nullptr;
QVERIFY(clientDisconnectedSpy.wait());
if (shadowDestroyedSpy.isEmpty()) {
QVERIFY(shadowDestroyedSpy.wait());
}
QCOMPARE(shadowDestroyedSpy.count(), 1);
m_shm->destroy();
m_compositor->destroy();
m_shadow->destroy();
m_queue->destroy();
}
QTEST_GUILESS_MAIN(ShadowTest)
#include "test_shadow.moc"

View file

@ -105,14 +105,6 @@ void ShadowManagerInterface::Private::createShadow(wl_client *client, wl_resourc
delete shadow;
return;
}
QObject::connect(s, &QObject::destroyed, shadow,
[shadow] {
if (shadow->resource()) {
wl_resource_destroy(shadow->resource());
delete shadow;
}
}
);
s->d_func()->setShadow(QPointer<ShadowInterface>(shadow));
}