fix(keyboard-state): make device removal idempotent to stop libinput abort
On device unplug the inotify IN_DELETE handler removed the libinput device and unref'd it before erasing the entry from libinput_devices_. A repeated IN_DELETE event for the same path (observed as the "has been removed" log line printed twice) could reach an already-unlinked device and trigger a libinput list_remove assertion abort. Erase the map entry first (under devices_mutex_) so a second delete for the same path is a no-op, then call libinput_path_remove_device() and libinput_device_unref() exactly once per device pointer. Fixes #5143, #4443, #4566.
This commit is contained in:
@@ -268,10 +268,16 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
||||
std::lock_guard<std::mutex> lock(devices_mutex_);
|
||||
auto it = libinput_devices_.find(dev_path);
|
||||
if (it != libinput_devices_.end()) {
|
||||
spdlog::info("Keyboard {} has been removed.", dev_path);
|
||||
libinput_path_remove_device(it->second);
|
||||
libinput_device_unref(it->second);
|
||||
struct libinput_device* device = it->second;
|
||||
// Erase from the map first so that a second IN_DELETE event for the
|
||||
// same path becomes a no-op. This keeps removal idempotent and
|
||||
// ensures libinput_path_remove_device()/libinput_device_unref() are
|
||||
// called exactly once per device, avoiding a libinput list_remove
|
||||
// assertion abort on double removal.
|
||||
libinput_devices_.erase(it);
|
||||
spdlog::info("Keyboard {} has been removed.", dev_path);
|
||||
libinput_path_remove_device(device);
|
||||
libinput_device_unref(device);
|
||||
}
|
||||
}
|
||||
i += sizeof(struct inotify_event) + event->len;
|
||||
|
||||
Reference in New Issue
Block a user