fix: 尝试修复 ISSUE #I68I8W 安装结束时随机崩溃问题

暂时未知,目前怀疑安装结束后,DownloadItem 触发 finished() 信号,在详情页槽函数中执行 disconnect 操作时导致崩溃

Log: 去除 disconnect 操作;修改可能造成问题的控件指针获取方式;修复多线程执行下载安装操作时跨线程相关警告

* 该提交可能存在严重问题,建议多进行测试;如果存在问题,及时 revert 该提交
This commit is contained in:
zty199 2023-02-03 01:35:15 +08:00
parent eaf268a10d
commit cb093dcc2b
7 changed files with 163 additions and 123 deletions

View File

@ -145,17 +145,19 @@ void DownloadController::startDownload(const QString &url)
command.append(aria2NoSeeds.toUtf8()); command.append(aria2NoSeeds.toUtf8());
} }
qDebug() << command; qDebug() << command;
auto cmd = new QProcess(this);
cmd->setProcessChannelMode(QProcess::MergedChannels);
cmd->setProgram("aria2c");
cmd->setArguments(command);
cmd->start();
cmd->waitForStarted(); //等待启动完成
QObject::connect(cmd, &QProcess::readyReadStandardOutput, [&]() bool downloadSuccess = true;
QProcess cmd;
cmd.setProcessChannelMode(QProcess::MergedChannels);
cmd.setProgram("aria2c");
cmd.setArguments(command);
cmd.start();
cmd.waitForStarted(-1); //等待启动完成
connect(&cmd, &QProcess::readyReadStandardOutput, [&]()
{ {
//通过读取输出计算下载速度 //通过读取输出计算下载速度
QString message = cmd->readAllStandardOutput().data(); QString message = cmd.readAllStandardOutput().data();
// qDebug() << message; // qDebug() << message;
message = message.replace(" ", ""); message = message.replace(" ", "");
QStringList list; QStringList list;
@ -195,17 +197,21 @@ void DownloadController::startDownload(const QString &url)
emit downloadProcess(speedInfo, downloadSizeRecord, fileSize); emit downloadProcess(speedInfo, downloadSizeRecord, fileSize);
} }
}); });
QObject::connect(cmd, &QProcess::readyReadStandardError, [&]() connect(&cmd, &QProcess::readyReadStandardError, [&]()
{ {
emit errorOccur(cmd->readAllStandardError().data()); emit errorOccur(cmd.readAllStandardError().data());
return; downloadSuccess = false;
cmd.close();
}); });
auto pidNumber = cmd->processId(); pidNumber = cmd.processId();
this->pidNumber = pidNumber;
while (cmd->waitForFinished(-1)) cmd.waitForFinished(-1);
cmd.close();
if(!downloadSuccess)
{ {
continue; return;
} }
// 统计下载量 // 统计下载量
@ -218,7 +224,7 @@ void DownloadController::startDownload(const QString &url)
mailProcess.start(SenderdPath.toUtf8(), QStringList() << metaUrl << "HD70642"); mailProcess.start(SenderdPath.toUtf8(), QStringList() << metaUrl << "HD70642");
mailProcess.waitForStarted(); mailProcess.waitForStarted();
mailProcess.waitForFinished(3000); mailProcess.waitForFinished(3000);
mailProcess.deleteLater(); mailProcess.close();
emit downloadFinished(); }); emit downloadFinished(); });
} }

View File

@ -21,7 +21,7 @@ public:
private: private:
int threadNum; int threadNum;
int pidNumber = -1; qint64 pidNumber = -1;
QString filename; QString filename;
qint64 fileSize; qint64 fileSize;
QVector<QPair<qint64, qint64>> ranges; QVector<QPair<qint64, qint64>> ranges;

View File

