From 0e03c7a811ef477eae4465ffb3ff443e1b6e1e87 Mon Sep 17 00:00:00 2001 From: Christian Fillion Date: Wed, 16 Oct 2024 02:12:06 -0400 Subject: [PATCH 1/2] fix a segfault on signals received after main returns The waybar process does not exit instantaneously. Signals may be recevied after main has started freeing resources. When a worker thread is in `fgets` this time window can last forever. An easy way to duplicate the crash is pressing ^C twice with a Hyprland module. Thread 1 "waybar" received signal SIGSEGV, Segmentation fault. spdlog::sinks::sink::should_log (this=0x5f620b542ca5, msg_level=spdlog::level::info) at /usr/src/debug/spdlog/spdlog-1.14.1/include/spdlog/sinks/sink-inl.h:13 13 return msg_level >= level_.load(std::memory_order_relaxed); (gdb) p $_siginfo._sifields._sigfault.si_addr $1 = (void *) 0x5f620b542cad --- src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 679c66d6..442c530c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,6 +107,10 @@ int main(int argc, char* argv[]) { ret = client->main(argc, argv); } while (reload); + std::signal(SIGUSR1, SIG_IGN); + std::signal(SIGUSR2, SIG_IGN); + std::signal(SIGINT, SIG_IGN); + delete client; return ret; } catch (const std::exception& e) { From 92242f0b9d7f37f4ccf87f03b0c0ce30255d2d54 Mon Sep 17 00:00:00 2001 From: Christian Fillion Date: Wed, 16 Oct 2024 09:56:05 -0400 Subject: [PATCH 2/2] hyprland: fix a data race at startup between sockets 1 and 2 `Workspaces::*` and `IPC::startIPC` may both call `getSocketFolder` at the same time. This randomly causes crashes and/or corruption of the socket path. Typical crash A: [2024-10-16 07:42:09.987] [info] Hyprland IPC starting malloc(): unaligned tcache chunk detected [2024-10-16 07:42:09.987] [error] Hyprland IPC: Unable to connect? Thread 1 "waybar" received signal SIGABRT, Aborted. (gdb) bt #0 __pthread_kill_implementation (threadid=, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44 (omitted for brievety) #9 0x00007ffff64ae745 in operator new (sz=sz@entry=296) at /usr/src/debug/gcc/gcc/libstdc++-v3/libsupc++/new_op.cc:50 #10 0x00007ffff65ab1f1 in std::filesystem::__cxx11::path::_List::_Impl::copy (this=0x555555a23350) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++17/fs_path.cc:249 #11 0x00007ffff65ab3bd in std::filesystem::__cxx11::path::_List::_List (this=0x7fffffff9d30, other=) at /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/unique_ptr.h:454 #12 0x00005555556f4ab1 in waybar::modules::hyprland::IPC::getSocket1Reply(std::__cxx11::basic_string, std::allocator > const&) () #13 0x00005555556f5e3d in waybar::modules::hyprland::IPC::getSocket1JsonReply(std::__cxx11::basic_string, std::allocator > const&) () #14 0x000055555571289c in waybar::modules::hyprland::Workspaces::setCurrentMonitorId() () Typical crash B: [2024-10-16 10:01:15.859] [info] Hyprland IPC starting [2024-10-16 10:01:15.859] [info] Loading persistent workspaces from Hyprland workspace rules Thread 8 "waybar" received signal SIGSEGV, Segmentation fault. (gdb) bt #0 std::__cxx11::basic_string, std::allocator >::_S_copy (__d=0x5555558fbca8 "/", __s=0x2973961a26d35726 , __n=1) at /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:433 (omitted for brievety) #15 waybar::modules::hyprland::IPC::getSocketFolder[abi:cxx11](char const*) (instanceSig=0x7fffffffe604 "4520b30d498daca8079365bdb909a8dea38e8d55_1729051218_1982280648") at ../src/modules/hyprland/backend.cpp:41 #16 0x000055555564230f in waybar::modules::hyprland::IPC::startIPC()::{lambda()#1}::operator()() const () at ../src/modules/hyprland/backend.cpp:70 #17 0x00007ffff64e1c34 in std::execute_native_thread_routine (__p=0x5555558119c0) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:104 #18 0x00007ffff62a339d in start_thread (arg=) at pthread_create.c:447 --- src/modules/hyprland/backend.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index 77f534e0..39341a14 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -18,6 +18,9 @@ namespace waybar::modules::hyprland { std::filesystem::path IPC::socketFolder_; std::filesystem::path IPC::getSocketFolder(const char* instanceSig) { + static std::mutex folderMutex; + std::unique_lock lock(folderMutex); + // socket path, specified by EventManager of Hyprland if (!socketFolder_.empty()) { return socketFolder_;