make cookie jar thread safe, make qsettings thread safe

This commit is contained in:
Martin Rotter 2023-01-05 09:44:46 +01:00
parent e87ecd91f2
commit 7e14390e2c
6 changed files with 33 additions and 25 deletions

View file

@ -60,7 +60,7 @@
<content_rating type="oars-1.0" /> <content_rating type="oars-1.0" />
<content_rating type="oars-1.1" /> <content_rating type="oars-1.1" />
<releases> <releases>
<release version="4.2.7" date="2023-01-04" /> <release version="4.2.7" date="2023-01-05" />
</releases> </releases>
<provides> <provides>
<binary>@APP_LOW_NAME@</binary> <binary>@APP_LOW_NAME@</binary>

View file

@ -82,23 +82,14 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
qDebugNN << LOGSEC_FEEDDOWNLOADER << "No feeds to update in worker thread, aborting update."; qDebugNN << LOGSEC_FEEDDOWNLOADER << "No feeds to update in worker thread, aborting update.";
} }
else { else {
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Starting feed updates from worker in thread: '" << QThread::currentThreadId() qDebugNN << LOGSEC_FEEDDOWNLOADER << "Starting feed updates from worker in thread"
<< "'."; << QUOTE_W_SPACE_DOT(QThread::currentThreadId());
// Job starts now. // Job starts now.
emit updateStarted(); emit updateStarted();
QSet<CacheForServiceRoot*> caches; QSet<CacheForServiceRoot*> caches;
QMultiHash<ServiceRoot*, Feed*> feeds_per_root; QMultiHash<ServiceRoot*, Feed*> feeds_per_root;
// 1. key - account.
// 2. key - feed custom ID.
// 3. key - msg state.
QHash<ServiceRoot*, QHash<QString, QHash<ServiceRoot::BagOfMessages, QStringList>>> stated_messages;
// 1. key - account.
// 2. key - label custom ID.
QHash<ServiceRoot*, QHash<QString, QStringList>> tagged_messages;
for (auto* fd : feeds) { for (auto* fd : feeds) {
CacheForServiceRoot* fd_cache = fd->getParentServiceRoot()->toCache(); CacheForServiceRoot* fd_cache = fd->getParentServiceRoot()->toCache();
@ -112,21 +103,17 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
synchronizeAccountCaches(caches.values(), false); synchronizeAccountCaches(caches.values(), false);
auto roots = feeds_per_root.uniqueKeys(); auto roots = feeds_per_root.uniqueKeys();
bool is_main_thread = QThread::currentThread() == qApp->thread(); QSqlDatabase database = qApp->database()->driver()->threadSafeConnection(metaObject()->className());
QSqlDatabase database = is_main_thread ? qApp->database()->driver()->connection(metaObject()->className())
: qApp->database()->driver()->connection(QSL("feed_upd"));
for (auto* rt : roots) { for (auto* rt : roots) {
auto fds = feeds_per_root.values(rt); auto fds = feeds_per_root.values(rt);
QHash<QString, QStringList> per_acc_tags;
QHash<QString, QHash<ServiceRoot::BagOfMessages, QStringList>> per_acc_states;
// Obtain lists of local IDs. // Obtain lists of local IDs.
if (rt->wantsBaggedIdsOfExistingMessages()) { if (rt->wantsBaggedIdsOfExistingMessages()) {
// Tags per account. // Tags per account.
auto per_acc_tags = DatabaseQueries::bagsOfMessages(database, rt->labelsNode()->labels()); per_acc_tags = DatabaseQueries::bagsOfMessages(database, rt->labelsNode()->labels());
tagged_messages.insert(rt, per_acc_tags);
QHash<QString, QHash<ServiceRoot::BagOfMessages, QStringList>> per_acc_states;
// This account has activated intelligent downloading of messages. // This account has activated intelligent downloading of messages.
// Prepare bags. // Prepare bags.
@ -151,8 +138,6 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
m_feeds.append(fu); m_feeds.append(fu);
} }
stated_messages.insert(rt, per_acc_states);
} }
else { else {
for (Feed* fd : fds) { for (Feed* fd : fds) {
@ -166,7 +151,7 @@ void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
} }
try { try {
rt->aboutToBeginFeedFetching(fds, stated_messages.value(rt), tagged_messages.value(rt)); rt->aboutToBeginFeedFetching(fds, per_acc_states, per_acc_tags);
} }
catch (const ApplicationException& ex) { catch (const ApplicationException& ex) {
// Common error showed, all feeds from the root are errored now! // Common error showed, all feeds from the root are errored now!

View file

@ -438,7 +438,8 @@ DVALUE(QStringList) Browser::ExternalToolsDef = QStringList();
DKEY CategoriesExpandStates::ID = "categories_expand_states"; DKEY CategoriesExpandStates::ID = "categories_expand_states";
Settings::Settings(const QString& file_name, Format format, SettingsProperties::SettingsType type, QObject* parent) Settings::Settings(const QString& file_name, Format format, SettingsProperties::SettingsType type, QObject* parent)
: QSettings(file_name, format, parent), m_initializationStatus(type) { : QSettings(file_name, format, parent), m_lock(QReadWriteLock(QReadWriteLock::RecursionMode::Recursive)),
m_initializationStatus(type) {
Messages::PreviewerFontStandardDef = QFont(QApplication::font().family(), 12).toString(); Messages::PreviewerFontStandardDef = QFont(QApplication::font().family(), 12).toString();
} }

View file

@ -14,7 +14,9 @@
#include <QColor> #include <QColor>
#include <QDateTime> #include <QDateTime>
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QReadWriteLock>
#include <QStringList> #include <QStringList>
#include <QWriteLocker>
#define KEY extern const QString #define KEY extern const QString
#define DKEY const QString #define DKEY const QString
@ -518,12 +520,13 @@ class Settings : public QSettings {
static SettingsProperties determineProperties(); static SettingsProperties determineProperties();
private: private:
// Constructor.
explicit Settings(const QString& file_name, explicit Settings(const QString& file_name,
Format format, Format format,
SettingsProperties::SettingsType type, SettingsProperties::SettingsType type,
QObject* parent = nullptr); QObject* parent = nullptr);
private:
mutable QReadWriteLock m_lock;
SettingsProperties::SettingsType m_initializationStatus; SettingsProperties::SettingsType m_initializationStatus;
}; };
@ -545,10 +548,12 @@ inline QVariant Settings::value(const QString& section, const QString& key, cons
} }
inline void Settings::setValue(const QString& section, const QString& key, const QVariant& value) { inline void Settings::setValue(const QString& section, const QString& key, const QVariant& value) {
QWriteLocker lck(&m_lock);
QSettings::setValue(QString(QSL("%1/%2")).arg(section, key), value); QSettings::setValue(QString(QSL("%1/%2")).arg(section, key), value);
} }
inline void Settings::setValue(const QString& key, const QVariant& value) { inline void Settings::setValue(const QString& key, const QVariant& value) {
QWriteLocker lck(&m_lock);
QSettings::setValue(key, value); QSettings::setValue(key, value);
} }
@ -557,6 +562,8 @@ inline bool Settings::contains(const QString& section, const QString& key) const
} }
inline void Settings::remove(const QString& section, const QString& key) { inline void Settings::remove(const QString& section, const QString& key) {
QWriteLocker lck(&m_lock);
if (key.isEmpty()) { if (key.isEmpty()) {
beginGroup(section); beginGroup(section);
QSettings::remove({}); QSettings::remove({});

View file

@ -120,10 +120,12 @@ void CookieJar::saveCookies() {
} }
QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl& url) const { QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl& url) const {
QReadLocker l(&m_lock);
return QNetworkCookieJar::cookiesForUrl(url); return QNetworkCookieJar::cookiesForUrl(url);
} }
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie>& cookie_list, const QUrl& url) { bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie>& cookie_list, const QUrl& url) {
QWriteLocker l(&m_lock);
return QNetworkCookieJar::setCookiesFromUrl(cookie_list, url); return QNetworkCookieJar::setCookiesFromUrl(cookie_list, url);
} }
@ -188,11 +190,13 @@ bool CookieJar::insertCookie(const QNetworkCookie& cookie) {
return {}; return {};
} }
else { else {
QWriteLocker l(&m_lock);
return insertCookieInternal(cookie, false, true); return insertCookieInternal(cookie, false, true);
} }
} }
bool CookieJar::deleteCookie(const QNetworkCookie& cookie) { bool CookieJar::deleteCookie(const QNetworkCookie& cookie) {
QWriteLocker l(&m_lock);
return deleteCookieInternal(cookie, false); return deleteCookieInternal(cookie, false);
} }
@ -206,5 +210,12 @@ void CookieJar::updateSettings() {
} }
bool CookieJar::updateCookie(const QNetworkCookie& cookie) { bool CookieJar::updateCookie(const QNetworkCookie& cookie) {
QWriteLocker l(&m_lock);
return updateCookieInternal(cookie, false); return updateCookieInternal(cookie, false);
} }
/*
bool CookieJar::validateCookie(const QNetworkCookie &cookie, const QUrl &url) const {
return QNetworkCookieJar::validateCookie(cookie, url);
}
*/

View file

@ -5,6 +5,8 @@
#include <QNetworkCookieJar> #include <QNetworkCookieJar>
#include <QReadWriteLock>
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
class QWebEngineCookieStore; class QWebEngineCookieStore;
#endif #endif
@ -18,6 +20,7 @@ class CookieJar : public QNetworkCookieJar {
virtual bool insertCookie(const QNetworkCookie& cookie); virtual bool insertCookie(const QNetworkCookie& cookie);
virtual bool updateCookie(const QNetworkCookie& cookie); virtual bool updateCookie(const QNetworkCookie& cookie);
virtual bool deleteCookie(const QNetworkCookie& cookie); virtual bool deleteCookie(const QNetworkCookie& cookie);
// virtual bool validateCookie(const QNetworkCookie& cookie, const QUrl& url) const;
void updateSettings(); void updateSettings();
@ -37,6 +40,7 @@ class CookieJar : public QNetworkCookieJar {
QWebEngineCookieStore* m_webEngineCookies; QWebEngineCookieStore* m_webEngineCookies;
#endif #endif
mutable QReadWriteLock m_lock{QReadWriteLock::RecursionMode::Recursive};
bool m_ignoreAllCookies; bool m_ignoreAllCookies;
}; };