@ -291,34 +291,39 @@ void AppIntoPage::initConnections()
void AppIntoPage::isDownloading(const QUrl &url) void AppIntoPage::isDownloading(const QUrl &url)
{ {
if (dw->getUrlList().lastIndexOf(url) == -1) int index = dw->getUrlList().lastIndexOf(url);
if (index == -1)
{ {
ui->downloadButton->setEnabled(true); ui->downloadButton->setEnabled(true);
return; return;
} }
else
DownloadItem *item = dw->getDIList().at(index);
if (item == nullptr)
{ {
ui->downloadButton->setEnabled(false); ui->downloadButton->setEnabled(true);
return;
} }
ui->downloadButton->setEnabled(false);
ui->pushButton_3->hide(); ui->pushButton_3->hide();
if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 2) if (item->download == 2)
{ {
ui->downloadButton->setEnabled(true); ui->downloadButton->setEnabled(true);
ui->downloadButton->setText(tr("Download")); ui->downloadButton->setText(tr("Download"));
} }
if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 1) if (item->download == 1)
{ {
ui->downloadButton->setEnabled(true); ui->downloadButton->setEnabled(true);
ui->downloadButton->setText(tr("Install")); ui->downloadButton->setText(tr("Install"));
} }
if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->isInstall) if (item->isInstall)
{ {
ui->downloadButton->setEnabled(false); ui->downloadButton->setEnabled(false);
ui->downloadButton->setText(tr("Installing")); ui->downloadButton->setText(tr("Installing"));
return; return;
} }
if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 3) if (item->download == 3)
{ {
ui->downloadButton->setEnabled(true); ui->downloadButton->setEnabled(true);
ui->downloadButton->setText(tr("Reinstall")); ui->downloadButton->setText(tr("Reinstall"));
@ -368,32 +373,39 @@ void AppIntoPage::setAppinfoTags(const QStringList &tagList)
void AppIntoPage::on_downloadButton_clicked() void AppIntoPage::on_downloadButton_clicked()
{ {
QString downloadUrl = SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString();
if (ui->downloadButton->text() == tr("Install")) if (ui->downloadButton->text() == tr("Install"))
{ {
dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())]->install(0); DownloadItem *item = dw->getDIList()[dw->getUrlList().lastIndexOf(downloadUrl)];
isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); if (item == nullptr)
connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, [=]()
{ {
isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); return;
disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, nullptr, nullptr); }); }
connect(item, &DownloadItem::finished, [=]() { isDownloading(downloadUrl); });
item->install(0);
isDownloading(downloadUrl);
return; return;
} }
emit clickedDownloadBtn(); emit clickedDownloadBtn();
dw->addItem(info["Name"].toString(), info["Filename"].toString(), info["Pkgname"].toString(), iconpixmap, SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); DownloadItem *item = dw->addItem(info["Name"].toString(), info["Filename"].toString(), info["Pkgname"].toString(), iconpixmap, downloadUrl);
if (item == nullptr)
{
return;
}
if (ui->downloadButton->text() == tr("Reinstall")) if (ui->downloadButton->text() == tr("Reinstall"))
{ {
dw->getDIList()[dw->allDownload - 1]->reinstall = true; item->reinstall = true;
} }
ui->downloadButton->setEnabled(false); ui->downloadButton->setEnabled(false);
connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, [=]() connect(item, &DownloadItem::finished, [=]() { isDownloading(downloadUrl); });
{
isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString());
disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, nullptr, nullptr); });
isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); isDownloading(downloadUrl);
} }
void AppIntoPage::on_pushButton_3_clicked() void AppIntoPage::on_pushButton_3_clicked()

View File

@ -105,6 +105,44 @@ void DownloadItem::install(int t)
ui->label_2->setToolTip(tr("Installing")); ui->label_2->setToolTip(tr("Installing"));
QtConcurrent::run([=]() QtConcurrent::run([=]()
{
slotAsyncInstall(t);
});
qDebug() << ui->label_filename->text().toUtf8();
}
}
void DownloadItem::on_pushButton_install_clicked()
{
DownloadItem::install(0);
}
void DownloadItem::on_pushButton_2_clicked()
{
ui->label_2->setText(tr("Download canceled"));
ui->label_2->setToolTip(tr("Download canceled"));
download = 2;
ui->pushButton_2->setEnabled(false);
ui->progressBar->hide();
close = true;
}
void DownloadItem::on_pushButton_3_clicked()
{
textbrowser->setLineWidth(0);
textbrowser->setText(out);
textbrowser->setMinimumHeight(500);
output_w->setMinimumHeight(600);
output_w->setAttribute(Qt::WA_TranslucentBackground);
output_w->setTitle(ui->label->text());
output_w->layout()->setMargin(20);
output_w->layout()->addWidget(textbrowser);
output_w->show();
}
void DownloadItem::slotAsyncInstall(int t)
{ {
QProcess installer; QProcess installer;
switch(t) switch(t)
@ -173,37 +211,5 @@ void DownloadItem::install(int t)
ui->widget_spinner->hide(); ui->widget_spinner->hide();
DownloadItem::isInstall = false; DownloadItem::isInstall = false;
emit finished(); }); emit finished();
// emit finished();
qDebug() << ui->label_filename->text().toUtf8();
}
}
void DownloadItem::on_pushButton_install_clicked()
{
DownloadItem::install(0);
}
void DownloadItem::on_pushButton_2_clicked()
{
ui->label_2->setText(tr("Download canceled"));
ui->label_2->setToolTip(tr("Download canceled"));
download = 2;
ui->pushButton_2->setEnabled(false);
ui->progressBar->hide();
close = true;
}
void DownloadItem::on_pushButton_3_clicked()
{
textbrowser->setLineWidth(0);
textbrowser->setText(out);
textbrowser->setMinimumHeight(500);
output_w->setMinimumHeight(600);
output_w->setAttribute(Qt::WA_TranslucentBackground);
output_w->setTitle(ui->label->text());
output_w->layout()->setMargin(20);
output_w->layout()->addWidget(textbrowser);
output_w->show();
} }

