Fix sporadic hang in QLocalServer::close() in OS X 10.7

There is a bug in CFSocket/CFRunLoopSource in OS X 10.7 which can lead to a deadlock
in CFRunLoopRemoveSource or CFRunLoopSourceInvalidate if the CFSocket manager thread
is concurrently calling CFSocketInvalidate as a result of the socket's file descriptor
having been closed.

QLocalServer::close() triggers this race by closing the socket fd before unregistering
the QSocketNotifier, which internally uses CFSocket.

This commit fixes the problem by changing the ordering in close() so that the socket notifier
is disabled before closing the file descriptor.  This change also makes QLocalServer::close()
perform operations in reverse order to QLocalServer::listen(), as would be expected.

Task-number: QTBUG-22789
Merge-request: 1470
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
(cherry picked from commit a9c3f7169faf4621d39714f753d6e8b376c5d6e5)
Change-Id: Ia9c3f7169faf4621d39714f753d6e8b376c5d6e5
bb10
Robert Knight 2011-11-18 18:07:21 +01:00 committed by Qt by Nokia
parent 36ea62e64f
commit 67106b169c
1 changed files with 4 additions and 4 deletions

View File

@ -149,16 +149,16 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
*/
void QLocalServerPrivate::closeServer()
{
if (-1 != listenSocket)
QT_CLOSE(listenSocket);
listenSocket = -1;
if (socketNotifier) {
socketNotifier->setEnabled(false); // Otherwise, closed socket is checked before deleter runs
socketNotifier->deleteLater();
socketNotifier = 0;
}
if (-1 != listenSocket)
QT_CLOSE(listenSocket);
listenSocket = -1;
if (!fullServerName.isEmpty())
QFile::remove(fullServerName);
}