Boost logo

Boost :

From: andreas_m_huber (andreas_at_[hidden])
Date: 2002-01-03 18:31:28


Hello there

I had a quick look at the new Signals library and I'm having
difficulties how to safely use it in an MT environment. For example,
if not used _very_ carefully, the proposed boost::trackable baseclass
seems to make otherwise inncocent-looking code vulnerable to race
conditions.

Example (derived from the signals library documentation, does not
compile):

struct Provider {
  Provider( const std::string & name ) : name( name ) {}

  boost::signal1< void, const std::string & > SomeSignal;

  void DoIt() { SomeSignal( name ); }

private:
  std::string name;
};

struct SomeSlot : public boost::trackable {
  // connects itself with the passed provider and relies on the
  // base class destructor to be disconnected
  SomeSlot( Provider & provider ) {
    provider.SomeSignal.connect(
      boost::bind( &SomeSlot::DoIt, this, _1 ) );
  }

  void DoIt( const std::string & );

private:
  // some Mutex protected members accessed by DoIt
};

Provider myProvider( "OK!" );
SomeSlot * pSlot = new SomeSlot( myProvider );

myProvider.DoIt(); // prints OK!

// here pSlot is handed to thread 2
delete pSlot; // executed by thread 2

myProvider.DoIt(); // executed by thread 1

The base class portion of an object is destructed after the derived
class members, so the following could occur:
- thread 2 has already destructed the members of SomeSlot but has not
yet destructed the boost::trackable base class.
- thread 1 fully executes myProvider.DoIt() before thread 2 has a
chance to complete the destruction of the object (and thus

remove the SomeSlot object from the slot list).

--> Thread 1 accesses the already destructed subobject(s) of SomeSlot.

I cannot see how to _easily_ avoid this problem if one solely relies
on boost::trackable for connection management.

I believe the same thing could happen even if manual connection
management is used (although less likely): One thread makes a
"call" through the signal while another thread disconnects the slot.
It could AFAICT happen that the slot is called _after_ it has been
disconnected (which of course could lead to all sorts of problems).

IMPORTANT: This is not meant as a critisism to the signals library or
its designer. I (with my limited experience in multithreading) simply
cannot figure out how to use the library safely in an MT environment.

Andreas


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk