Safely close database connections and delete backends

Also fix NewClosure leak caused by disconnected object signals
This commit is contained in:
Jonas Kvinge
2019-07-24 19:16:51 +02:00
parent bd78e8c275
commit b5eb13449b
47 changed files with 490 additions and 53 deletions

View File

@@ -20,8 +20,11 @@
#include <memory>
#include <functional>
#include <assert.h>
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QMutex>
#include <QIODevice>
#include <QDir>
@@ -56,7 +59,36 @@ using std::shared_ptr;
const int PlaylistBackend::kSongTableJoins = 2;
PlaylistBackend::PlaylistBackend(Application *app, QObject *parent)
: QObject(parent), app_(app), db_(app_->database()) {}
: QObject(parent), app_(app), db_(app_->database()), original_thread_(nullptr) {
original_thread_ = thread();
}
PlaylistBackend::~PlaylistBackend() {}
void PlaylistBackend::Close() {
if (db_) {
QMutexLocker l(db_->Mutex());
db_->Close();
}
}
void PlaylistBackend::ExitAsync() {
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
}
void PlaylistBackend::Exit() {
assert(QThread::currentThread() == thread());
Close();
moveToThread(original_thread_);
emit ExitFinished();
}
PlaylistBackend::PlaylistList PlaylistBackend::GetAllPlaylists() {
return GetPlaylists(GetPlaylists_All);
@@ -157,6 +189,10 @@ QSqlQuery PlaylistBackend::GetPlaylistRows(int playlist) {
q.bindValue(":playlist", playlist);
q.exec();
if (QThread::currentThread() != thread() && QThread::currentThread() != qApp->thread()) {
db_->Close();
}
return q;
}

View File

@@ -39,6 +39,7 @@
#include "collection/sqlrow.h"
#include "playlistitem.h"
class QThread;
class Application;
class Database;
@@ -47,6 +48,7 @@ class PlaylistBackend : public QObject {
public:
Q_INVOKABLE PlaylistBackend(Application *app, QObject *parent = nullptr);
~PlaylistBackend();
struct Playlist {
Playlist() : id(-1), favorite(false), last_played(0) {}
@@ -62,6 +64,9 @@ class PlaylistBackend : public QObject {
static const int kSongTableJoins;
void Close();
void ExitAsync();
PlaylistList GetAllPlaylists();
PlaylistList GetAllOpenPlaylists();
PlaylistList GetAllFavoritePlaylists();
@@ -82,8 +87,12 @@ class PlaylistBackend : public QObject {
Application *app() const { return app_; }
public slots:
void Exit();
void SavePlaylist(int playlist, const PlaylistItemList &items, int last_played);
signals:
void ExitFinished();
private:
struct NewSongFromQueryState {
QHash<QString, SongList> cached_cues_;
@@ -105,6 +114,7 @@ class PlaylistBackend : public QObject {
Application *app_;
Database *db_;
QThread *original_thread_;
};
#endif // PLAYLISTBACKEND_H

View File

@@ -22,6 +22,7 @@
#include "config.h"
#include <QtGlobal>
#include <QApplication>
#include <QObject>
#include <QWidget>
#include <QtConcurrentRun>
@@ -363,6 +364,10 @@ TagCompletionModel::TagCompletionModel(CollectionBackend *backend, Playlist::Col
setStringList(backend->GetAll(col));
}
if (QThread::currentThread() != backend->thread() && QThread::currentThread() != qApp->thread()) {
backend->Close();
}
}
QString TagCompletionModel::database_column(Playlist::Column column) {

View File

@@ -80,6 +80,7 @@ class PlaylistHeader;
class PlaylistProxyStyle : public QProxyStyle {
public:
PlaylistProxyStyle(QStyle *base);
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;