Merge pull request #4852 from tobixen/fix/keyboard-state-hotplug-crash
fix(keyboard-state): fix segfault on device hotplug removal
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
#include <fmt/chrono.h>
|
||||
#include <gtkmm/label.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
@ -41,6 +42,7 @@ class KeyboardState : public AModule {
|
||||
|
||||
struct libinput* libinput_;
|
||||
std::unordered_map<std::string, struct libinput_device*> libinput_devices_;
|
||||
std::mutex devices_mutex_; // protects libinput_devices_
|
||||
std::set<int> binding_keys;
|
||||
|
||||
util::SleeperThread libinput_thread_, hotplug_thread_;
|
||||
|
||||
@ -232,9 +232,12 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
||||
}
|
||||
tryAddDevice(dev_path);
|
||||
} else if (event->mask & IN_DELETE) {
|
||||
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);
|
||||
libinput_devices_.erase(it);
|
||||
}
|
||||
}
|
||||
@ -245,6 +248,7 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
||||
}
|
||||
|
||||
waybar::modules::KeyboardState::~KeyboardState() {
|
||||
std::lock_guard<std::mutex> lock(devices_mutex_);
|
||||
for (const auto& [_, dev_ptr] : libinput_devices_) {
|
||||
libinput_path_remove_device(dev_ptr);
|
||||
}
|
||||
@ -256,11 +260,17 @@ auto waybar::modules::KeyboardState::update() -> void {
|
||||
|
||||
try {
|
||||
std::string dev_path;
|
||||
if (config_["device-path"].isString() &&
|
||||
libinput_devices_.find(config_["device-path"].asString()) != libinput_devices_.end()) {
|
||||
dev_path = config_["device-path"].asString();
|
||||
} else {
|
||||
dev_path = libinput_devices_.begin()->first;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(devices_mutex_);
|
||||
if (libinput_devices_.empty()) {
|
||||
return;
|
||||
}
|
||||
if (config_["device-path"].isString() &&
|
||||
libinput_devices_.find(config_["device-path"].asString()) != libinput_devices_.end()) {
|
||||
dev_path = config_["device-path"].asString();
|
||||
} else {
|
||||
dev_path = libinput_devices_.begin()->first;
|
||||
}
|
||||
}
|
||||
int fd = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY);
|
||||
auto dev = openDevice(fd);
|
||||
@ -308,10 +318,15 @@ auto waybar::modules ::KeyboardState::tryAddDevice(const std::string& dev_path)
|
||||
auto dev = openDevice(fd);
|
||||
if (supportsLockStates(dev)) {
|
||||
spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path);
|
||||
std::lock_guard<std::mutex> lock(devices_mutex_);
|
||||
if (libinput_devices_.find(dev_path) == libinput_devices_.end()) {
|
||||
auto device = libinput_path_add_device(libinput_, dev_path.c_str());
|
||||
libinput_device_ref(device);
|
||||
libinput_devices_[dev_path] = device;
|
||||
if (device) {
|
||||
libinput_device_ref(device);
|
||||
libinput_devices_[dev_path] = device;
|
||||
} else {
|
||||
spdlog::warn("keyboard-state: Failed to add device to libinput: {}", dev_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
libevdev_free(dev);
|
||||
|
||||
Reference in New Issue
Block a user