mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
Retry a Failed Lock File, Keep Special Targets in Place and Sweep Stale Temporaries
A lock file that failed to open once stayed unopened for the rest of the process, so a scanner holding the fresh file for a moment on Windows silently disabled the lock for the session, and a lock call that throws, as it does on a share without a lock service, was re-attempted and logged by every guard. Both are now left alone for the cool-down and then retried. Renaming a fresh file over the target turned a symlinked preset into a plain file, reset its permissions to the umask default, and could not work at all for a settings export to a device or pipe, since a temporary cannot be created beside /dev/stdout. A target that is not a regular file is now written in place, an existing target keeps its permissions, and a directory that refuses the temporary but not the file falls back too. The inline PhysicalPrinter::save() overload was the one physical printer writer without the guard. load_info() took the lock redundantly under the scan guard and, in read-only mode, created user.lock per file; the bundle metadata reader now honours read_only too. The plugin config, the setup guide's profile cache and the vendor preset cache wrote through a temporary by hand; they use the helper, with a binary mode for the cache. A crash between temporary and rename left a <name>.<pid>.tmp behind for good; AppConfig::load() and the preset scan remove stale ones while they hold the lock, and AppConfig::save() names its temporary the same way.
This commit is contained in:
@@ -62,6 +62,35 @@ TEST_CASE("InstanceLock is a no-op for an empty path and survives an unwritable
|
||||
REQUIRE_FALSE(unwritable.locked());
|
||||
}
|
||||
|
||||
TEST_CASE("InstanceLock retries a lock file it could not open once the cool-down passes", "[InstanceLock]")
|
||||
{
|
||||
ScopedTemporaryDir dir;
|
||||
const std::string path = (dir.path() / "later" / "shared.lock").string();
|
||||
const auto saved_cooldown = InstanceLock::cooldown;
|
||||
InstanceLock::cooldown = 50ms;
|
||||
|
||||
bool before_dir, during_cooldown, after_cooldown;
|
||||
{
|
||||
InstanceLock lock(path, 100ms);
|
||||
before_dir = lock.locked();
|
||||
}
|
||||
boost::filesystem::create_directories(dir.path() / "later");
|
||||
{
|
||||
InstanceLock lock(path, 100ms);
|
||||
during_cooldown = lock.locked();
|
||||
}
|
||||
std::this_thread::sleep_for(80ms);
|
||||
{
|
||||
InstanceLock lock(path, 100ms);
|
||||
after_cooldown = lock.locked();
|
||||
}
|
||||
InstanceLock::cooldown = saved_cooldown;
|
||||
|
||||
REQUIRE_FALSE(before_dir);
|
||||
REQUIRE_FALSE(during_cooldown);
|
||||
REQUIRE(after_cooldown);
|
||||
}
|
||||
|
||||
TEST_CASE("InstanceLock serialises the threads of one process", "[InstanceLock]")
|
||||
{
|
||||
ScopedTemporaryFile lock_file(".lock");
|
||||
|
||||
Reference in New Issue
Block a user