This commit addresses memory churn caused by implicit deep copies during traversal and allocation of complex structures:
- Replaced pass-by-value 'Json::Value' in std::ranges and range-based for loops with 'const auto&' or 'const Json::Value&' in Hyprland modules, preventing large JSON tree duplications on every update.
- Fixed implicit string and pair copies in UPower and CPU Frequency loops by converting 'auto' to 'const auto&' where possible.
- Added 'std::vector::reserve' calls before 'push_back' loops in MPRIS, Niri, and CFFI modules to prevent exponential vector reallocation during initialization.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Valgrind Massif profiling revealed that invoking Gtk::IconTheme::rescan_if_needed() inside SNI updateImage() and getIconByName() loops caused considerable memory churn and potential filesystem stat overhead whenever a system tray app pushed a metadata update.
This commit removes the rescan polling from the SNI proxy callback pipeline and the DefaultGtkIconThemeWrapper, restricting icon theme caching to load boundaries.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Memory profiling via Valgrind Massif indicated that 10-20% of peak memory allocations within the SNI loop resulted from copying DBus image data payloads via g_memdup2 before modifying them from ARGB to RGBA.
This commit optimizes the pixel conversion by directly allocating the final array via g_malloc and running the ARGB->RGBA transposition in a single pass while copying from the read-only GVariant buffer, entirely eliminating the intermediate g_memdup stage.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
- Replaced pass-by-value std::string parameters with const std::string&
or std::string_view to prevent SSO overallocations.
- Refactored static mapping functions in UPower to return
std::string_view instead of constructing std::string literals, enabling
perfect cache locality.
- Optimized string concatenation in hot loops (network IPs, inhibitor
lists, sway window marks) by using std::string::append() and
pre-reserving capacity instead of overloaded operator+ which produces
temporary heap instances.
These optimizations reduce high-frequency memory churn and overall heap
fragmentation within the main rendering loops.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Hyprland IPC had fd lifecycle risks on failure/shutdown paths and used a
spin-sleep listener model.
I initialized fd state defensively, tightened connect/close/shutdown handling,
moved to blocking read with newline framing, and added RAII-style fd cleanup in
socket1 reply paths.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
- Fix AudioBackend destructor: properly lock the PA mainloop before
disconnecting the context to prevent race conditions with PA callbacks
- Fix context leak on reconnect: call pa_context_unref() when the old
context is replaced after PA_CONTEXT_FAILED to avoid resource leaks
- Fix PA mainloop killed on reconnect (critical): PA_CONTEXT_TERMINATED
was unconditionally calling quit() on the mainloop, even during
reconnection when the old context fires TERMINATED after the new one
was created. This was killing the new context and preventing successful
reconnection, causing Waybar to appear frozen. The fix only quits
the mainloop when the terminating context is still the active one.
- Fix Wireplumber use-after-free: explicitly disconnect GObject signal
handlers for mixer_api_, def_nodes_api_, and om_ before clearing the
object references in the destructor to prevent callbacks from firing
with a destroyed self pointer.
- Fix GVariant memory leak in Wireplumber::handleScroll: unref the
GVariant created for the set-volume signal after the emit call.
Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com>
Don't attempt to use niri modules when socket connection fails. Prevents
rendering modules when running another compositor. In same concept as
previous Hyprland change
4295faa7c4
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
The keyboard-state module crashes with SIGSEGV in libinput_device_ref
when a new input device appears in /dev/input/.
Three bugs fixed:
1. Missing NULL check: tryAddDevice() calls libinput_path_add_device()
which returns NULL on failure, then immediately passes the result to
libinput_device_ref() without checking. On laptops, virtual input
devices (power buttons, lid switch, etc.) appear and disappear in
/dev/input/ triggering the hotplug handler; if libinput can't open
one of these, the NULL return causes the segfault.
2. Missing cleanup on device removal: The IN_DELETE handler erased
devices from the map without calling libinput_path_remove_device(),
leaving dangling pointers in the libinput context.
3. Thread safety: libinput_devices_ was accessed from 3 threads
(main/GTK, libinput_thread_, hotplug_thread_) without any mutex.
Fixes#4851
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>