From 079f46af1a5821f981fcb53bf7484885f18b5b86 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 17 Jul 2009 16:17:41 +0200 Subject: Fix deadlock in the QWS server when destroying lots of windows First, don't call QWSWindowSurface::winId() in the destructor, as it will actually request a new id if there isn't already one around - which is a bit silly and highlighted the "real" bug. Second, make sure QWSDisplay::Data::takeId() asks for 1 new id before waiting for more ids to arrive. This is because waitForCreation() calls QWSServer::processEventQueue(). If the events in the queue cause takeId() to be called, QWSDisplay::Data::takeId() gets called recursively. Even though there will be a create 15 ids command in the queue, that will only allow 15 QWSDisplay::Data::takeId() calls to return. The 16th call to QWSDisplay::Data::takeId() on the stack will not be able to return because all the IDs have been taken and (because it has been called recursively) no new create id commands have been generated. So the 16th call to takeId() spins in waitForCreate(). Reviewed-by: Paul --- src/gui/kernel/qapplication_qws.cpp | 8 ++++++-- src/gui/painting/qwindowsurface_qws.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index 1e158fc..ab2062c 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -661,10 +661,14 @@ void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd) int QWSDisplay::Data::takeId() { - if (unused_identifiers.count() == 10) + int unusedIdCount = unused_identifiers.count(); + if (unusedIdCount == 10) create(15); - if (unused_identifiers.count() == 0) + if (unusedIdCount == 0) { + create(1); // Make sure we have an incoming id to wait for, just in case we're recursive waitForCreation(); + } + return unused_identifiers.takeFirst(); } diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp index 639bc92..d5a5c20 100644 --- a/src/gui/painting/qwindowsurface_qws.cpp +++ b/src/gui/painting/qwindowsurface_qws.cpp @@ -421,7 +421,8 @@ QWSWindowSurface::QWSWindowSurface(QWidget *widget) QWSWindowSurface::~QWSWindowSurface() { #ifdef Q_BACKINGSTORE_SUBSURFACES - winIdToSurfaceMap()->remove(winId()); + if (d_ptr->winId) + winIdToSurfaceMap()->remove(d_ptr->winId); #endif delete d_ptr; -- cgit v0.12