Skip to content

fix(AppConfig): prevent config loss on unclean shutdown - #5613

Open
moumoum0 wants to merge 1 commit into
seerge:mainfrom
moumoum0:fix/config-corruption-on-unclean-shutdown
Open

fix(AppConfig): prevent config loss on unclean shutdown#5613
moumoum0 wants to merge 1 commit into
seerge:mainfrom
moumoum0:fix/config-corruption-on-unclean-shutdown

Conversation

@moumoum0

Copy link
Copy Markdown

Problem

Asus TUF/Tian Xuan laptops have a long-standing hardware bug: opening the lid from sleep can trigger a spontaneous hard reboot — essentially a sudden power loss.

G-Helper's config write logic had a flaw: any call to Set() would schedule a disk write after 2 seconds, regardless of whether the value actually changed. Lid-open events fire a cascade of system events (monitor wake, power state changes, mode re-application) that all call Set(), but most of them write the exact same values already in memory.

The result: lid-open = trigger disk write + trigger reboot, both dangerous operations tied to the same user action. The reboot lands during that brief write window, corrupting both config.json and its .bak backup into 0x00 bytes. Next launch sees both files trashed, falls through all recovery paths, and resets everything to defaults.

Fix (Two layers)

Layer 1: Dirty-check before writing

Added a value-comparison guard in Set() / Remove(). If the new value equals the existing one, skip the write entirely. This eliminates the vast majority of redundant disk writes triggered by system events, drastically reducing the chance of a crash mid-write.

Layer 2: Harden the fallback backup

Previously SyncFallbackConfig used File.Copy(source, fallback), meaning a corrupted primary file would silently overwrite and destroy the backup copy.

Now it receives the freshly serialized JSON string (guaranteed valid) and writes it atomically via WriteAtomic. An additional guard aborts the write if the JSON string is empty or contains NUL bytes, preventing the fallback from being poisoned by corrupted data from the primary file.

Two-layer fix for intermittent total config reset (all settings wiped)
caused by NUL-byte corruption of both config.json and its .bak on
machines where opening the lid can trigger a spontaneous reboot (Asus
TUF / Tian Xuan series ACPI hardware quirk).

Layer 1 - dirty-check in Set / Remove
Before scheduling a debounced write, compare the incoming value to
what is already stored. Skip Write() when nothing changed. This
significantly reduces the frequency of disk writes triggered by
periodic re-apply calls (ReapplyTimer, fan sensor loop, lid-open /
monitor-power events), shrinking the window in which a crash mid-write
can corrupt the file.

Layer 2 - harden SyncFallbackConfig
Previously it did File.Copy(configFile, fallback), so a zeroed primary
file would silently overwrite the fallback, destroying the last recovery
copy. Now it receives the in-memory JSON string that was just serialized
(guaranteed valid) and writes it through WriteAtomic. An additional
guard skips the write entirely if the content is empty or contains NUL
bytes, ensuring the fallback can never be polluted by a corrupted source.
@seerge
seerge force-pushed the main branch 2 times, most recently from 027e4b6 to 2107c5f Compare July 2, 2026 11:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant