I am generating images in a loop and adding to multi-input filter. In pseudo-code
filterA = A::New()
/* Do something with filterA, e.g. set a filename and read an image() */
filterB = B::New()
image = filterB->GetOutput()
However, I get a segfault when updating filterC because this update is propagated to the upstream of the disconnected input object: The disconnected inputs’ m_Source still points the filterB (which has now gone out of scope) after the call to DisconnectPipeline. This is because DisconnectPipeline only calls m_Source->SetOutput(NULLPTR) on the input object, but the m_Source itself is not set to null. Therefore, when UpdateOutputInformation() tries to propagate information to the source (which has now gone out of scope) the segfault occurs.
I could move filterB out of the loop to avoid that it goes out of scope. But that doesnt solve the underlying problem: The disconnected input is still connected to filterB via it’s m_Source and update calls are propagated upstream.
Clearly there is something I have overlooked. I dont understand why any downstream updates should be propagated the upstream of a disconnected object (the way DisconnectPipeline is implemented).
To solve this particular use case, I need to set m_Source on the input to nullptr (what I previously thought DisconnectPipeline did). How do I achieve this?
A call to DisconnectPipeline() triggers a set of calls to return the pipeline and the data object to a proper state. DisconnectPipeline() calls ProcessObject::SetOutput() to remove the data object from the list of outputs. This triggers a call a DataObject::SetSource() to clear the source field of the data object being disconnected. So the intent is that from the user code, only a call to DisconnectPipeline() is needed, with the source field of the data object being reset automatically.
There are a few conditionals in this call stack, so you could be hitting on one of these.
Or, it could be something related to the lifecycle of the smart pointers to “image”.
I would put a breakpoint at the image->DisconnectPipeline() call and walk the calls to see why