Skip to content

Handle overlay config reload on live updates#98

Merged
supermarsx merged 4 commits intomainfrom
smx/implement-parameter-refresh-in-reload-thread-2025-11-01
Nov 1, 2025
Merged

Handle overlay config reload on live updates#98
supermarsx merged 4 commits intomainfrom
smx/implement-parameter-refresh-in-reload-thread-2025-11-01

Conversation

@supermarsx
Copy link
Copy Markdown
Owner

Summary

  • add deferred config refresh support in the overlay so reloads update spawn strategy, badge sizing, FPS mode, and emoji atlas data without rebuilding the overlay
  • reload emoji resources and badge selector data when asset paths change while keeping the renderer running
  • invoke the overlay refresh from the config reload thread and synchronize tray FPS state with the latest configuration

Testing

  • cmake --preset linux (fails: GTK+-3.0 development files are missing in the container)

https://chatgpt.com/codex/tasks/task_e_69050af7b1548325a6f95a7e36efcc47

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +643 to +682
void Overlay::apply_pending_config() {
PendingConfig pending;
{
std::lock_guard<std::mutex> lock(m_pending_mutex);
if (!m_pending_config) {
return;
}
pending = *m_pending_config;
m_pending_config.reset();
}

if (pending.spawn_strategy == "cursor_follow") {
m_spawn_strategy = BadgeSpawnStrategy::CursorFollow;
} else {
m_spawn_strategy = BadgeSpawnStrategy::RandomScreen;
}

m_badge_min_px = pending.badge_min_px;
m_badge_max_px = pending.badge_max_px;
m_badges_per_second_max = pending.badges_per_second_max;

if (pending.fps_mode == "fixed") {
set_fps_fixed(pending.fps_fixed);
set_fps_mode(platform::FpsMode::Fixed);
} else {
set_fps_mode(platform::FpsMode::Auto);
}

auto normalized = normalize_path(pending.emoji_atlas);
bool atlas_changed = normalized != m_current_emoji_path;
if (atlas_changed) {
if (load_atlas_from_path(normalized)) {
m_badges.clear();
m_spawn_times.clear();
} else {
normalized = m_current_emoji_path;
}
}

build_selector(pending.emoji, pending.emoji_weighted);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard overlay config refresh against concurrent badge spawns

The new apply_pending_config mutates m_spawn_strategy, m_badge_min_px, m_badge_max_px, m_badges_per_second_max, m_selector_indices, m_selector, and the sprite atlas in place when a reload occurs. These members are read from the keyboard hook thread via spawn_badge/select_sprite without any synchronization. With runtime refresh now possible, a config reload can reorder or resize the sprite/selector vectors while the hook thread is in the middle of adding a badge, yielding a data race and potential use-after-free or corrupted RNG state. Consider protecting these shared structures (e.g., with a mutex or event queue) or ensuring spawns occur on the same thread as the refresh.

Useful? React with 👍 / 👎.

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex fix comments

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Guarded runtime badge configuration updates with m_spawn_config_mutex so pending-config refreshes rebuild spawn parameters without racing concurrent keyboard-hook spawns. src/overlay/overlay.cppL669-L690
  • Cached spawn parameters under the same mutex and routed badge creation through spawn_badge_internal to keep sprite selection and spawn throttling consistent during live reloads. src/overlay/overlay.cppL722-L820

Testing

  • ⚠️ cmake --preset linux (not run; GTK+-3.0 development files are missing in the container)

View task →

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +582 to +584
m_sprite_lookup = std::move(lookup);
m_sprites = std::move(sprites);
m_current_emoji_path = normalized;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reloading emoji atlas without mutex can corrupt selector state

The new load_atlas_from_path swaps m_sprite_lookup and m_sprites directly, but spawn_badge/select_sprite read these structures under m_spawn_config_mutex to generate badges. When a config reload changes the atlas, apply_pending_config calls this function before it acquires the mutex to rebuild the selector, so another thread can call spawn_badge while the atlas vectors have already been replaced but the selector still contains indices for the old arrays. Rendering later indexes m_sprites[b.sprite] and can hit out‑of‑range data, producing crashes during live reloads under key spam. The atlas update should also hold m_spawn_config_mutex (or defer swapping until inside the locked section) so the sprite table and selector stay consistent.

Useful? React with 👍 / 👎.

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex fix comments

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Added an AtlasData container and refactored the atlas loader to return optional atlas contents without mutating shared state directly, enabling synchronized installs. src/overlay/overlay.cppL125-L130 src/overlay/overlay.cppL481-L603
  • Applied atlas data and rebuilt the emoji selector under the spawn mutex during initialization to keep sprite lookups consistent before badge generation resumes. src/overlay/overlay.cppL246-L331
  • Updated pending-config application to load atlas resources first, then replace sprite tables and rebuild selection structures while holding the mutex, preventing races with badge spawns. src/overlay/overlay.cppL676-L707

Testing

  • ⚠️ cmake --preset linux (fails: GTK+-3.0 development files are missing in the container).

View task →

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +665 to +684
void Overlay::apply_pending_config() {
PendingConfig pending;
{
std::lock_guard<std::mutex> lock(m_pending_mutex);
if (!m_pending_config) {
return;
}
pending = *m_pending_config;
m_pending_config.reset();
}

auto normalized = normalize_path(pending.emoji_atlas);
bool atlas_changed = normalized != m_current_emoji_path;
std::optional<AtlasData> atlas;
if (atlas_changed) {
atlas = load_atlas_from_path(normalized);
if (atlas) {
m_badges.clear();
m_spawn_times.clear();
} else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Clearing badge containers races with concurrent spawns

When a config refresh arrives, apply_pending_config clears m_badges and m_spawn_times before taking m_spawn_config_mutex. Key presses on the hook thread call spawn_badge without holding any mutex for these containers. If the user reloads the configuration while keys are still being pressed, the reload thread running on the render loop can erase the vectors at the same time another thread pushes into them, leading to iterator invalidation and undefined behaviour (crash or corrupted badge state). The same mutex that guards spawn configuration should also wrap the container clear, or spawns should be stopped while the vectors are reset.

Useful? React with 👍 / 👎.

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex fix comments

@chatgpt-codex-connector
Copy link
Copy Markdown

Summary

  • Cleared badge and spawn-time containers while swapping in refreshed atlas data under the spawn mutex so live config reloads update sprite assets atomically. src/overlay/overlay.cppL664-L706
  • Routed badge spawns through the spawn mutex and consolidated badge creation inside spawn_badge_locked to synchronize throttling and RNG state with config refreshes. src/overlay/overlay.cppL751-L820

Testing

  • ⚠️ cmake --preset linux (fails: GTK+-3.0 development files are missing in the container)

View task →

@supermarsx
Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@supermarsx supermarsx merged commit 8b12fcf into main Nov 1, 2025
0 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant