简体   繁体   中英

Unexpected variable value using Boost.Asio

I found some weird problem from my boost.asio project. so i made a sample-console project that same problem happening.

Here is the code:

class server
{
public:
    server()
        : m_acceptor(m_ios)
    {
        m_work.reset(new boost::asio::io_service::work(m_ios));
        m_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &m_ios));
    }

    virtual ~server()
    {
        m_work.reset();
        m_ios.stop();
        m_thread.join();
    }

    void do_test()
    {
        m_ios.post(boost::bind(&server::handle_test, this));
    }

private:
    void handle_test()
    {
        m_value = 1234;
        printf("server::handle_test() -> m_value %d.\n", m_value);
    }

    boost::shared_ptr<boost::asio::io_service::work> m_work;
    boost::asio::io_service m_ios;
    boost::thread m_thread;
    boost::asio::ip::tcp::acceptor m_acceptor;

public:
    int m_value;
};


void main()
{
    server s;
    s.do_test();

    _getch(); // wait for a while
    printf("main() -> m_value is %d.\n", s.m_value);

    _getch();
}

OK. so with this code, console output will be:

server::handle_test() -> m_value is 1234.

main() -> m_value is 1234.

Press any key to continue . . .

Right??

But strangely, actual console output is:

server::handle_test() -> m_value is 1234.

main() -> m_value is 0.

Press any key to continue . . .

Why???

Is there anyone who can explain this? and how can i fix it fundamentally?

Here is the whole project file and exe. https://www.dropbox.com/s/cflcmbuwgab1rxb/boost_asio_test.zip?dl=0

[Test Environment]

Windows Embedded 8.1 Industry Pro x64

Compiled with Visual Studio 2013 (VisualStudioVersion 12.0.31101.0)

You don't synchronize access to shared data from multiple threads.

This is data race.

Data races are Undefined Behaviour . Anything can happen.

Fix it by synchronizing access to m_value

UPDATE

When enabling the thread sanitizer ( -fsanitizer=thread on gcc/clang) you get this very specific report for Live On Coliru

==================
WARNING: ThreadSanitizer: data race (pid=27230)
Read of size 4 at 0x7fff488eb360 by main thread:
    #0 main /tmp/test.cpp:57 (test+0x0000004e2d82)

Previous write of size 4 at 0x7fff488eb360 by thread T1:
    #0 server::handle_test() /tmp/test.cpp:36 (test+0x00000051259c)
    #1 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
    #2 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
    #3 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
    #4 void boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, ...) /home/sehe/custom/boost/boost/asio/handler_invoke_hook.hpp:69 (test+0x000000516a35)
    #5 void boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >(boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&, boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >&) /home/sehe/custom/boost/boost/asio/detail/handler_invoke_helpers.hpp:37 (test+0x0000005167e0)
    #6 boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/completion_handler.hpp:68 (test+0x0000005162b7)
    #7 boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned long) /home/sehe/custom/boost/boost/asio/detail/task_io_service_operation.hpp:38 (test+0x000000532a63)
    #8 boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:372 (test+0x00000052db18)
    #9 boost::asio::detail::task_io_service::run(boost::system::error_code&) /home/sehe/custom/boost/boost/asio/detail/impl/task_io_service.ipp:149 (test+0x00000052721a)
    #10 boost::asio::io_service::run() /home/sehe/custom/boost/boost/asio/impl/io_service.ipp:59 (test+0x0000005266ce)
    #11 server::worker() /tmp/test.cpp:17 (test+0x000000518f19)
    #12 boost::_mfi::mf0<void, server>::operator()(server*) const /home/sehe/custom/boost/boost/bind/mem_fn_template.hpp:49 (test+0x00000051741e)
    #13 void boost::_bi::list1<boost::_bi::value<server*> >::operator()<boost::_mfi::mf0<void, server>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, server>&, boost::_bi::list0&, int) /home/sehe/custom/boost/boost/bind/bind.hpp:255 (test+0x00000051705a)
    #14 boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > >::operator()() /home/sehe/custom/boost/boost/bind/bind.hpp:895 (test+0x000000516cbf)
    #15 boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server*> > > >::run() /home/sehe/custom/boost/boost/thread/detail/thread.hpp:116 (test+0x00000051d5a9)
    #16 thread_proxy thread.cpp (libboost_thread.so.1.59.0+0x000000011aa9)

As if synchronized via sleep:
    #0 nanosleep <null> (test+0x000000475c10)
    #1 boost::this_thread::hiden::sleep_for(timespec const&) <null> (libboost_thread.so.1.59.0+0x000000012885)
    #2 void boost::this_thread::sleep_for<long, boost::ratio<1l, 1000l> >(boost::chrono::duration<long, boost::ratio<1l, 1000l> > const&) /home/sehe/custom/boost/boost/thread/v2/thread.hpp:112 (test+0x0000004e65fb)
    #3 main /tmp/test.cpp:56 (test+0x0000004e2b71)

Location is stack of main thread.

Thread T1 (tid=27234, running) created by main thread at:
    #0 pthread_create <null> (test+0x00000047aaf1)
    #1 boost::thread::start_thread_noexcept() <null> (libboost_thread.so.1.59.0+0x000000010ea9)
    #2 thread<boost::_bi::bind_t<void, boost::_mfi::mf0<void, server>, boost::_bi::list1<boost::_bi::value<server *> > > > /home/sehe/custom/boost/boost/thread/detail/thread.hpp:266 (test+0x000000519122)
    #3 server /tmp/test.cpp:13 (test+0x0000004e58b3)
    #4 main /tmp/test.cpp:53 (test+0x0000004e2855)

SUMMARY: ThreadSanitizer: data race /tmp/test.cpp:57 main
==================
server::handle_test() -> m_value 1234
main() -> m_value is 1234
ThreadSanitizer: reported 1 warnings

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM