Discussion:
Race condition between io_service::run() and io_service::post()
(too old to reply)
ivan kostov
2016-12-09 12:26:43 UTC
Permalink
Dear ASIO users,

I want to use io_service as a thread pool for CPU intensive operations. It
is important for me to not loose any jobs pending in the queue when
stopping it. So according to the boost documentation I'm using
io_service::work for this purpose. When I need to stop the pool from
running I just destruct the work. However the unittest which you can find
at the end of the e-mail issues a race condition warning from the clang's
thread sanitizer ( clang 3.8, ubuntu 14.04 ).

After modifying the singal_and_unlock function in the posix_event.hpp the
warning is gone and the unittest runs without issues.

// Signal the event and unlock the mutex.
template <typename Lock>
void signal_and_unlock(Lock& lock)
{
BOOST_ASIO_ASSERT(lock.locked());
signalled_ = true;
// lock.unlock();
::pthread_cond_signal(&cond_); // Ignore EINVAL.
lock.unlock();
}

Is this a real bug, or am I doing something wrong ? If it is a bug, where
should I post it ?

Thank you in advance,
Ivan


Unittest

BOOST_AUTO_TEST_CASE(ioServiceShallWaitForPendingJobs)
{
auto test = []()
{
boost::asio::io_service service;
std::unique_ptr<boost::asio::io_service::work> work (new
boost::asio::io_service::work(service));
std::thread t(
[&service]()
{
service.run();
}
);
std::atomic_bool called{false};
service.post(
[&called]()
{
std::this_thread::sleep_for (std::chrono::milliseconds(50));
called = true;
}
);
std::this_thread::sleep_for (std::chrono::milliseconds(1));

work.reset(); // -> leak
t.join();
BOOST_REQUIRE(called);
};

for( size_t i = 0 ; i < 100000; ++i)
{
BOOST_TEST_MESSAGE(i);
test();
}
}

Loading...