Modify

Opened 6 weeks ago

#13283 new Bugs

boost log crash during thread termination

Reported by: Marco Strohner <marco.strohner@…> Owned by:
Milestone: To Be Determined Component: None
Version: Boost 1.64.0 Severity: Problem
Keywords: Cc:

Description

I'm using boost 1.64 on iOS and Android. Adding trivial log causes a crash during thread termination.

Removing more and more code produces the follwing example code for reproducing the issue. In the default settings in XCode it randomly crashed.

Enabling all memory related helper in the Scheme (memory guards, ...) helps because it crashes more reproducible and procudes better callstacks.

My result of debugging is:

  1. the first executed log line -> creates a thread local storage object with the severity - this severity is stored in severity_level_holder which creates a thread local storage with an automatic deleter (boost::this_thread::at_thread_exit(boost::bind(checked_deleter< uintmax_t >(), p));) - saw this in severity_level.cpp
  2. normal Code -> logging works
  3. thread terminates
  4. the destructor of the TestClass? is called and adds a result to the internal promise -> logging works
  5. the automatic deleter is called and frees the memory block for the severity.
  6. the TestClass? of the internal promise is destroyed -> logging crashes because it tries to read the destroyed severity memory block.
#include <memory>

#ifndef BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE
#endif

#ifndef BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#endif

#include <boost/thread/thread.hpp>
#include <boost/thread/future.hpp>
#include <boost/log/trivial.hpp>



class TestClass {
public:
  TestClass(bool shouldSet) : shouldSet_(shouldSet) {}

  virtual ~TestClass() {
    if (shouldSet_) {
      BOOST_LOG_TRIVIAL(warning) << "crashes here";
      promise_.set_value(std::unique_ptr<TestClass>(new TestClass(false)));
    }
  }

  bool shouldSet_;
  boost::promise<std::unique_ptr<TestClass>> promise_;
};


int main(int, char **) {
#define N 1

  auto wait_future = boost::async([](){
    auto task = []() {
      for (int i=0;i<1000;i++) {
        BOOST_LOG_TRIVIAL(warning) << "Create event #" << i;
        std::shared_ptr<TestClass> event = std::shared_ptr<TestClass>(new TestClass(false));
        boost::future<std::unique_ptr<TestClass>>  future = event->promise_.get_future();
        future.then([i](boost::future<std::unique_ptr<TestClass>>){BOOST_LOG_TRIVIAL(warning) << "event handled #" << i; });
        boost::async([event, i](){
          event->promise_.set_value(std::unique_ptr<TestClass>(new TestClass(true)));
          BOOST_LOG_TRIVIAL(warning) << "Destroy event #" << i;
        }).wait();
      }
    };
    boost::future<void> f[N];

    for(int j=0; j<N; j++){
      f[j] = boost::async(task);
    }
    for(int j=0; j<N; j++){
      f[j].wait();
    }

  });

  wait_future.wait_for(boost::chrono::seconds(10));
  return 0;
}

Attachments (0)

Change History (0)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The ticket will remain with no owner.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.