Clear the Read-Only Attribute Before Replacing a Config and Back Off After a Failed Save

Nothing replaces a read-only file on Windows, neither a rename over it
nor an in-place write, so the opt-in that keeps a read-only config
saveable clears the attribute first; without that the test for it could
not pass there. A failed config write still leaves the flag dirty, as
before this change, but the next attempt waits ten seconds, so the idle
handler does not repeat a hopeless write on every event.

A file moved aside by a refused rename can be the only copy left if the
process dies in between, so the sweep puts such a file back when its
original is missing rather than removing it, and the directory-only
errors that could only come from a directory target no longer trigger
the move-aside at all. The sweep after a write runs only under the data
dir and at most once an hour per directory, so a batch of saves does not
read the directory once per file and an export into a user's folder
never reads that folder. A lock holder that never lets go doubles the
cool-down for each timeout in a row, up to five minutes, instead of
costing a stall every ten seconds for good.
This commit is contained in:
Hanif Koh
2026-09-24 23:22:31 +08:00
parent 1b30ae7424
commit b7102a524b
7 changed files with 88 additions and 19 deletions
+4
View File
@@ -2,6 +2,7 @@
#define slic3r_AppConfig_hpp_
#include <set>
#include <chrono>
#include <map>
#include <string>
#include "nlohmann/json.hpp"
@@ -457,6 +458,9 @@ private:
bool write_config_file(const std::string &path, std::string body, const std::string &checksum_source);
bool m_dirty;
// After a failed write, save() does nothing until this point, so the idle
// handler does not repeat the attempt on every event.
std::chrono::steady_clock::time_point m_retry_save_at{};
// Original version found in the ini file before it was overwritten
Semver m_orig_version;
// Whether the existing version is before system profiles & configuration updating