mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-25 09:50:59 +00:00
Let an Explicit Config Save Bypass the Back-Off and Lock the Scan's Failure Cleanup
The ten-second back-off after a failed config write sat inside save() itself, so the save on exit could return without writing and lose the session's changes; it gates only the idle-time save now, through save_due(), and an explicit save always tries. The preset scan's failure handlers removed a broken preset and its .info after the per-file guard had ended, so another instance's fresh copy of that file could be deleted from under it; they take the guard too. A lock that is acquired ends the cool-down a timeout started, rather than letting every guard for the rest of it proceed unlocked whenever the lock is momentarily held. The lock file's identity is checked on every acquisition, one stat, since a handle to a replaced file locks nothing anyone else can see. Write access on Windows is probed with an open for writing, which sees ACLs where _waccess sees only the read-only attribute, and a temporary name too long for the filesystem falls back to an in-place write for a new file as well as an existing one. The lock tests restore the knobs they change however they end.
This commit is contained in:
@@ -18,6 +18,15 @@
|
||||
using namespace Slic3r;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// Sets a process-wide knob for one test and restores it however the test ends.
|
||||
template<typename T> struct ScopedStaticValue
|
||||
{
|
||||
T &ref;
|
||||
T saved;
|
||||
ScopedStaticValue(T &ref, T value) : ref(ref), saved(ref) { ref = value; }
|
||||
~ScopedStaticValue() { ref = saved; }
|
||||
};
|
||||
|
||||
TEST_CASE("InstanceLock creates its lock file and holds it for the guard's scope", "[InstanceLock]")
|
||||
{
|
||||
ScopedTemporaryFile lock_file(".lock");
|
||||
@@ -67,8 +76,7 @@ TEST_CASE("InstanceLock retries a lock file it could not open once the cool-down
|
||||
{
|
||||
ScopedTemporaryDir dir;
|
||||
const std::string path = (dir.path() / "later" / "shared.lock").string();
|
||||
const auto saved_cooldown = InstanceLock::cooldown;
|
||||
InstanceLock::cooldown = 300ms;
|
||||
ScopedStaticValue cooldown(InstanceLock::cooldown, 300ms);
|
||||
|
||||
bool before_dir, during_cooldown, after_cooldown;
|
||||
const auto started = std::chrono::steady_clock::now();
|
||||
@@ -87,7 +95,6 @@ TEST_CASE("InstanceLock retries a lock file it could not open once the cool-down
|
||||
InstanceLock lock(path, 100ms);
|
||||
after_cooldown = lock.locked();
|
||||
}
|
||||
InstanceLock::cooldown = saved_cooldown;
|
||||
|
||||
REQUIRE_FALSE(before_dir);
|
||||
// A loaded runner may take longer than the cool-down to get here; then the
|
||||
@@ -101,8 +108,7 @@ TEST_CASE("InstanceLock reopens a lock file that was replaced on disk", "[Instan
|
||||
{
|
||||
ScopedTemporaryFile lock_file(".lock");
|
||||
const std::string path = lock_file.string();
|
||||
const auto saved_interval = InstanceLock::identity_check_interval;
|
||||
InstanceLock::identity_check_interval = 0ms;
|
||||
ScopedStaticValue interval(InstanceLock::identity_check_interval, 0ms);
|
||||
{
|
||||
InstanceLock lock(path);
|
||||
REQUIRE(lock.locked());
|
||||
@@ -110,7 +116,6 @@ TEST_CASE("InstanceLock reopens a lock file that was replaced on disk", "[Instan
|
||||
|
||||
boost::filesystem::remove(path);
|
||||
InstanceLock lock(path);
|
||||
InstanceLock::identity_check_interval = saved_interval;
|
||||
REQUIRE(lock.locked());
|
||||
// Only a reopen recreates the file; a guard still holding the unlinked one
|
||||
// would leave the path missing. (The inode number itself may be reused once
|
||||
|
||||
Reference in New Issue
Block a user