Opened 4 years ago

Last modified 4 years ago

#13562 new Bugs

Missing null pointer check in compensating_work_started

Reported by: michael.lindig@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.66.0 Severity: Problem
Keywords: Cc:

Description

In boost/asio/detail/impl/scheduler.ipp(275):

void scheduler::compensating_work_started()
{
  thread_info_base* this_thread = thread_call_stack::contains(this);
  ++static_cast<thread_info*>(this_thread)->private_outstanding_work;
}

there is a missing null pointer check for this_thread, other routines have one!

I saw the error comming from boost/asio/detail/impl/epoll_reactor.ipp(712):

688 struct epoll_reactor::perform_io_cleanup_on_block_exit
689 {
690   explicit perform_io_cleanup_on_block_exit(epoll_reactor* r)
691     : reactor_(r), first_op_(0)
692   {
693   }
694 
695   ~perform_io_cleanup_on_block_exit()
696   {
697     if (first_op_)
698     {
699       // Post the remaining completed operations for invocation.
700       if (!ops_.empty())
701         reactor_->scheduler_.post_deferred_completions(ops_);
702 
703       // A user-initiated operation has completed, but there's no need to
704       // explicitly call work_finished() here. Instead, we'll take advantage of
705       // the fact that the scheduler will call work_finished() once we return.
706     }
707     else
708     {
709       // No user-initiated operations have completed, so we need to compensate
710       // for the work_finished() call that the scheduler will make once this
711       // operation returns.
712       reactor_->scheduler_.compensating_work_started();
713     }
714   }

Change History (1)

comment:1 by Vladimir Shapranov <equidamoid@…>, 4 years ago

Just found this ticket while googling for a crash I'm currently trying to fix:

(gdb) bt
#0  0x00d1d4e8 in boost::asio::detail::scheduler::compensating_work_started (this=0x1c02f90) at include/boost/asio/detail/impl/scheduler.ipp:275
#1  0x00d1d0bc in boost::asio::detail::epoll_reactor::perform_io_cleanup_on_block_exit::~perform_io_cleanup_on_block_exit (this=0x618feca4, __in_chrg=<optimized out>) at include/boost/asio/detail/impl/epoll_reactor.ipp:712
#2  0x00d1d334 in boost::asio::detail::epoll_reactor::descriptor_state::perform_io (this=0x1c05ef0, events=1) at include/boost/asio/detail/impl/epoll_reactor.ipp:730
#3  0x00d1d3b8 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete (owner=0x1c02f90, base=0x1c05ef0, ec=..., bytes_transferred=1) at include/boost/asio/detail/impl/epoll_reactor.ipp:774
#4  0x76c2e370 in boost::asio::detail::scheduler_operation::complete (bytes_transferred=1, ec=..., owner=0x1c02f90, this=<optimized out>) at include/boost/asio/detail/scheduler_operation.hpp:40
#5  boost::asio::detail::scheduler::do_run_one (ec=..., this_thread=..., lock=..., this=0x1c02f90) at include/boost/asio/detail/impl/scheduler.ipp:401
#6  boost::asio::detail::scheduler::run (ec=..., this=0x1c02f90) at include/boost/asio/detail/impl/scheduler.ipp:154
#7  boost::asio::io_context::run (this=<optimized out>) at include/boost/asio/impl/io_context.ipp:62
#

The relevant TLS entry is null:

(gdb) print boost::asio::detail::call_stack<boost::asio::detail::thread_context, boost::asio::detail::thread_info_base>::top_.tss_key_
$1 = 8
(gdb) print *((struct pthread*)pthread_self())->specific@32
$2 = {0x618ff42c, 0x0 <repeats 31 times>}

Reproduces when an executable linked against multiple shared libraries that are linked against static boost.

Note: See TracTickets for help on using tickets.