QCFSocketNotifier: fix registering a source in the run loop

Even if a callback type is not automatically re-enabled, callbacks are
implicitly enabled when the source has been added to the run loop.
In this case, calling CFSocketEnableCallBacks() could produce an extra
notification if there is a pending event in the queue.

The bug is quite unstable and completely depends on the internal OS
delays. So, it can't be tested inside Qt.

Task-number: QTBUG-59930
Change-Id: I751b8b8cf99cb86b80055f2214a42a638f01abe4
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Alex Trotsenko 2017-04-27 16:21:46 +03:00
parent 0fefed996c
commit 979c8b746b

View File

@ -292,10 +292,19 @@ void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoo
continue;
}
if (!socketInfo->readNotifier)
// Apple docs say: "If a callback is automatically re-enabled,
// it is called every time the condition becomes true ... If a
// callback is not automatically re-enabled, then it gets called
// exactly once, and is not called again until you manually
// re-enable that callback by calling CFSocketEnableCallBacks()".
// So, we don't need to enable callbacks on registering.
socketInfo->readEnabled = (socketInfo->readNotifier != nullptr);
if (!socketInfo->readEnabled)
CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
if (!socketInfo->writeNotifier)
socketInfo->writeEnabled = (socketInfo->writeNotifier != nullptr);
if (!socketInfo->writeEnabled)
CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
continue;
}
if (socketInfo->readNotifier && !socketInfo->readEnabled) {