From 47874b37068290dda8705b5d47e0f320f3949a6d Mon Sep 17 00:00:00 2001 From: Albert S Date: Sat, 27 Aug 2022 10:21:58 +0200 Subject: [PATCH] gui: ipcworker,ipcserver: Refactor Crashes were observed, faulting in libQtNetwork. Those were rather rare. We also have no traces. Probably depends on some order signal/slots were processed. Remove shared states between connections, such as the IPCPreviewWorker and socket instance in IPCServer. --- gui/ipcpreviewworker.cpp | 44 +++++++++++++++++++++++++++++++++++----- gui/ipcpreviewworker.h | 14 ++++++++++--- gui/ipcserver.cpp | 29 ++++++++++++-------------- gui/ipcserver.h | 3 --- 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/gui/ipcpreviewworker.cpp b/gui/ipcpreviewworker.cpp index 8d39391..7b11970 100644 --- a/gui/ipcpreviewworker.cpp +++ b/gui/ipcpreviewworker.cpp @@ -1,16 +1,50 @@ #include #include "ipcpreviewworker.h" #include "previewgeneratormapfunctor.h" -IPCPreviewWorker::IPCPreviewWorker() +IPCPreviewWorker::IPCPreviewWorker(QLocalSocket *peer) { + this->peer = peer; this->connect(&previewWorkerWatcher, &QFutureWatcher::resultReadyAt, this, - [this](int index) { emit previewGenerated(previewWorkerWatcher.resultAt(index)); }); - connect(&previewWorkerWatcher, &QFutureWatcher::finished, this, [this] { emit finished(); }); + [this](int index) + { + if(this->peer != nullptr) + { + QDataStream stream{this->peer}; + stream << previewWorkerWatcher.resultAt(index); + this->peer->flush(); + } + }); + connect(&previewWorkerWatcher, &QFutureWatcher::finished, this, &IPCPreviewWorker::shutdownSocket); + connect(this->peer, &QLocalSocket::disconnected, this, &IPCPreviewWorker::shutdownSocket); } -void IPCPreviewWorker::start(RenderConfig config, const QVector &targets, QLocalSocket *peer) +void IPCPreviewWorker::shutdownSocket() +{ + if(cleaned) + { + return; + } + cleaned = true; + if(this->peer != nullptr) + { + if(this->peer->state() == QLocalSocket::ConnectedState) + { + this->peer->flush(); + this->peer->waitForBytesWritten(); + this->peer->disconnectFromServer(); + if(this->peer->state() != QLocalSocket::UnconnectedState) + { + this->peer->waitForDisconnected(); + } + } + delete this->peer; + this->peer = nullptr; + } + emit finished(); +} + +void IPCPreviewWorker::start(RenderConfig config, const QVector &targets) { - stop(); auto mapFunctor = PreviewGeneratorMapFunctor(); mapFunctor.setRenderConfig(config); diff --git a/gui/ipcpreviewworker.h b/gui/ipcpreviewworker.h index cc7959c..52f5548 100644 --- a/gui/ipcpreviewworker.h +++ b/gui/ipcpreviewworker.h @@ -11,13 +11,21 @@ class IPCPreviewWorker : public QObject Q_OBJECT private: QFutureWatcher previewWorkerWatcher; + QLocalSocket *peer; + bool cleaned = false; public: - IPCPreviewWorker(); - void start(RenderConfig config, const QVector &targets, QLocalSocket *peer); + IPCPreviewWorker(QLocalSocket *peer); + void start(RenderConfig config, const QVector &targets); void stop(); + ~IPCPreviewWorker() + { + delete this->peer; + } + private slots: + void shutdownSocket(); + signals: - void previewGenerated(QByteArray); void finished(); }; diff --git a/gui/ipcserver.cpp b/gui/ipcserver.cpp index 89d82aa..484bee9 100644 --- a/gui/ipcserver.cpp +++ b/gui/ipcserver.cpp @@ -18,8 +18,6 @@ IpcServer::IpcServer() /* Only 1, we are doing work for the GUI, not a service for general availability */ this->spawningServer.setMaxPendingConnections(1); connect(&this->spawningServer, &QLocalServer::newConnection, this, &IpcServer::spawnerNewConnection); - connect(&this->previewWorker, &IPCPreviewWorker::previewGenerated, this, &IpcServer::handlePreviewGenerated); - connect(&this->previewWorker, &IPCPreviewWorker::finished, this, [this] { this->currentSocket->flush(); }); } bool IpcServer::startSpawner(QString socketPath) @@ -31,8 +29,6 @@ bool IpcServer::startSpawner(QString socketPath) void IpcServer::spawnerNewConnection() { QLocalSocket *socket = this->spawningServer.nextPendingConnection(); - connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater); - this->currentSocket = socket; if(socket != nullptr) { if(!socket->waitForReadyRead()) @@ -53,21 +49,22 @@ void IpcServer::spawnerNewConnection() stream.startTransaction(); stream >> renderConfig >> targets; } while(!stream.commitTransaction() && socket->state() == QLocalSocket::ConnectedState); - - stream << targets.count(); - socket->flush(); - previewWorker.start(renderConfig, targets, socket); + if(socket->state() == QLocalSocket::ConnectedState) + { + stream << targets.count(); + socket->flush(); + IPCPreviewWorker *previewWorker = new IPCPreviewWorker(socket); + connect(previewWorker, &IPCPreviewWorker::finished, this, [previewWorker] { delete previewWorker; }); + previewWorker->start(renderConfig, targets); + } + else + { + delete socket; + } } if(command == StopGeneratePreviews) { - previewWorker.stop(); + /* TODO: implement */ } } } - -void IpcServer::handlePreviewGenerated(QByteArray ba) -{ - QDataStream stream{this->currentSocket}; - stream << ba; - this->currentSocket->flush(); -} diff --git a/gui/ipcserver.h b/gui/ipcserver.h index 572ec00..ebf59cb 100644 --- a/gui/ipcserver.h +++ b/gui/ipcserver.h @@ -10,13 +10,10 @@ class IpcServer : public QObject { Q_OBJECT private: - IPCPreviewWorker previewWorker; QLocalServer spawningServer; - QLocalSocket *currentSocket = nullptr; SaveFileResult addFile(QString file); private slots: void spawnerNewConnection(); - void handlePreviewGenerated(QByteArray ba); public: IpcServer();