sml icon indicating copy to clipboard operation
sml copied to clipboard

queue_event default move assignment operator could cause improper destruction

Open palarson opened this issue 6 years ago • 1 comments

We've uncovered an issue when deferring events that hold shared pointers. The issue manifests when the event is on the back end of a defer queue deque and is erased. It turns out that the deque will move events on the queue backwards, and with the default move assignment operator, the move/dtor on the underlying data is not called properly.

The code below triggers the issue. The program prints

  1. 2
  2. 1
#include <queue>
#include <memory>
#include <boost/sml.hpp>

namespace sml = boost::sml;                                                     

struct e1 {
    std::shared_ptr<int> p;
};

struct e2 {};

struct e3 {};

struct table {
    auto operator()() noexcept {                                               
        using namespace sml;
        // clang-format off
        return make_transition_table(
            *"s1"_s + event<e1> / defer
            , "s1"_s + event<e2> / defer
            , "s1"_s + event<e3> = "s2"_s
            , "s2"_s + event<e1> / [](auto const& ev) { std::cout << *ev.p << ": " << ev.p.use_count() << std::endl; }
            , "s2"_s + event<e2> / defer
        );
        // clang-format on
    }
};

int main() {
    sml::sm<table, sml::defer_queue<std::deque>> sm;

    auto e1val = std::make_shared<int>(1);
    auto e2val = std::make_shared<int>(2);

    sm.process_event(e2{});
    sm.process_event(e2{});
    sm.process_event(e2{});
    sm.process_event(e2{});
    sm.process_event(e2{});
    sm.process_event(e2{});
    sm.process_event(e2{});    
    sm.process_event(e1{ e1val });
    sm.process_event(e1{ e2val });
    sm.process_event(e3{});
}

palarson avatar May 19 '19 19:05 palarson

Can this be closed, because https://github.com/boost-experimental/sml/pull/280 has been merged ?

lumpidu avatar Apr 03 '20 14:04 lumpidu