Is qDebug()
thread-safe? By thread-safe I don't just mean not-crashing, but also if I call qDebug()
from different threads, is it possible for the output to become mixed-up? I tested it with this code, and it doesn't appear to be so, however, I couldn't find anywhere in the documentation where they talk about this.
This is my test code:
#include <QtConcurrent>
#include <QApplication>
void print_a() {
for (int ii = 0; ii < 10000; ii++) {
qDebug("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
}
void print_b()
{
for (int ii = 0; ii < 10000; ii++) {
qDebug("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtConcurrent::run(print_a);
QtConcurrent::run(print_b);
return a.exec();
}
There were no 'a' and 'b' mixed in the same line anywhere, but I'm still not sure if it's 100% thread safe...
I've found such thing: http://www.qtcentre.org/threads/28879-redirecting-qDebug-to-file-threading-question
Quoting:
I'm afraid that it is not thread-safe. Also, I tried your code and had mixed output.
I had the same luck with
qDebug() << "..."
Tested in Qt5.2.1 with mingw48_32 compiler.
Following are my answer and comments:
If the documentation of qDebug() does not mention whether it is thread-safe or not, we should assume it is not. The answer is likely platform-dependent: how qDebug() is implemented at the system level (Linux, Windows, ...).
Instead of the broader question of thread-safety, I think you were asking a more specific question like this: "Will the use of qDebug() in a multi-threaded application lead to interleaved output lines?" The answer is "Yes, occasionally." as demonstrated by the results produced by @dmcontador above. And the probability increases when the strings to be printed out are getting longer, as explained by @quetzalcoatl above.
The answer does not depend on whether you use qDebug("...") or qDebug() << "...", as both will finally call the system-level implementation code.
It is not easy for me to produce interleaved output lines using your original example code. So I have created a new example as shown below:
The probability increases when you increase MAX_LEN.
Both
as well as
qInfo, qWarning, qCritical, and the categorized versions like qCDebug, qCInfo, qCWarning, qCritical are safe to be used concurrently from different threads.
However, you have to make sure that the log sink can also handle large data atomically. This is were the confusion comes from, because stderr apparently breaks line that are too long. You can easily verify this by just replacing qDebug() by fprintf(stderr) in the example: It shows exactly the same behavior for me.
You can try other logging sinks, like journald. Anyhow, they might impose restrictions on the maximum length, too. In general I'd suggest to keep the maximum length of a log message reasonable.
The docs say If a function is not marked as thread-safe or reentrant, it should not be used from different threads. In case of
qDebug()
it doesn't say it's thread-safe or reentrant, so it's probably not safe to use from different threads.Practically
qDebug( ..text.. )
is thread-safe (at least if compiled with gcc).If you look in the qt (4) source file
qglobal.cpp
,qDebug
callsqt_message_output
which callsfprintf(stderr, ...)
, which is thread-safe in glibc(
qDebug() << ..
is another story )