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>bb10
parent
e5fd241770
commit
61e1bcb4dd
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue