Waybar icon indicating copy to clipboard operation
Waybar copied to clipboard

Crash during CPU hotplug

Open gergo-salyi opened this issue 6 months ago • 0 comments

On Linux the number of CPUs can change during runtime (see CPU hotplug). Users commonly use this to disable hyper-threading, E-cores, etc. For example:

# echo 0 > /sys/devices/system/cpu/cpu1/online
# echo 1 > /sys/devices/system/cpu/cpu1/online

Currently this can cause Waybar to crash:

$ waybar -l debug

/usr/include/c++/14.1.1/bits/stl_vector.h:1130: constexpr std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](size_type) [with _Tp = std::tuple<long unsigned int, long unsigned int>; _Alloc = std::allocator<std::tuple<long unsigned int, long unsigned int> >; reference = std::tuple<long unsigned int, long unsigned int>&; size_type = long unsigned int]: Assertion '__n < this->size()' failed.

[1]    345703 IOT instruction (core dumped)  waybar -l debug

The guilt is on waybar::modules::CpuUsage::getCpuUsage() which is iterating through 2 cpu-number-length vectors in src/modules/cpu_usage/common.cpp:64 unsafely assuming that the number of CPUs is unchanged and hence the length of the vectors is the same.

This results in accessing an out-of-bounds index which is caught by an assert if compiled with FORTIFY_SOURCE and aborts the program.

I'm writing a PR to fix this...

Backtrace:

#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x000072ed802a5463 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:78
#2  0x000072ed8024c120 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x000072ed802334c3 in __GI_abort () at abort.c:79
#4  0x000072ed804d3bb0 in std::__glibcxx_assert_fail (file=file@entry=0x5d8cf717d200 "/usr/include/c++/14.1.1/bits/stl_vector.h", line=line@entry=1130,
    function=function@entry=0x5d8cf7182a10 "constexpr std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](size_type) [with _Tp = std::tuple<long unsigned int, long unsigned int>; _Alloc = std::allocator<std::tuple<long unsi"..., condition=condition@entry=0x5d8cf7178837 "__n < this->size()")
    at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/assert_fail.cc:41
#5  0x00005d8cf70ba730 in std::vector<std::tuple<unsigned long, unsigned long>, std::allocator<std::tuple<unsigned long, unsigned long> > >::operator[] (this=<optimized out>,
    __n=<optimized out>) at /usr/include/c++/14.1.1/bits/stl_vector.h:1128
#6  std::vector<std::tuple<unsigned long, unsigned long>, std::allocator<std::tuple<unsigned long, unsigned long> > >::operator[] (this=0x5d8d0d326bf0, __n=<optimized out>)
    at /usr/include/c++/14.1.1/bits/stl_vector.h:1128
#7  waybar::modules::CpuUsage::getCpuUsage[abi:cxx11](std::vector<std::tuple<unsigned long, unsigned long>, std::allocator<std::tuple<unsigned long, unsigned long> > >&) (
    prev_times=std::vector of length 8, capacity 16 = {...}) at ../src/modules/cpu_usage/common.cpp:66
#8  0x00005d8cf70b3c0e in waybar::modules::Cpu::update (this=0x5d8d0d326a00) at ../src/modules/cpu.cpp:27
#9  0x00005d8cf708dfa7 in operator() (__closure=0x5d8d0d2b0a90) at ../src/bar.cpp:514
#10 sigc::adaptor_functor<waybar::Bar::getModules(const waybar::Factory&, const std::string&, waybar::Group*)::<lambda()> >::operator() (this=0x5d8d0d2b0a90)
    at /usr/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h:256
#11 sigc::internal::slot_call0<waybar::Bar::getModules(const waybar::Factory&, const std::string&, waybar::Group*)::<lambda()>, void>::call_it(sigc::internal::slot_rep *) (
    rep=0x5d8d0d2b0a60) at /usr/include/sigc++-2.0/sigc++/functors/slot.h:136
#12 0x000072ed81740bc2 in sigc::internal::signal_emit0<void, sigc::nil>::emit (impl=0x5d8d0d2f77f0) at /usr/include/sigc++-2.0/sigc++/signal.h:794
#13 sigc::signal0<void, sigc::nil>::emit (this=<optimized out>) at /usr/include/sigc++-2.0/sigc++/signal.h:2805
#14 sigc::signal0<void, sigc::nil>::operator() (this=<optimized out>) at /usr/include/sigc++-2.0/sigc++/signal.h:2821
#15 Glib::DispatchNotifier::pipe_io_handler (this=<optimized out>) at ../glibmm/glib/glibmm/dispatcher.cc:486
#16 0x000072ed81740f60 in sigc::slot1<bool, Glib::IOCondition>::operator() (_A_a1=@0x7ffd89be1ac4: Glib::IO_IN, this=<optimized out>)
    at /usr/include/sigc++-2.0/sigc++/functors/slot.h:675
#17 Glib::IOSource::dispatch (this=<optimized out>, slot=<optimized out>) at ../glibmm/glib/glibmm/main.cc:1377
#18 0x000072ed81741daf in Glib::Source::dispatch_vfunc (callback=<optimized out>, user_data=<optimized out>) at ../glibmm/glib/glibmm/main.cc:131
#19 0x000072ed81822ab9 in g_main_dispatch (context=0x5d8d0d1e0b40) at ../glib/glib/gmain.c:3344
#20 0x000072ed818849e7 in g_main_context_dispatch_unlocked (context=0x5d8d0d1e0b40) at ../glib/glib/gmain.c:4152
#21 g_main_context_iterate_unlocked.isra.0 (context=context@entry=0x5d8d0d1e0b40, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4217
#22 0x000072ed81821fc5 in g_main_context_iteration (context=context@entry=0x5d8d0d1e0b40, may_block=may_block@entry=1) at ../glib/glib/gmain.c:4282
#23 0x000072ed815fac66 in g_application_run (application=0x5d8d0d1cec90, argc=<optimized out>, argv=0x7ffd89be28c8) at ../glib/gio/gapplication.c:2712
#24 0x00005d8cf7051dfd in waybar::Client::main (this=0x5d8d0d158cc0, argc=<optimized out>, argv=<optimized out>) at /usr/include/glibmm-2.4/glibmm/refptr.h:259
#25 0x00005d8cf704f935 in main (argc=3, argv=0x7ffd89be28c8) at ../src/main.cpp:107

gergo-salyi avatar Aug 02 '24 13:08 gergo-salyi