Procházet zdrojové kódy

protect all access to shared data by mutexes

separate public methods that must lock and private methods that must not
lock

will avoid deadlock or unprotected accesses

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
Matthieu Gallien před 2 roky
rodič
revize
9c8b624ef7
2 změnil soubory, kde provedl 79 přidání a 64 odebrání
  1. 76 63
      src/libsync/logger.cpp
  2. 3 1
      src/libsync/logger.h

+ 76 - 63
src/libsync/logger.cpp

@@ -34,9 +34,38 @@
 #endif
 
 namespace {
+
 constexpr int CrashLogSize = 20;
 constexpr int MaxLogSizeBytes = 1024 * 512;
+
+static bool compressLog(const QString &originalName, const QString &targetName)
+{
+#ifdef ZLIB_FOUND
+    QFile original(originalName);
+    if (!original.open(QIODevice::ReadOnly))
+        return false;
+    auto compressed = gzopen(targetName.toUtf8(), "wb");
+    if (!compressed) {
+        return false;
+    }
+
+    while (!original.atEnd()) {
+        auto data = original.read(1024 * 1024);
+        auto written = gzwrite(compressed, data.data(), data.size());
+        if (written != data.size()) {
+            gzclose(compressed);
+            return false;
+        }
+    }
+    gzclose(compressed);
+    return true;
+#else
+    return false;
+#endif
 }
+
+}
+
 namespace OCC {
 
 Logger *Logger::instance()
@@ -118,23 +147,23 @@ void Logger::doLog(QtMsgType type, const QMessageLogContext &ctx, const QString
     cout << msg << endl;
 #endif
     {
+        QMutexLocker lock(&_mutex);
+
         if (_logFile.size() >= MaxLogSizeBytes) {
-            close();
-            enterNextLogFile();
+            closeNoLock();
+            enterNextLogFileNoLock();
         }
 
         _crashLogIndex = (_crashLogIndex + 1) % CrashLogSize;
         _crashLog[_crashLogIndex] = msg;
 
-        QMutexLocker lock(&_mutex);
-
         if (_logstream) {
             (*_logstream) << msg << Qt::endl;
             if (_doFileFlush)
                 _logstream->flush();
         }
         if (type == QtFatalMsg) {
-            close();
+            closeNoLock();
 #if defined(Q_OS_WIN)
             // Make application terminate in a way that can be caught by the crash reporter
             Utility::crash();
@@ -144,9 +173,8 @@ void Logger::doLog(QtMsgType type, const QMessageLogContext &ctx, const QString
     emit logWindowLog(msg);
 }
 
-void Logger::close()
+void Logger::closeNoLock()
 {
-    QMutexLocker lock(&_mutex);
     dumpCrashLog();
     if (_logstream)
     {
@@ -158,40 +186,14 @@ void Logger::close()
 
 QString Logger::logFile() const
 {
+    QMutexLocker locker(&_mutex);
     return _logFile.fileName();
 }
 
 void Logger::setLogFile(const QString &name)
 {
     QMutexLocker locker(&_mutex);
-    if (_logstream) {
-        _logstream.reset(nullptr);
-        _logFile.close();
-    }
-
-    if (name.isEmpty()) {
-        return;
-    }
-
-    bool openSucceeded = false;
-    if (name == QLatin1String("-")) {
-        openSucceeded = _logFile.open(stdout, QIODevice::WriteOnly);
-    } else {
-        _logFile.setFileName(name);
-        openSucceeded = _logFile.open(QIODevice::WriteOnly);
-    }
-
-    if (!openSucceeded) {
-        locker.unlock(); // Just in case postGuiMessage has a qDebug()
-        postGuiMessage(tr("Error"),
-            QString(tr("<nobr>File \"%1\"<br/>cannot be opened for writing.<br/><br/>"
-                       "The log output <b>cannot</b> be saved!</nobr>"))
-                .arg(name));
-        return;
-    }
-
-    _logstream.reset(new QTextStream(&_logFile));
-    _logstream->setCodec(QTextCodec::codecForName("UTF-8"));
+    setLogFileNoLock(name);
 }
 
 void Logger::setLogExpire(int expire)
@@ -276,33 +278,7 @@ void Logger::dumpCrashLog()
     }
 }
 
-static bool compressLog(const QString &originalName, const QString &targetName)
-{
-#ifdef ZLIB_FOUND
-    QFile original(originalName);
-    if (!original.open(QIODevice::ReadOnly))
-        return false;
-    auto compressed = gzopen(targetName.toUtf8(), "wb");
-    if (!compressed) {
-        return false;
-    }
-
-    while (!original.atEnd()) {
-        auto data = original.read(1024 * 1024);
-        auto written = gzwrite(compressed, data.data(), data.size());
-        if (written != data.size()) {
-            gzclose(compressed);
-            return false;
-        }
-    }
-    gzclose(compressed);
-    return true;
-#else
-    return false;
-#endif
-}
-
-void Logger::enterNextLogFile()
+void Logger::enterNextLogFileNoLock()
 {
     if (!_logDirectory.isEmpty()) {
 
@@ -335,7 +311,7 @@ void Logger::enterNextLogFile()
         newLogName.append("." + QString::number(maxNumber + 1));
 
         auto previousLog = _logFile.fileName();
-        setLogFile(dir.filePath(newLogName));
+        setLogFileNoLock(dir.filePath(newLogName));
 
         // Compress the previous log file. On a restart this can be the most recent
         // log file.
@@ -353,4 +329,41 @@ void Logger::enterNextLogFile()
     }
 }
 
+void Logger::setLogFileNoLock(const QString &name)
+{
+    if (_logstream) {
+        _logstream.reset(nullptr);
+        _logFile.close();
+    }
+
+    if (name.isEmpty()) {
+        return;
+    }
+
+    bool openSucceeded = false;
+    if (name == QLatin1String("-")) {
+        openSucceeded = _logFile.open(stdout, QIODevice::WriteOnly);
+    } else {
+        _logFile.setFileName(name);
+        openSucceeded = _logFile.open(QIODevice::WriteOnly);
+    }
+
+    if (!openSucceeded) {
+        postGuiMessage(tr("Error"),
+                       QString(tr("<nobr>File \"%1\"<br/>cannot be opened for writing.<br/><br/>"
+                                  "The log output <b>cannot</b> be saved!</nobr>"))
+                           .arg(name));
+        return;
+    }
+
+    _logstream.reset(new QTextStream(&_logFile));
+    _logstream->setCodec(QTextCodec::codecForName("UTF-8"));
+}
+
+void Logger::enterNextLogFile()
+{
+    QMutexLocker locker(&_mutex);
+    enterNextLogFileNoLock();
+}
+
 } // namespace OCC

+ 3 - 1
src/libsync/logger.h

@@ -96,8 +96,10 @@ private:
     Logger(QObject *parent = nullptr);
     ~Logger() override;
 
-    void close();
+    void closeNoLock();
     void dumpCrashLog();
+    void enterNextLogFileNoLock();
+    void setLogFileNoLock(const QString &name);
 
     QFile _logFile;
     bool _doFileFlush = false;