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, [=]() {
{ return;
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); });
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,76 +105,10 @@ void DownloadItem::install(int t)
ui->label_2->setToolTip(tr("Installing")); ui->label_2->setToolTip(tr("Installing"));
QtConcurrent::run([=]() QtConcurrent::run([=]()
{ {
QProcess installer; slotAsyncInstall(t);
switch(t) });
{
case 0:
installer.start("pkexec", QStringList() << "ssinstall" << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 1:
installer.start("deepin-deb-installer", QStringList() << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 2:
installer.start("pkexec", QStringList() << "gdebi" << "-n" << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
}
bool haveError = false;
bool notRoot = false;
installer.waitForFinished(-1); // 不设置超时
out = installer.readAllStandardOutput();
QStringList everyOut = out.split("\n");
for (int i = 0; i < everyOut.size(); i++)
{
if(everyOut[i].left(2) == "E:")
{
haveError = true;
}
if(everyOut[i].right(14) == "Not authorized")
{
notRoot = true;
}
}
QProcess isInstall;
isInstall.start("dpkg", QStringList() << "-s" << pkgName);
isInstall.waitForFinished(180*1000); // 默认超时 3 分钟
int error = QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
if (error == 0 && !haveError)
{
ui->pushButton_install->hide();
Utils::sendNotification("spark-store",tr("Spark Store"),ui->label->text() + " " + tr("Installation complete."));
ui->label_2->setText(tr("Finish"));
ui->label_2->setToolTip(tr("Finish"));
download = 3;
ui->pushButton_3->show();
}
else
{
ui->pushButton_install->show();
ui->pushButton_install->setText(tr("Retry"));
download = 1;
Utils::sendNotification("spark-store",tr("Spark Store"),tr("Error happened in dpkg progress , you can try it again."));
ui->label_2->setText(tr("Error happened in dpkg progress , you can try it again"));
ui->label_2->setToolTip(tr("Error happened in dpkg progress , you can try it again"));
ui->pushButton_3->show();
}
if (notRoot)
{
Utils::sendNotification("spark-store",tr("Spark Store"),tr("dpkg progress had been abortedyou can retry installation."));
ui->label_2->setText(tr("dpkg progress had been abortedyou can retry installation"));
ui->label_2->setToolTip(tr("dpkg progress had been abortedyou can retry installation"));
ui->pushButton_install->show();
ui->pushButton_3->hide();
}
ui->widget_spinner->hide();
DownloadItem::isInstall = false;
emit finished(); });
// emit finished();
qDebug() << ui->label_filename->text().toUtf8(); qDebug() << ui->label_filename->text().toUtf8();
} }
} }
@@ -207,3 +141,75 @@ void DownloadItem::on_pushButton_3_clicked()
output_w->layout()->addWidget(textbrowser); output_w->layout()->addWidget(textbrowser);
output_w->show(); output_w->show();
} }
void DownloadItem::slotAsyncInstall(int t)
{
QProcess installer;
switch(t)
{
case 0:
installer.start("pkexec", QStringList() << "ssinstall" << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 1:
installer.start("deepin-deb-installer", QStringList() << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 2:
installer.start("pkexec", QStringList() << "gdebi" << "-n" << "/tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
}
bool haveError = false;
bool notRoot = false;
installer.waitForFinished(-1); // 不设置超时
out = installer.readAllStandardOutput();
QStringList everyOut = out.split("\n");
for (int i = 0; i < everyOut.size(); i++)
{
if(everyOut[i].left(2) == "E:")
{
haveError = true;
}
if(everyOut[i].right(14) == "Not authorized")
{
notRoot = true;
}
}
QProcess isInstall;
isInstall.start("dpkg", QStringList() << "-s" << pkgName);
isInstall.waitForFinished(180*1000); // 默认超时 3 分钟
int error = QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
if (error == 0 && !haveError)
{
ui->pushButton_install->hide();
Utils::sendNotification("spark-store",tr("Spark Store"),ui->label->text() + " " + tr("Installation complete."));
ui->label_2->setText(tr("Finish"));
ui->label_2->setToolTip(tr("Finish"));
download = 3;
ui->pushButton_3->show();
}
else
{
ui->pushButton_install->show();
ui->pushButton_install->setText(tr("Retry"));
download = 1;
Utils::sendNotification("spark-store",tr("Spark Store"),tr("Error happened in dpkg progress , you can try it again."));
ui->label_2->setText(tr("Error happened in dpkg progress , you can try it again"));
ui->label_2->setToolTip(tr("Error happened in dpkg progress , you can try it again"));
ui->pushButton_3->show();
}
if (notRoot)
{
Utils::sendNotification("spark-store",tr("Spark Store"),tr("dpkg progress had been abortedyou can retry installation."));
ui->label_2->setText(tr("dpkg progress had been abortedyou can retry installation"));
ui->label_2->setToolTip(tr("dpkg progress had been abortedyou can retry installation"));
ui->pushButton_install->show();
ui->pushButton_3->hide();
}
ui->widget_spinner->hide();
DownloadItem::isInstall = false;
emit finished();
}

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;