c++ multithreading qt qdebug

c++ - ¿Es qDebug() seguro para subprocesos?



multithreading qt (6)

¿Es qDebug() seguro para subprocesos? Por thread-safe no solo me refiero a no-crashing, sino también si llamo a qDebug() desde diferentes hilos, ¿es posible que la salida se mezcle? Lo probé con este código, y no parece ser así, sin embargo, no pude encontrar en ninguna parte de la documentación donde hablan sobre esto.

Este es mi código de prueba:

#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(); }

No había ''a'' y ''b'' mezclados en la misma línea en ninguna parte, pero aún no estoy seguro de si es 100% seguro para hilos ...


A continuación están mis respuestas y comentarios:

  1. Si la documentación de qDebug () no menciona si es seguro para subprocesos o no, debemos suponer que no lo es. La respuesta probablemente depende de la plataforma: cómo se implementa qDebug () a nivel del sistema (Linux, Windows, ...).

  2. En lugar de la cuestión más amplia de seguridad de subprocesos, creo que estaba haciendo una pregunta más específica como esta: "¿El uso de qDebug () en una aplicación de subprocesos múltiples dará lugar a líneas de salida intercaladas?" La respuesta es "Sí, ocasionalmente". como lo demuestran los resultados producidos por @dmcontador arriba. Y la probabilidad aumenta cuando las cadenas que se van a imprimir son cada vez más largas, como se explica en @quetzalcoatl más arriba.

  3. La respuesta no depende de si usa qDebug ("...") o qDebug () << "...", ya que ambos finalmente llamarán al código de implementación del nivel del sistema.

  4. No es fácil para mí producir líneas de salida intercaladas usando su código de ejemplo original. Así que he creado un nuevo ejemplo como se muestra a continuación:

    #include <QCoreApplication> #include <QtConcurrent> #define MAX_ITERS 10 #define MAX_LEN 10000 void print_a() { QString a(MAX_LEN, ''a''); for(int i = 0; i < MAX_ITERS; ++i) { qDebug().noquote() << a; } } void print_b() { QString b(MAX_LEN, ''b''); for(int i = 0; i < MAX_ITERS; ++i) { qDebug().noquote() << b; } } int main(int argc, char * argv[]) { QCoreApplication a(argc, argv); QtConcurrent::run(print_a); QtConcurrent::run(print_b); return 0; }

La probabilidad aumenta cuando aumenta MAX_LEN.

  1. Una pregunta de seguimiento sería: "¿Cómo usar qDebug () para producir líneas de salida no entrelazadas?" Una solución sería usar QMutex en cada línea de qDebug (). Tenga en cuenta que no he probado esta solución que no es práctica.

Ambos

qDebug("xx")

tanto como

qDebug() << "xx"

qInfo, qWarning, qCritical, y las versiones clasificadas como qCDebug, qCInfo, qCWarning, qCritical son seguras para ser utilizadas simultáneamente desde diferentes subprocesos.

Sin embargo, debe asegurarse de que el sumidero de registros también pueda manejar datos grandes de forma atómica. De aquí viene la confusión, porque stderr aparentemente rompe líneas que son demasiado largas. Puede verificar esto fácilmente simplemente reemplazando qDebug () por fprintf (stderr) en el ejemplo: Muestra exactamente el mismo comportamiento para mí.

Puedes probar otros receptores de registro, como journald. De todos modos, también pueden imponer restricciones a la longitud máxima. En general, sugiero mantener la longitud máxima de un mensaje de registro razonable.


He encontrado algo así: http://www.qtcentre.org/threads/28879-redirecting-qDebug-to-file-threading-question

Citando:

Para responder a la pregunta si qdebug es seguro para el hilo: QDebug usa un QTextstream. Un QTextStream no es seguro para los hilos. La documentación no es clara al respecto, pero si observa el código fuente de qdebug o qtextstream, verá que no hay bloqueo de exclusión mutua en el código.



Me temo que no es seguro para subprocesos. Además, probé tu código y obtuve resultados mixtos.

aaaaaaaaaaaabbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbabbbbbbbbbbbbbbbbbb

Tuve la misma suerte con qDebug() << "..."

Probado en Qt5.2.1 con el compilador mingw48_32.


Prácticamente qDebug( ..text.. ) es seguro para subprocesos (al menos si se compila con gcc).

Si busca en el archivo fuente qt (4) qglobal.cpp , qDebug llama a qt_message_output que llama a fprintf(stderr, ...) , que es seguro para subprocesos en glibc

( qDebug() << .. es otra historia)