Strange behaviour from Disconnect()

Hi,
I am experiencing some strange things when trying to disconnect some signals. I will try to explain through a simpler example since my real application is a bit more messy.

I have an object of a class A, A1, to which I connect two objects of class B, B1 and B2. The B objects are ment to update each time A1 changes and be deleted if A1 is deleted. It is possible that B1 is deleted regardless of A1 and B2.

In class B’s ctor I have: B::B(A* ptr) : a(ptr){ a->Connect("Altered()","B",this,"Update()"); a->Connect("Destroyed()","B",this,"KillMe()"); }
and in the first attempt of a dtor I have:

B::~B(){ a->Disconnect(0,this,0); }
However of some reason this stop the Destroyed() signal to reach B2 if A1 is deleted. My conclusion is that B1’s dtor in some way also disconnects B2 from A1. Since each B is only connected to one A i tried an alternative dtor that disconnect all signals from objects of class A:

B::~B{ TQObject::Disconnect("A",0,this,0); }
This should be equivalent in my case to the previous dtor but now both B:s are deleted if A1 is. However now the “Altered()” signal is not disconnected leading to the situation that if B1 is deleted and A1 is altered afterwards, I get a segfault. My last dtor that at least does not cause any segfaults looks like:

B::~B(){ a->Disconnect("Altered()",this,"Update()"); TQObject::Disconnect("A","Destroyed()",this,"killMe()"); }
any other combination of the commands I have tried leads to segfaults in some situation.

I am very puzzled by this behaviour. Have I misunderstood how signals are supposed to be handled or is there a bug lurking around somewhere? My ROOT-version is 5.27/04.

Grateful for any help.

Hi,

When deleting a TQObject, all signals and connections are automatically removed:

[code]//______________________________________________________________________________
TQObject::~TQObject()
{
// TQObject Destructor.
// - delete all connections and signal list

if (!gROOT) return;

Destroyed(); // emit “Destroyed()” signal

if (fListOfSignals) {
fListOfSignals->Delete();
SafeDelete(fListOfSignals); // delete list of signals
}

// loop over all connections and remove references to this object
if (fListOfConnections) {
TIter next_connection(fListOfConnections);
TQConnection *connection;

  while ((connection = (TQConnection*)next_connection())) {
     TIter next_list(connection);
     TQConnectionList *list;
     while ((list = (TQConnectionList*)next_list())) {
        list->Remove(connection);
        if (list->IsEmpty()) SafeDelete(list);
     }
  }
  SafeDelete(fListOfConnections);

}
}[/code]
So you should not use Disconnect() in the destructor. Could you try?
And if you still have a problem, please post a small piece of code reproducing it.

Cheers, Bertrand.

Is that meant to take care of all connections i.e. both signals being sent to the object and signals being sent from the object (both directions)? If so I will post some code reproducing it as soon as I have time.

Yes, this should take care of it.

I have attached a small code example of an object of class B being signaled by an object of class A even though the first object is deleted. Depending on if the object still is present in memory or not the connected method may be executed or we will get a segfault.

classes.hpp (383 Bytes)main.cpp (231 Bytes)classesLinkDef.hpp (200 Bytes)
After compiling and running I get that the method doStuff() is executed twice but since b1 is deleted it should only happen once.

Hi,

OK, I see, this is weird and I’ll investigate (this is maybe due to the use of the RQ_OBJECT macro…)
Anyway, please take a look at your modified code, I think you will see how to do it properly. If there is still something not clear, feel free to ask!
And many thanks for the test case!

Cheers, Bertrand.
classesLinkDef.hpp (200 Bytes)
main.cpp (391 Bytes)
classes.hpp (766 Bytes)

Alas, I have tried using Disconnect the way you use it in the dtor (I guess the virtual keyword does not change anything?) but that disconnects both object as in the 1st case where I used Disconnect(0,this,0). The only way I can make everything work is by using the third ctor in my first post and that was what made me think this was really strange.

Thanks for your investigation and I hope you will find out what is happening. Please post here again if you find something.

Cheers

That’s weird, did you try the code I sent? How does it fails? For me it does:

[code]c:\Users\bellenot\Temp\kjan>test
calling a1->emit()
b1: Doing stuff
b2: Doing stuff
calling a1->emit()
b2: Doing stuff
deleting a1
b2: Please kill me

c:\Users\bellenot\Temp\kjan>[/code]
And Disconnect(0,this,0) disconnects the receiver, regardless of the signal (i.e. all signals), so it is to not receive the . a->Disconnect(“Altered()”,this,“Update()”); should be the right method (i.e. passing the signal names)
For more infos, please take a look at the the TQObject::Disconnect() documentation at: root.cern.ch/root/html/TQObject. … Disconnect%1
Anyway, if I find something I’ll let you know
Cheers, Bertrand.

Well, your code works but when I do the equivalent thing in my original code it does not which is of course very strange. However, my real application is much larger and messy so it could be that the problem is somewhere else. Is there a way of getting a list of all current connections in the application? That certainly would help debugging it. (I have read the documentation, that is why I am confused that it does not work)

Cheers, and thanks again for helping

You can access the list of signals and the list of connection for a given TQObject:

TList* GetListOfConnections() const TList* GetListOfSignals() const
Cheers, Bertrand.