mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-25 01:40:57 +00:00
Lock the Preset Scan Per File and Reopen a Lock File Replaced on Disk
Holding the lock across the whole preset scan meant a reload on a background thread, which the login path runs, blocked a save on the GUI thread for the scan's duration through the in-process mutex, which has no timeout. Each file is locked on its own now, which keeps a file whole under a reader without keeping the saver waiting. A guard kept its handle to the lock file for good, so a lock file that someone deleted or recreated left this instance locking a file no other instance could see. The guard compares what the path names against what it opened and reopens when they differ. Preset::save() serialises before it takes the lock, so the exclusive window is the two file writes. On Windows an unlocked reader, which the CLI and a timed-out instance are by design, made the rename fail at once and the write go in place under that reader; the rename is retried for half a second first, since a reader is done in milliseconds, and the fallback when no temporary can be created is logged like the other one. The sweep matches only the exact <name>.<pid>.<n>.tmp shape and waits an hour, since hosts sharing a data dir may disagree on the time. Real write access is checked with access(), the read-only tests skip as root, and the dead permissions block after the rename is gone.
This commit is contained in:
@@ -96,6 +96,24 @@ TEST_CASE("InstanceLock retries a lock file it could not open once the cool-down
|
||||
REQUIRE(after_cooldown);
|
||||
}
|
||||
|
||||
TEST_CASE("InstanceLock reopens a lock file that was replaced on disk", "[InstanceLock]")
|
||||
{
|
||||
ScopedTemporaryFile lock_file(".lock");
|
||||
const std::string path = lock_file.string();
|
||||
{
|
||||
InstanceLock lock(path);
|
||||
REQUIRE(lock.locked());
|
||||
}
|
||||
|
||||
boost::filesystem::remove(path);
|
||||
InstanceLock lock(path);
|
||||
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
|
||||
// the old handle is closed, so it is no proof either way.)
|
||||
REQUIRE(boost::filesystem::exists(path));
|
||||
}
|
||||
|
||||
TEST_CASE("InstanceLock serialises the threads of one process", "[InstanceLock]")
|
||||
{
|
||||
ScopedTemporaryFile lock_file(".lock");
|
||||
|
||||
Reference in New Issue
Block a user