Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sway): resolve destruction dependency between Ipc and SleeperThread #578

Merged
merged 1 commit into from
Feb 6, 2020

Conversation

alebastr
Copy link
Contributor

@alebastr alebastr commented Feb 5, 2020

Could fix some rare crashes when disconnecting monitors. I'm still not satisfied with the change but it works and I don't think I'll have a better fix anytime soon.

Differences from the first attempt: Ipc now owns the SleeperThread

AddressSanitizer backtrace:

=================================================================
==78099==ERROR: AddressSanitizer: heap-use-after-free on address 0x6030001b2ce8 at pc 0x000000ac9815 bp 0x7f4c7d1ea570 sp 0x7f4c7d1ea568
READ of size 8 at 0x6030001b2ce8 thread T7
    #0 0xac9814 in std::__cxx11::list<sigc::slot_base, std::allocator<sigc::slot_base> >::empty() const /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/stl_list.h:1052:38
    #1 0xac8f60 in sigc::internal::signal_emit1<void, waybar::modules::sway::Ipc::ipc_response const&, sigc::nil>::emit(sigc::internal::signal_impl*, waybar::modules::sway::Ipc::ipc_response const&) /usr/include/sigc++-2.0/sigc++/signal.h:1033:33
    #2 0xac8ba2 in sigc::signal1<void, waybar::modules::sway::Ipc::ipc_response const&, sigc::nil>::emit(waybar::modules::sway::Ipc::ipc_response const&) const /usr/include/sigc++-2.0/sigc++/signal.h:2951:14
    #3 0xac8737 in waybar::modules::sway::Ipc::handleEvent() /home/alebastr/sources/waybar/build-asan/../src/modules/sway/ipc/client.cpp:142:16
    #4 0xae1de7 in waybar::modules::sway::Window::worker()::$_0::operator()() const /home/alebastr/sources/waybar/build-asan/../src/modules/sway/window.cpp:34:12
    #5 0xae16c7 in std::_Function_handler<void (), waybar::modules::sway::Window::worker()::$_0>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/std_function.h:300:2
    #6 0x7958a9 in std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/std_function.h:690:14
    #7 0x7956c6 in waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()::operator()() const /home/alebastr/sources/waybar/build-asan/../include/util/sleeper_thread.hpp:27:9
    #8 0x795537 in void std::__invoke_impl<void, waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()>(std::__invoke_other, waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-redha
t-linux/9/../../../../include/c++/9/bits/invoke.h:60:14
    #9 0x795317 in std::__invoke_result<waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()>::type std::__invoke<waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()>(waybar::util::SleeperThread::operator=(std::
function<void ()>)::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/invoke.h:95:14
    #10 0x795260 in void std::thread::_Invoker<std::tuple<waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/thread:244:1
3
    #11 0x795137 in std::thread::_Invoker<std::tuple<waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()> >::operator()() /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/thread:251:11
    #12 0x79396a in std::thread::_State_impl<std::thread::_Invoker<std::tuple<waybar::util::SleeperThread::operator=(std::function<void ()>)::'lambda'()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/thread:195:13
    #13 0x7f4c96e496f3  (/lib64/libstdc++.so.6+0xd76f3)
    #14 0x7f4c96c134e1 in start_thread (/lib64/libpthread.so.0+0x94e1)
    #15 0x7f4c96b146d2 in clone (/lib64/libc.so.6+0x1016d2)

0x6030001b2ce8 is located 8 bytes inside of 32-byte region [0x6030001b2ce0,0x6030001b2d00)
freed by thread T0 here:
    #0 0x6c3c37 in operator delete(void*, unsigned long) (/home/alebastr/sources/waybar/build-asan/waybar+0x6c3c37)
    #1 0x7f4c984d7e26 in sigc::signal_base::~signal_base() (/lib64/libsigc-2.0.so.0+0x3e26)

previously allocated by thread T0 here:
    #0 0x6c2db7 in operator new(unsigned long) (/home/alebastr/sources/waybar/build-asan/waybar+0x6c2db7)
    #1 0x7f4c984d7a2c in sigc::signal_base::impl() const (/lib64/libsigc-2.0.so.0+0x3a2c)

Thread T7 created by T0 here:
    #0 0x60ba06 in pthread_create (/home/alebastr/sources/waybar/build-asan/waybar+0x60ba06)
    #1 0x7f4c96e499b8 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib64/libstdc++.so.6+0xd79b8)
    #2 0x7901c4 in waybar::util::SleeperThread::operator=(std::function<void ()>) /home/alebastr/sources/waybar/build-asan/../include/util/sleeper_thread.hpp:24:15
    #3 0xad9e66 in waybar::modules::sway::Window::worker() /home/alebastr/sources/waybar/build-asan/../src/modules/sway/window.cpp:32:11
    #4 0xad81a0 in waybar::modules::sway::Window::Window(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, waybar::Bar const&, Json::Value const&) /home/alebastr/sources/waybar/build-asan/../src/modules/sway/window.cpp
:14:3
    #5 0x6c6acd in waybar::Factory::makeModule(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /home/alebastr/sources/waybar/build-asan/../src/factory.cpp:23:18
    #6 0x98671d in waybar::Bar::getModules(waybar::Factory const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/alebastr/sources/waybar/build-asan/../src/bar.cpp:367:31
    #7 0x97e02a in waybar::Bar::setupWidgets() /home/alebastr/sources/waybar/build-asan/../src/bar.cpp:404:3
    #8 0x979da0 in waybar::Bar::Bar(waybar::waybar_output*, Json::Value const&) /home/alebastr/sources/waybar/build-asan/../src/bar.cpp:111:3
    #9 0x9c224e in std::_MakeUniq<waybar::Bar>::__single_object std::make_unique<waybar::Bar, waybar::waybar_output*, Json::Value const&>(waybar::waybar_output*&&, Json::Value const&) /usr/bin/../lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits
/unique_ptr.h:849:34
    #10 0x9b0464 in waybar::Client::handleOutputName(void*, zxdg_output_v1*, char const*) /home/alebastr/sources/waybar/build-asan/../src/client.cpp:123:35
    #11 0x7f4c96a0eaa7 in ffi_call_unix64 (/lib64/libffi.so.6+0x6aa7)

Ipc destructor closes socket and thus wakes up SleeperThread which was
waiting for socket data in Ipc::handleEvent.
Ipc::handleEvent then proceeds with sending signal to already destroyed
object, causing heap-use-after-free Address Sanitizer error.
@Alexays
Copy link
Owner

Alexays commented Feb 6, 2020

I was thinking about it, but it breaks the design that each module owns the thread, but it doesn't matter.

@Alexays
Copy link
Owner

Alexays commented Feb 6, 2020

Thanks :)

@Alexays Alexays merged commit e1215a6 into Alexays:master Feb 6, 2020
@alebastr alebastr deleted the ipc-use-after-free branch February 6, 2020 17:58
@alebastr
Copy link
Contributor Author

alebastr commented Feb 6, 2020

I was thinking about it, but it breaks the design that each module owns the thread, but it doesn't matter.

I'm more on the side of having one Ipc instance with single thread and multiple subscribers. For each event type SwayIPC class would send a shared_ptr<const JsonValue> to all subscribed to the event clients and they are free to hold that read-only object until they no longer require any data from it.
I won't have time to play with that concept for another couple of weeks though.

@alebastr alebastr restored the ipc-use-after-free branch February 7, 2020 02:55
@alebastr alebastr deleted the ipc-use-after-free branch February 7, 2020 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants