Skip to content

fix: atomic writes, volatile journal, ASCII console banners - #56

Merged
ojacques merged 2 commits into
mainfrom
fix/atomic-writes-volatile-journal
Jul 25, 2026
Merged

ojacques merged 2 commits into
mainfrom
fix/atomic-writes-volatile-journal

Conversation

@ojacques

@ojacques ojacques commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Repeated f2fs corruption on the Raspberry Pi after power loss. Root cause: direct file writes (open(path, 'w')) and continuous journald writes to /data.

Additionally, console banners displayed on the RPi terminal (tty1) were misaligned because emoji and Unicode box-drawing characters have inconsistent widths on the Linux framebuffer console.

Changes

1. Atomic file writes (zeclock/atomic_write.py)

New utility module implementing the crash-safe write pattern:

  • Write to temp file in same directory
  • fsync() the file descriptor
  • os.replace() (atomic POSIX rename)
  • fsync() the directory

Applied to all config/state writes:

  • zeclock.ini (brightness, wifi_addr, full config save, import)
  • plugins.yaml (plugin config save, default creation)
  • current-version (OTA updater)
  • history.json (OTA update history)

2. Journald switched to volatile (RAM)

  • Storage=volatile replaces Storage=persistent
  • Eliminates the feat: Plugin System #1 source of continuous writes to /data
  • Logs no longer survive reboots (acceptable tradeoff for a clock)
  • Capped at 10 MB RAM usage

3. ASCII-only console banners

  • Replaced Unicode box-drawing characters and emoji in _show_console_banner and _show_connected_banner with plain ASCII (+, |, =)
  • Removed emoji from main() print statements
  • Fixes misaligned borders on RPi framebuffer terminal

Result

  • Config files on /data are guaranteed to be either the previous valid version or the new complete version at any point during a power cut.
  • Console banners render correctly on all terminals.

ojacques added 2 commits July 25, 2026 10:54
Power-loss safety improvements for the Raspberry Pi deployment:

1. Atomic file writes (new zeclock/atomic_write.py):
   - All config/state writes now use temp file + fsync + rename
   - Guarantees files are either old or new, never truncated
   - Applied to: zeclock.ini, plugins.yaml, update version/history

2. Journald switched to volatile (RAM-only):
   - Continuous journal writes were the #1 source of f2fs corruption
   - Logs no longer survive reboots but /data stays healthy
   - RuntimeMaxUse=10M caps RAM usage

Files using atomic writes:
- clock.py (_persist_wifi_addr)
- rest_remote.py (save config, save plugins, persist brightness, import)
- updater.py (version file, history.json)
- plugin_config.py (create default config)
Terminal on RPi does not support emoji (width=2) or Unicode
box-drawing characters, causing misaligned banner borders.
Use plain ASCII characters (+, |, =) instead.
@ojacques ojacques changed the title fix: atomic writes + volatile journal to prevent /data corruption fix: atomic writes, volatile journal, ASCII console banners Jul 25, 2026
@ojacques
ojacques merged commit 696c0ba into main Jul 25, 2026
1 of 2 checks passed
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