mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-07-07 20:14:12 +02:00
Skip actively locked autosave files
Check the QLockFile in staleFiles() before returning a no-KF5 recovery candidate, matching the KAutoSaveFile contract that actively owned autosave files are not stale. Extend the no-KF5 Catch test so a child process keeps the autosave lock alive while allStaleFiles() runs, then verify recovery after the child is killed. Assisted-by: pi coding agent / Mika (OpenAI GPT-5.5)
This commit is contained in:
@@ -48,6 +48,11 @@ QString metadataFileName(const QString &autosave_file_name)
|
|||||||
return autosave_file_name + QStringLiteral(".path");
|
return autosave_file_name + QStringLiteral(".path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString lockFileName(const QString &autosave_file_name)
|
||||||
|
{
|
||||||
|
return autosave_file_name + QStringLiteral(".lock");
|
||||||
|
}
|
||||||
|
|
||||||
QUrl normalizeManagedFile(const QUrl &url)
|
QUrl normalizeManagedFile(const QUrl &url)
|
||||||
{
|
{
|
||||||
if (url.isEmpty()) {
|
if (url.isEmpty()) {
|
||||||
@@ -165,6 +170,18 @@ QStringList findAllStaleFiles(const QString &application_name)
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool autosaveFileIsRecoverable(const QString &autosave_file_name)
|
||||||
|
{
|
||||||
|
QLockFile lock(lockFileName(autosave_file_name));
|
||||||
|
lock.setStaleLockTime(60 * 1000);
|
||||||
|
if (!lock.tryLock()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
KAutoSaveFile::KAutoSaveFile(const QUrl &filename, QObject *parent) :
|
KAutoSaveFile::KAutoSaveFile(const QUrl &filename, QObject *parent) :
|
||||||
@@ -239,8 +256,7 @@ bool KAutoSaveFile::open(OpenMode openmode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_lock) {
|
if (!m_lock) {
|
||||||
m_lock = std::make_unique<QLockFile>(
|
m_lock = std::make_unique<QLockFile>(lockFileName(fileName()));
|
||||||
fileName() + QStringLiteral(".lock"));
|
|
||||||
m_lock->setStaleLockTime(60 * 1000);
|
m_lock->setStaleLockTime(60 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +284,9 @@ QList<KAutoSaveFile *> KAutoSaveFile::staleFiles(
|
|||||||
&& managed_file != managed_file_filter) {
|
&& managed_file != managed_file_filter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!autosaveFileIsRecoverable(file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto *stale_file = new KAutoSaveFile(managed_file);
|
auto *stale_file = new KAutoSaveFile(managed_file);
|
||||||
stale_file->setFileName(file);
|
stale_file->setFileName(file);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -34,11 +35,16 @@ TEST_CASE("Qt-only KAutoSaveFile recovers stale files", "[nokde][autosave]")
|
|||||||
REQUIRE(managed_file.write("<project/>\n") > 0);
|
REQUIRE(managed_file.write("<project/>\n") > 0);
|
||||||
managed_file.close();
|
managed_file.close();
|
||||||
|
|
||||||
|
int ready_pipe[2] = {-1, -1};
|
||||||
|
REQUIRE(pipe(ready_pipe) == 0);
|
||||||
|
|
||||||
const QByteArray payload("<project><diagram /></project>\n");
|
const QByteArray payload("<project><diagram /></project>\n");
|
||||||
const auto child_pid = fork();
|
const auto child_pid = fork();
|
||||||
REQUIRE(child_pid >= 0);
|
REQUIRE(child_pid >= 0);
|
||||||
|
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
|
close(ready_pipe[0]);
|
||||||
|
|
||||||
KAutoSaveFile backup(QUrl::fromLocalFile(managed_path));
|
KAutoSaveFile backup(QUrl::fromLocalFile(managed_path));
|
||||||
if (!backup.open(QIODevice::WriteOnly
|
if (!backup.open(QIODevice::WriteOnly
|
||||||
| QIODevice::Truncate
|
| QIODevice::Truncate
|
||||||
@@ -52,13 +58,34 @@ TEST_CASE("Qt-only KAutoSaveFile recovers stale files", "[nokde][autosave]")
|
|||||||
_exit(4);
|
_exit(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit(0);
|
const char ready = '1';
|
||||||
|
if (write(ready_pipe[1], &ready, 1) != 1) {
|
||||||
|
_exit(5);
|
||||||
|
}
|
||||||
|
close(ready_pipe[1]);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(ready_pipe[1]);
|
||||||
|
char ready = 0;
|
||||||
|
REQUIRE(read(ready_pipe[0], &ready, 1) == 1);
|
||||||
|
close(ready_pipe[0]);
|
||||||
|
REQUIRE(ready == '1');
|
||||||
|
|
||||||
|
auto active_files = KAutoSaveFile::allStaleFiles();
|
||||||
|
CHECK(active_files.isEmpty());
|
||||||
|
for (auto *file : active_files) {
|
||||||
|
delete file;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(kill(child_pid, SIGKILL) == 0);
|
||||||
int status = 0;
|
int status = 0;
|
||||||
REQUIRE(waitpid(child_pid, &status, 0) == child_pid);
|
REQUIRE(waitpid(child_pid, &status, 0) == child_pid);
|
||||||
REQUIRE(WIFEXITED(status));
|
REQUIRE(WIFSIGNALED(status));
|
||||||
REQUIRE(WEXITSTATUS(status) == 0);
|
REQUIRE(WTERMSIG(status) == SIGKILL);
|
||||||
|
|
||||||
auto stale_files = KAutoSaveFile::allStaleFiles();
|
auto stale_files = KAutoSaveFile::allStaleFiles();
|
||||||
REQUIRE(stale_files.size() == 1);
|
REQUIRE(stale_files.size() == 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user