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