diff options
author | El Mehdi Fekari <mfekari@blackberry.com> | 2013-12-19 11:15:34 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-02 19:01:26 +0100 |
commit | 61e1bcb4dd4995c9a8385aad6f3da10f53de2265 (patch) | |
tree | 58a93c3947278bddec6d3f8fb177ea50147e40fd /src | |
parent | e5fd2417701c1ecf35a3c771c647d931cef3f375 (diff) |
QLogging: Avoid infinite loop in error case
If the user code installs a message handler that uses
any API that prints logs (handled by qt_message_print)
then this will lead to an infinite loop.
This patch adds a thread local storage to check
if the message handler is done before the thread
is calling it again.
Note: This check is performed only if the compiler
supports thread_local (__declspec(thread) for MSVC).
Change-Id: I43b0460b8f39b26a18de48a5652a5e55f0b336f8
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qlogging.cpp | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 5b7a674ddb..cff8846cdc 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -925,6 +925,32 @@ static void qDefaultMsgHandler(QtMsgType type, const char *buf) qDefaultMessageHandler(type, emptyContext, QString::fromLocal8Bit(buf)); } +#if defined(Q_COMPILER_THREAD_LOCAL) || (defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)) +#if defined(Q_CC_MSVC) +static __declspec(thread) bool msgHandlerGrabbed = false; +#else +static thread_local bool msgHandlerGrabbed = false; +#endif + +static bool grabMessageHandler() +{ + if (msgHandlerGrabbed) + return false; + + msgHandlerGrabbed = true; + return true; +} + +static void ungrabMessageHandler() +{ + msgHandlerGrabbed = false; +} + +#else +static bool grabMessageHandler() { return true; } +static void ungrabMessageHandler() { } +#endif // (Q_COMPILER_THREAD_LOCAL) || ((Q_CC_MSVC) && !(Q_OS_WINCE)) + static void qt_message_print(QtMsgType msgType, const QMessageLogContext &context, const QString &message) { #ifndef QT_BOOTSTRAPPED @@ -942,12 +968,19 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex if (!messageHandler) messageHandler = qDefaultMessageHandler; - // prefer new message handler over the old one - if (msgHandler == qDefaultMsgHandler - || messageHandler != qDefaultMessageHandler) { - (*messageHandler)(msgType, context, message); + // prevent recursion in case the message handler generates messages + // itself, e.g. by using Qt API + if (grabMessageHandler()) { + // prefer new message handler over the old one + if (msgHandler == qDefaultMsgHandler + || messageHandler != qDefaultMessageHandler) { + (*messageHandler)(msgType, context, message); + } else { + (*msgHandler)(msgType, message.toLocal8Bit().constData()); + } + ungrabMessageHandler(); } else { - (*msgHandler)(msgType, message.toLocal8Bit().constData()); + fprintf(stderr, "%s", message.toLocal8Bit().constData()); } } |