Skip to content

Conversation

@dskvr
Copy link

@dskvr dskvr commented Oct 14, 2025

Note

This is in response to hyprwm#5247 and hyprwm#4373

I chose to isolate the PR here to avoid polluting upstream pull requests with an experiment that may not be welcomed since corresponding issue/discussion were closed. Will change base branch upon request.

Problem

  • Binds referencing plugin-provided dispatchers (e.g., split:workspace) are parsed before plugins register those dispatchers.
  • This yields noisy startup/reload errors like “Invalid dispatcher …”, which later disappear once plugins load and trigger a config reload.
  • The noise desensitizes users to real errors and complicates plugin setups where binds must coexist with core fallbacks.

Proposal

  • Make bind parsing tolerant to unknown dispatchers while plugins are still loading.
  • Defer reporting of unknown dispatchers until plugin loads settle; then surface unresolved ones as a single, clear error message.
  • Track config-driven plugin loads to know when the set of plugins has stabilized.

Changes

ConfigManager.cpp
  • Bind parsing: unknown dispatcher no longer errors immediately; it is deferred.
    • File: src/config/ConfigManager.cpp (handleBind)
  • Track and clear deferrals per reload cycle.
    • Added field: m_deferredUnknownDispatchers (vector)
    • Cleared in resetHLConfig().
  • After handlePluginLoads() in postConfigReload, if no plugin loads are pending, surface all deferred unknown dispatchers as a single error and clear them.
    • Files: src/config/ConfigManager.cpp (postConfigReload), src/config/ConfigManager.hpp
PluginSystem.cpp
  • Track in-flight config-declared plugin loads.
    • Added std::atomic<int> m_pendingConfigPluginLoads and accessor isLoadingConfigPlugins().
    • File: src/plugins/PluginSystem.hpp
  • In updateConfigPlugins, count new plugins to load, increment the counter, decrement on completion (success/failure), and when the counter reaches zero schedule a cohesive g_pConfigManager->reload().
    • File: src/plugins/PluginSystem.cpp

Behavior

  • On first parse, binds to plugin dispatchers are accepted without error and deferred.
  • Once all config-declared plugins load (or fail) and the system stabilizes, any still-unknown dispatchers are reported once, clearly.
  • No changes to existing configuration syntax or plugin APIs; plugins continue to register dispatchers via HyprlandAPI::addDispatcherV2.

Rationale vs Alternatives

  • Avoids adding new config directives (e.g., “exec-after/source-after”) and avoids global reordering of parsing vs plugin loading.
  • Keeps validation strict once plugins stabilize while removing spurious early errors.

Potential Issues / Trade-offs

  • Delayed error reporting: typos in dispatcher names are surfaced after plugin loads settle, not immediately on first parse.
  • verify may no longer fail purely on plugin dispatchers being absent (since plugins are not loaded in verify), which could hide plugin-related bind mistakes during verification. This could be resolved with a keyword that suppresses the deferred behavior or log-levels
  • Manual (non-config) plugin loads are not tracked by the pending counter; a transient error could appear if deferrals are surfaced before a manual load completes. A subsequent reload will resolve it.
  • One aggregated reload is scheduled after all config plugin loads finish; per-plugin load still schedules its own reload. This can result in extra reloads; optimizing to suppress per-plugin reloads for config-driven loads could be a follow-up.
  • Deferred list is not deduplicated; repeated unknown names may appear more than once in the final message (kept simple for now).

Testing Notes

  • With plugin=/path/to/plugin.so and binds to plugin dispatchers:
    • No startup “Invalid dispatcher …” spam.
    • After plugins load successfully, binds exist and work.
    • If a plugin fails or is removed, a single error lists the unresolved dispatchers after loads settle.
  • Manual hyprctl plugin load still works; subsequent reload resolves binds.

Compatibility

  • No breaking changes to existing configs or plugin interfaces.
  • Minimal, isolated code paths; low maintenance overhead.

Test Script

  • Run automated test script:
    • bash scripts/run_deferral_test.sh
    • Builds Hyprland and the hyprtester plugin, runs a nested Hyprland with an isolated config, captures logs, and asserts:
      • Deferral before plugin load for a valid plugin dispatcher.
      • Continued deferral for an intentionally unknown dispatcher.
      • No “Invalid dispatcher” spam on first parse.
    • Logs and temp config path are printed on success/failure for deeper inspection.

@dskvr dskvr changed the title experiment: Stab at solving config race conditions with deferred config resolution Defer bind dispatcher validation until plugins finish loading Oct 14, 2025
@dskvr dskvr marked this pull request as draft October 14, 2025 15:21
@dskvr dskvr changed the base branch from main to feature/hyprpm-dev-mode October 14, 2025 15:46
@dskvr dskvr changed the base branch from feature/hyprpm-dev-mode to main October 14, 2025 15:47
@dskvr dskvr marked this pull request as ready for review October 14, 2025 15:51
@dskvr dskvr force-pushed the experiment/bind-race-condition branch from 266c86a to 1402f0a Compare October 14, 2025 16:50
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