The simple answer is: avoid reentering your message handler, then:
// C++11, Qt 5.4+
void myMessageHandler(…) {
thread_local bool entered = false;
if (entered) return; // oops
QScopedValueRollback set{entered, true};
…
}
// C++11, Qt 4.8+
void myMessageHandler(…) {
thread_local bool entered = false;
if (entered) return; // oops
QScopedValueRollback back{entered};
entered = true;
…
}
// C++98, Qt 4
QThreadStorage<bool> entered;
void myMessageHandler(…) {
if (entered.localData()) return;
QScopedValueRollback back(entered.localData());
entered.localData() = true;
…
}
This was the old and silly answer, for posterity:
It will lead to infinite recursion only if your logging is synchronous. As soon as you make the logging asynchronous, you don't get the problem anymore: the message handler won't ever be re-entered, since you exit it immediately after emitting a signal, and signal emission over a queued connection posts zero or more QMetaCallEvent
instances to relevant threads' event queues and that's that.
Asynchronous logging is achieved by emitting a signal in the message handler, and handling the log writing from a slot/functor connected to the signal via an explicitly queued connection. You'll probably want your logger to reside in its own thread, so this is a very natural approach then and works great.