mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
fix: give every NVS user its own Preferences handle
loop() and the async web server task shared one global Preferences. A begin() from one task failed while the other had a namespace open, and the clear() or remove() after it then hit the other task's namespace: saving the radio settings while a command committed its rolling code could erase every rolling code. Each function now opens NVS with a local Preferences. NVS serializes access internally and the destructor closes the handle, so no lock is added (see docs/adr/0001). No new tests: nothing here builds natively, and deleting the global makes any missed use a compile error. The read-then-commit races on rolling codes across tasks remain and are tracked in docs/KNOWN_ISSUES.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4135f21ee7
commit
c1b47f898c
6 changed files with 94 additions and 27 deletions
12
docs/adr/0001-local-nvs-handles-no-wrapper.md
Normal file
12
docs/adr/0001-local-nvs-handles-no-wrapper.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Each function opens NVS with its own Preferences handle, with no lock or wrapper
|
||||
|
||||
A single global `Preferences pref` was used from both `loop()` and the async web server task. A `begin()` from one task could fail while the other task had a namespace open, and its `clear()` or `remove()` then hit the wrong namespace (a radio settings save could erase every rolling code). We replaced the global with a local `Preferences` in each function that uses NVS. We did not put an app-level lock or a wrapper module around it, because ESP-IDF's NVS API already serializes access internally (`nvs::Lock`), each `Preferences` holds its own handle, and its destructor calls `end()`.
|
||||
|
||||
## Considered Options
|
||||
|
||||
- **Global handle plus a mutex-backed `NvsSession`.** Rejected: the lock would only protect the shared handle, which is the actual bug, and it would block `loop()`'s rolling-code writes while `ConfigFile` keeps `ShadeCodes` open across LittleFS reads. Remove the shared handle and nothing is left for the lock to do.
|
||||
- **An `NvsStore` seam with typed accessors and an in-memory adapter for native tests.** Rejected: it would have exactly one real adapter, so the seam would be hypothetical, and deleting it would just give back `Preferences`. The only NVS logic worth testing (the next rolling code) is already tested natively through `RollingCode.h`, which takes its loader as a parameter.
|
||||
|
||||
## Consequences
|
||||
|
||||
Separate handles make each NVS operation safe on its own, but not a read-then-write sequence across tasks (rolling-code peek/commit in `loop()` against `/setRollingCode` or a restore on the web server task). Those races belong to the model, not to NVS, and are tracked in `docs/KNOWN_ISSUES.md`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue