Maybe I solved the problem on my own.
I found that QMetaObject::invokeMethod(QObject *object, const char *member, Qt::ConnectionType type), called with type = Qt::QueuedConnection, posts an event to object, that tells object to execute member as soon as it enters its main event loop.
So I tried to substitute
Qt Code:
  1. console->addLine(msg);
To copy to clipboard, switch view to plain text mode 
with
Qt Code:
  1. QMetaObject::invokeMethod(console, "addLine", Qt::QueuedConnection, Q_ARG(QString, msg));
To copy to clipboard, switch view to plain text mode 
and declaring addLine as Q_INVOKABLE, and now my application seems to work fine even if I spam the message logger from a while(true) loop living in its own thread.
Of course, with the spam active, the application slows down, but it doesn't crash and doesn't write the warnings I talked about in the previous post: for the sake of completeness they are
Qt Code:
  1. "QBasicTimer::stop: Failed. Possibly trying to stop from a different thread"
To copy to clipboard, switch view to plain text mode 
and
Qt Code:
  1. "QBasicTimer::start: Timers cannot be started from another thread"
To copy to clipboard, switch view to plain text mode 
I've seen them now for the first time after a long while...

So now my question becomes: am I doing something horribly wrong which I will pay for in the long run or am I just doing things right?

Bests