-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Description
EventLoop::loop() executes posted functions inside a for(;;) loop without exception safety on the cleanup path. If the posted function throws, m_post_fn is never reset to nullptr and m_cv.notify_all() is never called. The calling thread, blocked in post() waiting for m_post_fn != &fn, hangs forever.
The cleanup code after the loop (closing file descriptors, resetting m_async_fns, notifying waiters) also runs outside any RAII guard, so all of it is skipped during stack unwinding.
In loop():
if (m_post_fn) {
Unlock(lock, *m_post_fn); // exception propagates from here
m_post_fn = nullptr; // skipped
m_cv.notify_all(); // skipped
}In post():
// waits forever: m_post_fn still == &fn, nobody notifies
m_cv.wait(lock.m_lock, [this, &fn]() { return m_post_fn != &fn; });After the loop exits via exception, ~EventLoop() hits KJ_ASSERT(m_post_fn == nullptr) and aborts. If assertions are disabled, the condition variable is destroyed while the posting thread still waits on it (undefined behavior).
Current callers avoid this because clientInvoke captures exceptions in std::exception_ptr rather than letting them propagate. The bug is latent but violates exception safety guarantees and will break any future caller that throws from a posted function.
Reproducer
#include <mp/proxy-io.h>
#include <mp/util.h>
#include <cstdio>
#include <future>
#include <stdexcept>
#include <thread>
int main()
{
std::promise<mp::EventLoop*> loop_ready;
std::thread loop_thread([&] {
mp::EventLoop loop("bugtest", [](mp::LogMessage log) {
if (log.level == mp::Log::Raise)
throw std::runtime_error(log.message);
});
loop_ready.set_value(&loop);
try {
loop.loop();
} catch (const std::exception& e) {
fprintf(stderr, "loop() threw: %s\n", e.what());
}
// ~EventLoop fires KJ_ASSERT(m_post_fn == nullptr) here
});
mp::EventLoop* loop = loop_ready.get_future().get();
std::thread post_thread([&] {
loop->post(kj::Function<void()>([] {
throw std::runtime_error("throw from posted fn");
}));
});
post_thread.detach();
loop_thread.join();
return 0;
}Run under Helgrind:
$ valgrind --tool=helgrind ./post_race_test
==276139== Helgrind, a thread error detector
==276139== Copyright (C) 2007-2024, and GNU GPL'd, by OpenWorks LLP et al.
==276139== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==276139== Command: ./test/post_race_test
==276139==
==276139== ---Thread-Announcement------------------------------------------
==276139==
==276139== Thread #1 is the program's root thread
==276139==
==276139== ---Thread-Announcement------------------------------------------
==276139==
==276139== Thread #2 was created
==276139== at 0x50BF823: clone (in /usr/lib/libc.so.6)
==276139== by 0x50BF980: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503B4ED: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503C16B: pthread_create (in /usr/lib/libc.so.6)
==276139== by 0x4CB96A1: std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4008F22: std::thread::thread<main::{lambda()#1}, , void>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008D0B: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Possible data race during read of size 8 at 0x51CE098 by thread #1
==276139== Locks held: none
==276139== at 0x400CE00: std::__uniq_ptr_impl<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>::_M_ptr() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C1C1: std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>::get() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400B4DD: std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>::operator*() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400A9BC: std::__future_base::_State_baseV2::wait() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C861: std::__basic_future<mp::EventLoop*>::_M_get_result() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400BD32: std::future<mp::EventLoop*>::get() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008D2A: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== This conflicts with a previous write of size 8 by thread #2
==276139== Locks held: none
==276139== at 0x400CED2: std::enable_if<std::__and_<std::__not_<std::__is_tuple_like<std::__future_base::_Result_base*> >, std::is_move_constructible<std::__future_base::_Result_base*>, std::is_move_assignable<std::__future_base::_Result_base*> >::value, void>::type std::swap<std::__future_base::_Result_base*>(std::__future_base::_Result_base*&, std::__future_base::_Result_base*&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C318: std::__uniq_ptr_impl<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>::swap(std::__uniq_ptr_impl<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400B7D6: std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>::swap(std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400ACCF: std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400CE89: void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C213: std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400B574: std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C236: std::once_flag::_Prepare_execution::_Prepare_execution<std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x51ce098 is 24 bytes inside a block of size 48 alloc'd
==276139== at 0x488C093: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x400ECB8: std::__new_allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_State_baseV2, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400E3A6: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_State_baseV2, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_State_baseV2, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_State_baseV2, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400D98C: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::__future_base::_State_baseV2, std::allocator<void>>(std::__future_base::_State_baseV2*&, std::_Sp_alloc_shared_tag<std::allocator<void> >) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400D009: std::__shared_ptr<std::__future_base::_State_baseV2, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>>(std::_Sp_alloc_shared_tag<std::allocator<void> >) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400C402: std::shared_ptr<std::__future_base::_State_baseV2>::shared_ptr<std::allocator<void>>(std::_Sp_alloc_shared_tag<std::allocator<void> >) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400B8E6: std::shared_ptr<std::__future_base::_State_baseV2> std::make_shared<std::__future_base::_State_baseV2>() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400BA6D: std::promise<mp::EventLoop*>::promise() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008CF0: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Block was alloc'd by thread #1
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Possible data race during read of size 8 at 0x51CE100 by thread #1
==276139== Locks held: none
==276139== at 0x400BD43: std::future<mp::EventLoop*>::get() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008D2A: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== This conflicts with a previous write of size 8 by thread #2
==276139== Locks held: none
==276139== at 0x400EB56: std::__future_base::_Result<mp::EventLoop*>::_M_set(mp::EventLoop*&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400E8FA: std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400E617: std::unique_ptr<std::__future_base::_Result<mp::EventLoop*>, std::__future_base::_Result_base::_Deleter> std::__invoke_impl<std::unique_ptr<std::__future_base::_Result<mp::EventLoop*>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>&>(std::__invoke_other, std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400DBDA: std::enable_if<is_invocable_r_v<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>&>, std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> >::type std::__invoke_r<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>&>(std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400D1B9: std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_State_baseV2::_Setter<mp::EventLoop*, mp::EventLoop*&&> >::_M_invoke(std::_Any_data const&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400B839: std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400ACB1: std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x400CE89: void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x51ce100 is 16 bytes inside a block of size 32 alloc'd
==276139== at 0x488C093: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x400BA7F: std::promise<mp::EventLoop*>::promise() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008CF0: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Block was alloc'd by thread #1
==276139==
==276139== ---Thread-Announcement------------------------------------------
==276139==
==276139== Thread #3 was created
==276139== at 0x50BF823: clone (in /usr/lib/libc.so.6)
==276139== by 0x50BF980: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503B4ED: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503C16B: pthread_create (in /usr/lib/libc.so.6)
==276139== by 0x4CB96A1: std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x40090A8: std::thread::thread<main::{lambda()#2}, , void>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008D55: main (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Possible data race during read of size 8 at 0x5DBBB58 by thread #3
==276139== Locks held: none
==276139== at 0x4011264: mp::EventLoop::post(kj::Function<void ()>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008C75: main::{lambda()#2}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C30: void std::__invoke_impl<void, main::{lambda()#2}>(std::__invoke_other, main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BAE: std::__invoke_result<main::{lambda()#2}>::type std::__invoke<main::{lambda()#2}>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B3D: void std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009AF5: std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009A7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#2}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50BF833: clone (in /usr/lib/libc.so.6)
==276139== Address 0x5dbbb58 is on thread #2's stack
==276139== in frame #9, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Thread #2: Bug in libpthread: write lock granted on mutex/rwlock which is currently wr-held by a different thread
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401654E: std::unique_lock<std::mutex>::unique_lock(std::mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E32: mp::Lock::Lock(mp::Mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010C2F: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Lock at 0x5DBBBA0 was first observed
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401654E: std::unique_lock<std::mutex>::unique_lock(std::mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E32: mp::Lock::Lock(mp::Mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010A4B: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x5dbbba0 is on thread #2's stack
==276139== in frame #1, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139== Possible data race during read of size 8 at 0x5DBBB68 by thread #2
==276139== Locks held: none
==276139== at 0x4010C37: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50BF833: clone (in /usr/lib/libc.so.6)
==276139==
==276139== This conflicts with a previous write of size 8 by thread #3
==276139== Locks held: 1, at address 0x5DBBBA0
==276139== at 0x40112D9: mp::EventLoop::post(kj::Function<void ()>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008C75: main::{lambda()#2}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C30: void std::__invoke_impl<void, main::{lambda()#2}>(std::__invoke_other, main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BAE: std::__invoke_result<main::{lambda()#2}>::type std::__invoke<main::{lambda()#2}>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B3D: void std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009AF5: std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009A7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#2}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== Address 0x5dbbb68 is on thread #2's stack
==276139== in frame #1, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Thread #2 unlocked lock at 0x5DBBBA0 currently held by thread #3
==276139== at 0x4895369: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C5D: std::mutex::unlock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x40165C1: std::unique_lock<std::mutex>::unlock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E4D: mp::Lock::unlock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401A437: mp::UnlockGuard<mp::Lock>::UnlockGuard(mp::Lock&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401803D: void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010C5C: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Lock at 0x5DBBBA0 was first observed
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401654E: std::unique_lock<std::mutex>::unique_lock(std::mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E32: mp::Lock::Lock(mp::Mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010A4B: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x5dbbba0 is on thread #2's stack
==276139== in frame #7, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Possible data race during read of size 8 at 0x65BCC88 by thread #2
==276139== Locks held: none
==276139== at 0x401ACD6: kj::Own<kj::Function<void ()>::Iface, decltype(nullptr)>::operator*() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x40181A9: kj::Function<void ()>::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4018049: void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010C5C: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== Address 0x65bcc88 is on thread #3's stack
==276139== in frame #7, created by main::{lambda()#2}::operator()() const (???:)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Possible data race during read of size 8 at 0x51CF080 by thread #2
==276139== Locks held: none
==276139== at 0x40181AA: kj::Function<void ()>::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4018049: void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010C5C: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50BF833: clone (in /usr/lib/libc.so.6)
==276139== Address 0x51cf080 is 0 bytes inside a block of size 16 alloc'd
==276139== at 0x488C093: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x400929E: kj::Own<kj::Function<void ()>::Impl<main::{lambda()#2}::operator()() const::{lambda()#1}>, decltype(nullptr)> kj::heap<kj::Function<void ()>::Impl<main::{lambda()#2}::operator()() const::{lambda()#1}>, main::{lambda()#2}::operator()() const::{lambda()#1}>(main::{lambda()#2}::operator()() const::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008FE9: kj::Function<void ()>::Function<main::{lambda()#2}::operator()() const::{lambda()#1}>(main::{lambda()#2}::operator()() const::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008C66: main::{lambda()#2}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C30: void std::__invoke_impl<void, main::{lambda()#2}>(std::__invoke_other, main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BAE: std::__invoke_result<main::{lambda()#2}>::type std::__invoke<main::{lambda()#2}>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B3D: void std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009AF5: std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009A7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#2}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50BF833: clone (in /usr/lib/libc.so.6)
==276139== Block was alloc'd by thread #3
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Thread #2: Bug in libpthread: write lock granted on mutex/rwlock which is currently wr-held by a different thread
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E69: mp::Lock::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401A456: mp::UnlockGuard<mp::Lock>::~UnlockGuard() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4018075: void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010C5C: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139== ----------------------------------------------------------------
==276139==
==276139== Thread #2 unlocked lock at 0x5DBBBA0 currently held by thread #3
==276139== at 0x4895369: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C5D: std::mutex::unlock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x40165C1: std::unique_lock<std::mutex>::unlock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401657D: std::unique_lock<std::mutex>::~unique_lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4015D49: mp::Lock::~Lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4011005: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Lock at 0x5DBBBA0 was first observed
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401654E: std::unique_lock<std::mutex>::unique_lock(std::mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E32: mp::Lock::Lock(mp::Mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010A4B: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x5dbbba0 is on thread #2's stack
==276139== in frame #6, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139==
loop() threw: throw from posted fn
==276139== ----------------------------------------------------------------
==276139==
==276139== Lock at 0x5DBBBA0 was first observed
==276139== at 0x4894C2A: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==276139== by 0x4014C11: std::mutex::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4016614: std::unique_lock<std::mutex>::lock() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x401654E: std::unique_lock<std::mutex>::unique_lock(std::mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4014E32: mp::Lock::Lock(mp::Mutex&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4010A4B: mp::EventLoop::loop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ACC: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== Address 0x5dbbba0 is on thread #2's stack
==276139== in frame #2, created by main::{lambda()#1}::operator()() const (???:)
==276139==
==276139== Possible data race during read of size 8 at 0x5DBBB68 by thread #2
==276139== Locks held: none
==276139== at 0x4017725: kj::_::DebugComparison<kj::Function<void ()>*&, decltype(nullptr)> kj::_::DebugExpression<kj::Function<void ()>*&>::operator==<decltype(nullptr)>(decltype(nullptr)&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x40104BF: mp::EventLoop::~EventLoop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ADB: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C6D: void std::__invoke_impl<void, main::{lambda()#1}>(std::__invoke_other, main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BF3: std::__invoke_result<main::{lambda()#1}>::type std::__invoke<main::{lambda()#1}>(main::{lambda()#1}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B69: void std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B11: std::thread::_Invoker<std::tuple<main::{lambda()#1}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009ABF: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#1}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x503B98A: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50BF833: clone (in /usr/lib/libc.so.6)
==276139==
==276139== This conflicts with a previous write of size 8 by thread #3
==276139== Locks held: 1, at address 0x5DBBBA0
==276139== at 0x40112D9: mp::EventLoop::post(kj::Function<void ()>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008C75: main::{lambda()#2}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C30: void std::__invoke_impl<void, main::{lambda()#2}>(std::__invoke_other, main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BAE: std::__invoke_result<main::{lambda()#2}>::type std::__invoke<main::{lambda()#2}>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B3D: void std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009AF5: std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009A7F: std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::{lambda()#2}> > >::_M_run() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4CB95A3: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== Address 0x5dbbb68 is on thread #2's stack
==276139== in frame #2, created by main::{lambda()#1}::operator()() const (???:)
==276139==
terminate called after throwing an instance of 'kj::ExceptionImpl'
what(): mp/proxy.cpp:216: failed: expected m_post_fn == nullptr [65bcc80 == nullptr]
stack: 401052d 4008adb 4009c6d 4009bf3 4009b69 4009b11 4009abf 4cb95a3 503b98a 50bf833
==276139==
==276139== Process terminating with default action of signal 6 (SIGABRT): dumping core
==276139== at 0x503D90C: ??? (in /usr/lib/libc.so.6)
==276139== by 0x4FE339F: raise (in /usr/lib/libc.so.6)
==276139== by 0x4FCA579: abort (in /usr/lib/libc.so.6)
==276139== by 0x4C6BBF5: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4C85EB9: ??? (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4C6B5D8: std::terminate() (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4C86175: __cxa_throw (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4B65249: ??? (in /usr/lib/libkj.so.1.2.0)
==276139== by 0x4B713E2: kj::throwFatalException(kj::Exception&&, unsigned int) (in /usr/lib/libkj.so.1.2.0)
==276139== by 0x4B7146A: kj::_::Debug::Fault::fatal() (in /usr/lib/libkj.so.1.2.0)
==276139== by 0x401052D: mp::EventLoop::~EventLoop() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008ADB: main::{lambda()#1}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== ----------------------------------------------------------------
==276139==
==276139== Thread #3: Exiting thread still holds 1 lock
==276139== at 0x5043FE2: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503816B: ??? (in /usr/lib/libc.so.6)
==276139== by 0x50387DB: ??? (in /usr/lib/libc.so.6)
==276139== by 0x503AE9D: pthread_cond_wait (in /usr/lib/libc.so.6)
==276139== by 0x4CAEEA0: std::condition_variable::wait(std::unique_lock<std::mutex>&) (in /usr/lib/libstdc++.so.6.0.34)
==276139== by 0x4013150: void std::condition_variable::wait<mp::EventLoop::post(kj::Function<void ()>)::{lambda()#3}>(std::unique_lock<std::mutex>&, mp::EventLoop::post(kj::Function<void ()>)::{lambda()#3}) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4011323: mp::EventLoop::post(kj::Function<void ()>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4008C75: main::{lambda()#2}::operator()() const (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009C30: void std::__invoke_impl<void, main::{lambda()#2}>(std::__invoke_other, main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009BAE: std::__invoke_result<main::{lambda()#2}>::type std::__invoke<main::{lambda()#2}>(main::{lambda()#2}&&) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009B3D: void std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139== by 0x4009AF5: std::thread::_Invoker<std::tuple<main::{lambda()#2}> >::operator()() (in /home/mohamed/dev/libmultiprocess/build/test/post_race_test)
==276139==
==276139==
==276139== Use --history-level=approx or =none to gain increased speed, at
==276139== the cost of reduced accuracy of conflicting-access information
==276139== For lists of detected and suppressed errors, rerun with: -s
==276139== ERROR SUMMARY: 13 errors from 12 contexts (suppressed: 30 from 22)
[1] 276139 IOT instruction (core dumped) valgrind --tool=helgrind ./test/post_race_test