[Boost-bugs] [Boost C++ Libraries] #8354: Only thread blocked in io_service.run() is not processing event loop.

Subject: [Boost-bugs] [Boost C++ Libraries] #8354: Only thread blocked in io_service.run() is not processing event loop.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-03-30 17:52:16


#8354: Only thread blocked in io_service.run() is not processing event loop.
----------------------------------------------------+-----------------------
 Reporter: Tanner Sansbury <twsansbury@…> | Owner: chris_kohlhoff
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: asio
  Version: Boost Development Trunk | Severity: Problem
 Keywords: |
----------------------------------------------------+-----------------------
 There is a concurrency issue in {{{task_io_service}}} (Boost 1.48+), that
 can leave a thread blocked in {{{io_service.run()}}}, waiting for its
 {{{wakeup_event}}} to be signaled. If thread A invokes
 {{{io_service::poll()}}}, runs the reactor while thread B invokes
 {{{io_service.run()}}}, becoming an idle thread ({{{op_queue_}}} is
 empty), then if no work is ready to run, thread A {{{io_service::poll()}}}
 returns {{{0}}} without waking up the idle thread B. This results in
 thread B remaining blocked on {{{io_service::run()}}}, but never
 processing the event loop.

 A side-by-side visualization illustrating the problem:
 {{{
           poll thread | main thread
 ---------------------------------------+---------------------------------------
   lock() |
   do_poll_one() |
   |-- pop task_operation_ from |
   | queue_op_ |
   |-- unlock() | lock()
   |-- create task_cleanup | do_run_one()
   |-- service reactor (non-block) | `-- queue_op_ is empty
   |-- ~task_cleanup() | |-- set thread as idle
   | |-- lock() | `-- unlock()
   | `-- queue_op_.push( |
   | task_operation_) |
   `-- task_operation_ is |
       queue_op_.front() |
       `-- return 0 | // still waiting on wakeup_event
   unlock() |
 }}}

 Attached files are:
 * Patch file that modifies {{{task_io_service.ipp}}} to sleep immediately
 after {{{do_poll_one}}} runs the reactor. This is only used to increase
 the changes of reproducing the concurrency problem.
 * Test application:
   * An asynchronous work loop via a timer that will print "." every 3
 seconds.
   * Spawn off a single thread that will poll the {{{io_service}}}.
   * Delay to allow the new thread time to poll {{{io_service}}}, and have
 main call {{{io_service::run()}} while the poll thread sleeps in
 {{{task_io_service::do_poll_one()}}}.
 * Patch with suggested fix that invokes {{{wake_one_thread_and_unlock()}}}
 before {{{do_poll_one}}} returning {{{0}}} if no work is to be done after
 running the reactor.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/8354>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:12 UTC