fix use-afrer-free crash caused by QtConcurrent
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
@@ -121,7 +121,6 @@ QString cleanPath(QString path)
|
|||||||
void InstanceImportTask::processZipPack()
|
void InstanceImportTask::processZipPack()
|
||||||
{
|
{
|
||||||
setStatus(tr("Attempting to determine instance type"));
|
setStatus(tr("Attempting to determine instance type"));
|
||||||
setDetails("");
|
|
||||||
QDir extractDir(m_stagingPath);
|
QDir extractDir(m_stagingPath);
|
||||||
qDebug() << "Attempting to create instance from" << m_archivePath;
|
qDebug() << "Attempting to create instance from" << m_archivePath;
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ void ExportToZipTask::executeTask()
|
|||||||
{
|
{
|
||||||
setStatus("Adding files...");
|
setStatus("Adding files...");
|
||||||
setProgress(0, m_files.length());
|
setProgress(0, m_files.length());
|
||||||
m_build_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return exportZip(); });
|
m_buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return exportZip(); });
|
||||||
connect(&m_build_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExportToZipTask::finish);
|
connect(&m_buildZipWatcher, &QFutureWatcher<ZipResult>::finished, this, &ExportToZipTask::finish);
|
||||||
m_build_zip_watcher.setFuture(m_build_zip_future);
|
m_buildZipWatcher.setFuture(m_buildZipFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ExportToZipTask::exportZip() -> ZipResult
|
auto ExportToZipTask::exportZip() -> ZipResult
|
||||||
@@ -40,30 +40,30 @@ auto ExportToZipTask::exportZip() -> ZipResult
|
|||||||
return ZipResult(tr("Could not create file"));
|
return ZipResult(tr("Could not create file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto fileName : m_extra_files.keys()) {
|
for (auto fileName : m_extraFiles.keys()) {
|
||||||
if (m_build_zip_future.isCanceled())
|
if (m_buildZipFuture.isCanceled())
|
||||||
return ZipResult();
|
return ZipResult();
|
||||||
if (!m_output.addFile(fileName, m_extra_files[fileName])) {
|
if (!m_output.addFile(fileName, m_extraFiles[fileName])) {
|
||||||
return ZipResult(tr("Could not add:") + fileName);
|
return ZipResult(tr("Could not add:") + fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QFileInfo& file : m_files) {
|
for (const QFileInfo& file : m_files) {
|
||||||
if (m_build_zip_future.isCanceled())
|
if (m_buildZipFuture.isCanceled())
|
||||||
return ZipResult();
|
return ZipResult();
|
||||||
|
|
||||||
auto absolute = file.absoluteFilePath();
|
auto absolute = file.absoluteFilePath();
|
||||||
auto relative = m_dir.relativeFilePath(absolute);
|
auto relative = m_dir.relativeFilePath(absolute);
|
||||||
setStatus("Compressing: " + relative);
|
setStatus("Compressing: " + relative);
|
||||||
setProgress(m_progress + 1, m_progressTotal);
|
setProgress(m_progress + 1, m_progressTotal);
|
||||||
if (m_follow_symlinks) {
|
if (m_followSymlinks) {
|
||||||
if (file.isSymLink())
|
if (file.isSymLink())
|
||||||
absolute = file.symLinkTarget();
|
absolute = file.symLinkTarget();
|
||||||
else
|
else
|
||||||
absolute = file.canonicalFilePath();
|
absolute = file.canonicalFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_exclude_files.contains(relative) && !m_output.addFile(absolute, m_destination_prefix + relative)) {
|
if (!m_excludeFiles.contains(relative) && !m_output.addFile(absolute, m_destinationPrefix + relative)) {
|
||||||
return ZipResult(tr("Could not read and compress %1").arg(relative));
|
return ZipResult(tr("Could not read and compress %1").arg(relative));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,11 +76,11 @@ auto ExportToZipTask::exportZip() -> ZipResult
|
|||||||
|
|
||||||
void ExportToZipTask::finish()
|
void ExportToZipTask::finish()
|
||||||
{
|
{
|
||||||
if (m_build_zip_future.isCanceled()) {
|
if (m_buildZipFuture.isCanceled()) {
|
||||||
FS::deletePath(m_output_path);
|
FS::deletePath(m_outputPath);
|
||||||
emitAborted();
|
emitAborted();
|
||||||
} else if (auto result = m_build_zip_future.result(); result.has_value()) {
|
} else if (auto result = m_buildZipFuture.result(); result.has_value()) {
|
||||||
FS::deletePath(m_output_path);
|
FS::deletePath(m_outputPath);
|
||||||
emitFailed(result.value());
|
emitFailed(result.value());
|
||||||
} else {
|
} else {
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
@@ -89,8 +89,8 @@ void ExportToZipTask::finish()
|
|||||||
|
|
||||||
bool ExportToZipTask::abort()
|
bool ExportToZipTask::abort()
|
||||||
{
|
{
|
||||||
if (m_build_zip_future.isRunning()) {
|
if (m_buildZipFuture.isRunning()) {
|
||||||
m_build_zip_future.cancel();
|
m_buildZipFuture.cancel();
|
||||||
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
|
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
|
||||||
// immediately.
|
// immediately.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ class ExportToZipTask : public Task {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false)
|
ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false)
|
||||||
: m_output_path(outputPath)
|
: m_outputPath(outputPath)
|
||||||
, m_output(outputPath)
|
, m_output(outputPath)
|
||||||
, m_dir(dir)
|
, m_dir(dir)
|
||||||
, m_files(files)
|
, m_files(files)
|
||||||
, m_destination_prefix(destinationPrefix)
|
, m_destinationPrefix(destinationPrefix)
|
||||||
, m_follow_symlinks(followSymlinks)
|
, m_followSymlinks(followSymlinks)
|
||||||
{
|
{
|
||||||
setAbortable(true);
|
setAbortable(true);
|
||||||
};
|
};
|
||||||
@@ -44,8 +44,8 @@ class ExportToZipTask : public Task {
|
|||||||
|
|
||||||
virtual ~ExportToZipTask() = default;
|
virtual ~ExportToZipTask() = default;
|
||||||
|
|
||||||
void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; }
|
void setExcludeFiles(QStringList excludeFiles) { m_excludeFiles = excludeFiles; }
|
||||||
void addExtraFile(QString fileName, QByteArray data) { m_extra_files.insert(fileName, data); }
|
void addExtraFile(QString fileName, QByteArray data) { m_extraFiles.insert(fileName, data); }
|
||||||
|
|
||||||
using ZipResult = std::optional<QString>;
|
using ZipResult = std::optional<QString>;
|
||||||
|
|
||||||
@@ -57,16 +57,16 @@ class ExportToZipTask : public Task {
|
|||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_output_path;
|
QString m_outputPath;
|
||||||
ArchiveWriter m_output;
|
ArchiveWriter m_output;
|
||||||
QDir m_dir;
|
QDir m_dir;
|
||||||
QFileInfoList m_files;
|
QFileInfoList m_files;
|
||||||
QString m_destination_prefix;
|
QString m_destinationPrefix;
|
||||||
bool m_follow_symlinks;
|
bool m_followSymlinks;
|
||||||
QStringList m_exclude_files;
|
QStringList m_excludeFiles;
|
||||||
QHash<QString, QByteArray> m_extra_files;
|
QHash<QString, QByteArray> m_extraFiles;
|
||||||
|
|
||||||
QFuture<ZipResult> m_build_zip_future;
|
QFuture<ZipResult> m_buildZipFuture;
|
||||||
QFutureWatcher<ZipResult> m_build_zip_watcher;
|
QFutureWatcher<ZipResult> m_buildZipWatcher;
|
||||||
};
|
};
|
||||||
} // namespace MMCZip
|
} // namespace MMCZip
|
||||||
@@ -25,14 +25,14 @@ namespace MMCZip {
|
|||||||
|
|
||||||
void ExtractZipTask::executeTask()
|
void ExtractZipTask::executeTask()
|
||||||
{
|
{
|
||||||
m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
|
m_zipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
|
||||||
connect(&m_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
|
connect(&m_zipWatcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
|
||||||
m_zip_watcher.setFuture(m_zip_future);
|
m_zipWatcher.setFuture(m_zipFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ExtractZipTask::extractZip() -> ZipResult
|
auto ExtractZipTask::extractZip() -> ZipResult
|
||||||
{
|
{
|
||||||
auto target = m_output_dir.absolutePath();
|
auto target = m_outputDir.absolutePath();
|
||||||
auto target_top_dir = QUrl::fromLocalFile(target);
|
auto target_top_dir = QUrl::fromLocalFile(target);
|
||||||
|
|
||||||
QStringList extracted;
|
QStringList extracted;
|
||||||
@@ -52,8 +52,9 @@ auto ExtractZipTask::extractZip() -> ZipResult
|
|||||||
setStatus("Extracting files...");
|
setStatus("Extracting files...");
|
||||||
setProgress(0, m_input.getFiles().count());
|
setProgress(0, m_input.getFiles().count());
|
||||||
ZipResult result;
|
ZipResult result;
|
||||||
|
auto fileName = m_input.getZipName();
|
||||||
if (!m_input.parse([this, &result, &target, &target_top_dir, ext, &extracted](ArchiveReader::File* f) {
|
if (!m_input.parse([this, &result, &target, &target_top_dir, ext, &extracted](ArchiveReader::File* f) {
|
||||||
if (m_zip_future.isCanceled())
|
if (m_zipFuture.isCanceled())
|
||||||
return false;
|
return false;
|
||||||
setProgress(m_progress + 1, m_progressTotal);
|
setProgress(m_progress + 1, m_progressTotal);
|
||||||
QString file_name = f->filename();
|
QString file_name = f->filename();
|
||||||
@@ -104,17 +105,16 @@ auto ExtractZipTask::extractZip() -> ZipResult
|
|||||||
return true;
|
return true;
|
||||||
})) {
|
})) {
|
||||||
FS::removeFiles(extracted);
|
FS::removeFiles(extracted);
|
||||||
return result.has_value() || m_zip_future.isCanceled() ? result
|
return result.has_value() ? result : ZipResult(tr("Failed to parse file %1").arg(fileName));
|
||||||
: ZipResult(tr("Failed to parse file %1").arg(m_input.getZipName()));
|
|
||||||
}
|
}
|
||||||
return ZipResult();
|
return ZipResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractZipTask::finish()
|
void ExtractZipTask::finish()
|
||||||
{
|
{
|
||||||
if (m_zip_future.isCanceled()) {
|
if (m_zipFuture.isCanceled()) {
|
||||||
emitAborted();
|
emitAborted();
|
||||||
} else if (auto result = m_zip_future.result(); result.has_value()) {
|
} else if (auto result = m_zipFuture.result(); result.has_value()) {
|
||||||
emitFailed(result.value());
|
emitFailed(result.value());
|
||||||
} else {
|
} else {
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
@@ -123,8 +123,8 @@ void ExtractZipTask::finish()
|
|||||||
|
|
||||||
bool ExtractZipTask::abort()
|
bool ExtractZipTask::abort()
|
||||||
{
|
{
|
||||||
if (m_zip_future.isRunning()) {
|
if (m_zipFuture.isRunning()) {
|
||||||
m_zip_future.cancel();
|
m_zipFuture.cancel();
|
||||||
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
|
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
|
||||||
// immediately.
|
// immediately.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class ExtractZipTask : public Task {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "")
|
ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "")
|
||||||
: m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory)
|
: m_input(input), m_outputDir(outputDir), m_subdirectory(subdirectory)
|
||||||
{}
|
{}
|
||||||
virtual ~ExtractZipTask() = default;
|
virtual ~ExtractZipTask() = default;
|
||||||
|
|
||||||
@@ -44,10 +44,10 @@ class ExtractZipTask : public Task {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ArchiveReader m_input;
|
ArchiveReader m_input;
|
||||||
QDir m_output_dir;
|
QDir m_outputDir;
|
||||||
QString m_subdirectory;
|
QString m_subdirectory;
|
||||||
|
|
||||||
QFuture<ZipResult> m_zip_future;
|
QFuture<ZipResult> m_zipFuture;
|
||||||
QFutureWatcher<ZipResult> m_zip_watcher;
|
QFutureWatcher<ZipResult> m_zipWatcher;
|
||||||
};
|
};
|
||||||
} // namespace MMCZip
|
} // namespace MMCZip
|
||||||
Reference in New Issue
Block a user