View File

@ -59,6 +59,8 @@ private slots:
void on_pushButton_2_clicked(); void on_pushButton_2_clicked();
void on_pushButton_3_clicked(); void on_pushButton_3_clicked();
void slotAsyncInstall(int t);
signals: signals:
void finished(); void finished();
}; };

View File

@ -54,36 +54,42 @@ DownloadListWidget::~DownloadListWidget()
{ {
if (downloadController) if (downloadController)
{ {
downloadController->disconnect();
downloadController->stopDownload(); downloadController->stopDownload();
downloadController->deleteLater();
} }
clearItem();
delete ui; delete ui;
} }
void DownloadListWidget::clearItem() void DownloadListWidget::clearItem()
{ {
ui->listWidget->vScrollBar->scrollTop(); // QListWidgetItem *item = nullptr;
int n = ui->listWidget->count(); // while ((item = ui->listWidget->takeItem(0)) != nullptr)
for (int i = 0; i < n; i++) // {
{ // QWidget *card = ui->listWidget->itemWidget(item);
QListWidgetItem *item = ui->listWidget->takeItem(0); // if (card)
QWidget *card = ui->listWidget->itemWidget(item); // {
delete card; // card->deleteLater();
card = NULL; // card = nullptr;
delete item; // }
item = NULL; // delete item;
} // item = nullptr;
// }
// ui->listWidget->vScrollBar->scrollTop();
ui->listWidget->clear(); ui->listWidget->clear();
} }
void DownloadListWidget::addItem(QString name, QString fileName, QString pkgName, const QPixmap icon, QString downloadurl) DownloadItem* DownloadListWidget::addItem(QString name, QString fileName, QString pkgName, const QPixmap icon, QString downloadurl)
{ {
if (fileName.isEmpty()) if (fileName.isEmpty())
{ {
return; return nullptr;
} }
urList.append(downloadurl); urList.append(downloadurl);
allDownload += 1; allDownload += 1;
DownloadItem *di = new DownloadItem(this); DownloadItem *di = new DownloadItem;
dlist << downloadurl; dlist << downloadurl;
downloaditemlist << di; downloaditemlist << di;
di->setName(name); di->setName(name);
@ -99,6 +105,8 @@ void DownloadListWidget::addItem(QString name, QString fileName, QString pkgName
nowDownload += 1; nowDownload += 1;
startRequest(urList.at(nowDownload - 1), fileName); // 进行链接请求 startRequest(urList.at(nowDownload - 1), fileName); // 进行链接请求
} }
return di;
} }
QList<DownloadItem *> DownloadListWidget::getDIList() QList<DownloadItem *> DownloadListWidget::getDIList()
@ -119,7 +127,13 @@ void DownloadListWidget::startRequest(QUrl url, QString fileName)
isdownload = true; isdownload = true;
downloaditemlist[allDownload - 1]->free = false; downloaditemlist[allDownload - 1]->free = false;
downloadController = new DownloadController(this); // 并发下载,在点击下载按钮的时候才会初始化 if (downloadController)
{
downloadController->disconnect();
downloadController->stopDownload();
downloadController->deleteLater();
}
downloadController = new DownloadController; // 并发下载,在点击下载按钮的时候才会初始化
connect(downloadController, &DownloadController::downloadProcess, this, &DownloadListWidget::updateDataReadProgress); connect(downloadController, &DownloadController::downloadProcess, this, &DownloadListWidget::updateDataReadProgress);
connect(downloadController, &DownloadController::downloadFinished, this, &DownloadListWidget::httpFinished); connect(downloadController, &DownloadController::downloadFinished, this, &DownloadListWidget::httpFinished);
// connect(downloadController, &DownloadController::errorOccur, this, [=](QString msg){this->sendNotification(msg);}); // connect(downloadController, &DownloadController::errorOccur, this, [=](QString msg){this->sendNotification(msg);});

View File

@ -20,7 +20,7 @@ class DownloadListWidget : public DBlurEffectWidget
Q_OBJECT Q_OBJECT
public: public:
void addItem(QString name, QString fileName, QString pkgName, const QPixmap icon, QString downloadurl); DownloadItem *addItem(QString name, QString fileName, QString pkgName, const QPixmap icon, QString downloadurl);
int nowDownload = 0; int nowDownload = 0;
int allDownload = 0; int allDownload = 0;
QList<DownloadItem *> getDIList(); QList<DownloadItem *> getDIList();
@ -35,7 +35,7 @@ private:
QStringList dlist; QStringList dlist;
QList<QUrl> urList; QList<QUrl> urList;
QList<DownloadItem *> downloaditemlist; QList<DownloadItem *> downloaditemlist;
DownloadController *downloadController; DownloadController *downloadController = nullptr;
int nowdownload = 0; int nowdownload = 0;
QString theSpeed; QString theSpeed;
QTimer download_speed; QTimer download_speed;