diff options
author | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-07-17 14:17:41 (GMT) |
---|---|---|
committer | Tom Cooksey <thomas.cooksey@nokia.com> | 2009-07-17 14:52:15 (GMT) |
commit | 079f46af1a5821f981fcb53bf7484885f18b5b86 (patch) | |
tree | 4d2d62b16ed9de4cde6f1ba080eda47ff4f52cf6 /src/gui/painting | |
parent | b4d801bf4d6e664ad729e3e95b212b83cc0c784f (diff) | |
download | Qt-079f46af1a5821f981fcb53bf7484885f18b5b86.zip Qt-079f46af1a5821f981fcb53bf7484885f18b5b86.tar.gz Qt-079f46af1a5821f981fcb53bf7484885f18b5b86.tar.bz2 |
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
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qwindowsurface_qws.cpp | 3 |
1 files changed, 2 insertions, 1 deletions
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; |