How to _really_ disconnect pipeline?

Hello,

I am generating images in a loop and adding to multi-input filter. In pseudo-code

for(;;) {
  filterA = A::New()
  /* Do something with filterA, e.g. set a filename and read an image() */
  filterB = B::New()
  filterB->SetInput(filterA->GetOutput())
  filterB->Update()
  image = filterB->GetOutput()
  image->DisconnectPipeline()
  filterC->PushBackInput(image)
} 

filterC->Update()

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?

Thanks in advance and merry christmas!

Hello @kaspermarstal,

Here, is

filterB->Update();
ImageType:::Pointer output = filterB->GetOutput();
// PushBackInput internally uses a SmartPointer to increase the image's reference count
filterC->PushBackInput(output);

intended?

Merry Christmas! :christmas_tree:

1 Like

Yes, thank you. Updated question :slight_smile:

The described behavior does seem odd.

A minimal, compilable example source code will help determine specifically what is happening.

Because you name the results (or “output”): “input”, are you trying to use a circular pipeline?

I complete minimal example is needed, as Matt said. It’s likely that in the process of narrowing and isolating the problematic scenario you will determine the problem.

1 Like

@blowekamp Not trying a circular pipeline no. I updated the pseudocode and will make a minimal example.

@matt.mccormick What is it that you find odd? That m_Source is not nullptr after call to DisconnectPipeline? If not, what is the expected behaviour?

Thanks for your input!

In any case, there should not be a segfault. But, the pseudo-code does not look correct. A runnable example should help.

1 Like

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


is not being called.

3 Likes

Thank you for your detailed reply Jim. I will do this.