comparison base/Debug.cpp @ 1061:c1e43c8d2527 tonioni

Thread-local debug was causing crash on exit with Qt 5.4.x. But we introduced that because QDebug itself was crashing when used from multiple threads. Replace with simpler fstream version
author Chris Cannam
date Tue, 31 Mar 2015 10:36:52 +0100
parents c49d52386cde
children 8f076d02569a
comparison
equal deleted inserted replaced
1058:c49d52386cde 1061:c1e43c8d2527
14 */ 14 */
15 15
16 #include "Debug.h" 16 #include "Debug.h"
17 #include "ResourceFinder.h" 17 #include "ResourceFinder.h"
18 18
19 #include <QString> 19 #include <QMutex>
20 #include <QDir>
20 #include <QUrl> 21 #include <QUrl>
21 #include <QMutex>
22 #include <QMutexLocker>
23 #include <QFile>
24 #include <QDir>
25 #include <QCoreApplication> 22 #include <QCoreApplication>
26 #include <QDateTime>
27 #include <QThreadStorage>
28 23
29 #include <cstdio> 24 #ifndef NDEBUG
30 25
31 static QThreadStorage<QDebug *> debugs; 26 static SVDebug *debug = 0;
32 static QMutex mutex; 27 static QMutex mutex;
33 static char *prefix = 0;
34 28
35 QDebug & 29 SVDebug &getSVDebug() {
36 getSVDebug() 30 mutex.lock();
31 if (!debug) {
32 debug = new SVDebug();
33 }
34 mutex.unlock();
35 return *debug;
36 }
37
38 SVDebug::SVDebug() :
39 m_prefix(0),
40 m_ok(false),
41 m_eol(false)
37 { 42 {
38 mutex.lock();
39
40 QDebug *debug = 0;
41
42 QString pfx = ResourceFinder().getUserResourcePrefix(); 43 QString pfx = ResourceFinder().getUserResourcePrefix();
43 QDir logdir(QString("%1/%2").arg(pfx).arg("log")); 44 QDir logdir(QString("%1/%2").arg(pfx).arg("log"));
44 45
45 if (!prefix) { 46 m_prefix = strdup(QString("[%1]")
46 prefix = strdup(QString("[%1]") 47 .arg(QCoreApplication::applicationPid())
47 .arg(QCoreApplication::applicationPid()) 48 .toLatin1().data());
48 .toLatin1().data());
49 }
50 49
51 //!!! what to do if mkpath fails? 50 //!!! what to do if mkpath fails?
52 if (!logdir.exists()) logdir.mkpath(logdir.path()); 51 if (!logdir.exists()) logdir.mkpath(logdir.path());
53 52
54 if (!debugs.hasLocalData()) { 53 QString fileName = logdir.path() + "/sv-debug.log";
55 QFile *logFile = new QFile(logdir.path() + "/sv-debug.log"); 54
56 if (logFile->open(QIODevice::WriteOnly | QIODevice::Append)) { 55 m_stream.open(fileName.toLocal8Bit().data(), std::ios_base::out);
57 QDebug(QtDebugMsg) << (const char *)prefix 56
58 << "Opened debug log file " 57 if (!m_stream) {
59 << logFile->fileName(); 58 QDebug(QtWarningMsg) << (const char *)m_prefix
60 debug = new QDebug(logFile); 59 << "Failed to open debug log file "
61 } else { 60 << fileName << " for writing";
62 QDebug(QtWarningMsg) << (const char *)prefix
63 << "Failed to open debug log file "
64 << logFile->fileName()
65 << " for writing, using console debug instead";
66 delete logFile;
67 logFile = 0;
68 debug = new QDebug(QtDebugMsg);
69 }
70 debugs.setLocalData(debug);
71 *debug << endl << (const char *)prefix << "Log started at "
72 << QDateTime::currentDateTime().toString();
73 } else { 61 } else {
74 debug = debugs.localData(); 62 cerr << m_prefix << ": Log file is " << fileName << endl;
63 m_ok = true;
75 } 64 }
65 }
76 66
77 mutex.unlock(); 67 SVDebug::~SVDebug()
78 68 {
79 QDebug &dref = *debug; 69 m_stream.close();
80 dref << endl << (const char *)prefix;
81
82 return dref;
83 } 70 }
84 71
85 QDebug & 72 QDebug &
86 operator<<(QDebug &dbg, const std::string &s) 73 operator<<(QDebug &dbg, const std::string &s)
87 { 74 {
88 dbg << QString::fromUtf8(s.c_str()); 75 dbg << QString::fromUtf8(s.c_str());
89 return dbg; 76 return dbg;
90 } 77 }
78
79 #endif
91 80
92 std::ostream & 81 std::ostream &
93 operator<<(std::ostream &target, const QString &str) 82 operator<<(std::ostream &target, const QString &str)
94 { 83 {
95 return target << str.toStdString(); 84 return target << str.toStdString();