Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

Commit

Permalink
fix: Make logMessageHandler thread-safe
Browse files Browse the repository at this point in the history
Make use of mutexes and atomic operations to make logging thread-safe
and deadlock free.
  • Loading branch information
sudden6 committed Mar 26, 2016
1 parent c1e2a3c commit a7ffc08
Showing 1 changed file with 49 additions and 13 deletions.
62 changes: 49 additions & 13 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QMutex>
#include <QFontDatabase>
#include <QMutexLocker>

Expand All @@ -45,7 +46,9 @@
#endif

#ifdef LOG_TO_FILE
static FILE * logFileFile = nullptr;
static QAtomicPointer<FILE> logFileFile = nullptr;
static QList<QByteArray>* logBuffer = new QList<QByteArray>(); //Store log messages until log file opened
QMutex* logBufferMutex = new QMutex();
#endif

void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QString& msg)
Expand Down Expand Up @@ -80,16 +83,40 @@ void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QSt
fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), stderr);

#ifdef LOG_TO_FILE
if (logFileFile == nullptr)
return;
fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), logFileFile);
fflush(logFileFile);
FILE * logFilePtr = logFileFile.load(); // atomically load the file pointer
if (!logFilePtr)
{
logBufferMutex->lock();
if(logBuffer)
{
logBuffer->append(LogMsgBytes);
}
logBufferMutex->unlock();
}
else
{
logBufferMutex->lock();
if(logBuffer)
{
// empty logBuffer to file
foreach(QByteArray msg, *logBuffer)
{
fwrite(msg.constData(), 1, msg.size(), logFilePtr);
}

delete logBuffer; // no longer needed
logBuffer = nullptr;
}
logBufferMutex->unlock();

fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), logFilePtr);
fflush(logFilePtr);
}
#endif
}

int main(int argc, char *argv[])
{
qSetMessagePattern("%{time [HH:mm:ss.zzz]} %{file}:%{line} %{type} %{message}");
qInstallMessageHandler(logMessageHandler);

QApplication a(argc, argv);
Expand Down Expand Up @@ -130,7 +157,7 @@ int main(int argc, char *argv[])
QDir(logFileDir).mkpath(".");

QString logfile = logFileDir + "qtox.log";
logFileFile = fopen(logfile.toLocal8Bit().constData(), "a");
FILE * tmpLogFilePtr = fopen(logfile.toLocal8Bit().constData(), "a");

// Trim log file if over 1MB
if (QFileInfo(logfile).size() > 1000000)
Expand All @@ -141,16 +168,25 @@ int main(int argc, char *argv[])

// Check if log.1 already exists, and if so, delete it
if (dir.remove(logFileDir + "qtox.log.1"))
qDebug() << "Removed log successfully";
qDebug() << "Removed old log successfully";
else
qDebug() << "Unable to remove old log file";
qWarning() << "Unable to remove old log file";

if(!dir.rename(logFileDir + "qtox.log", logFileDir + "qtox.log.1"))
qCritical() << "Unable to move logs";

dir.rename(logFileDir + "qtox.log", logFileDir + "qtox.log.1");
// close old logfile
if(tmpLogFilePtr)
fclose(tmpLogFilePtr);

FILE * oldLogFileFile = logFileFile;
logFileFile = fopen(logfile.toLocal8Bit().constData(), "a");
fclose(oldLogFileFile);
// open a new logfile
tmpLogFilePtr = fopen(logfile.toLocal8Bit().constData(), "a");
}

if(!tmpLogFilePtr)
qCritical() << "Couldn't open logfile" << logfile;

logFileFile.store(tmpLogFilePtr); // atomically set the logFile
#endif

// Windows platform plugins DLL hell fix
Expand Down

0 comments on commit a7ffc08

Please sign in to comment.