Closed LStruber closed 2 years ago
1. Regarding the Exception:
I had hard times understanding what was going on here... I'll try to explain it as simple as possible.
In MIA when renaming a node, a value_changed
signal is emited by the node_controller
, calling the controller_value_changed
function of pipeline_manager_tab.py
. This function recover the current pipeline (pipeline = self.pipelineEditorTabs.get_current_pipeline()
) and set it to the current editor (editor = self.pipelineEditorTabs.get_current_editor()
and editor.set_pipeline(pipeline)
).
Here is the thing: set_pipeline
function of Capsul pipeline_developper_view.py
create a new PipelineScene
(via release_pipeline
function) without properly deleting the former. Then the old scene of our current editor has residuals connections with the nodes.
Then, when iterating a pipeline in MIA (build_iterated_pipeline
function in pipeline_manager_tab.py
), the remove_trait
function calls the update_parameters
function of Capsul pipeline_developper_view.py
(update_parameters
is connected to user_trait_changed
) BOTH in current PipelineScene
and in the former one ! In the former, self.name
is still assigned to the old name of the node throwing the Exception describe above.
The more simple and elegant way I found to fix it is to properly delete the previous scene (if it exists) before creating a new one. This translate by adding those lines (l.2750) in release_pipeline
function of pipeline_developper_view.py
:
if self.scene:
self.scene.__del__()
Note that to remove properly all remaining connections, I also had to add:
self.changed.disconnect()
in the __del__()
method of the PipelineScene
(pipeline_developper_view.py
l.1524).
As these are modifications in Capsul, I'm not sure of all their implications, but it seems to solve the problem in MIA. If @denisri is OK, I'll go for a PR.
2. Regarding the error name when iterating a simple brick:
This problem was far more simpler, we just needed to properly rename the context_name
attributes of the renamed node.
Nevertheless, working on this point raised a question: when renaming a pipeline (ex. Spatial_preprocessing pipeline), do we want to also update all child nodes full names ? It is currently not done, and to my mind it should be (I coded a small function in the node controller doing that in my branch)
Currently, when renaming spatial_preprocessing_1_1
node spatial_preproc
, all child nodes are still named after the old name, for example Pipeline.spatial_preprocessing_1_1.new_segment_1
. The consequence is that after completion, brick name in Data Browser is spatial_preprocessing_1_1.new_segment_1
and not spatial_preproc.new_segment_1
.
3. Note that all described problems and fixes were observed and performed using CapsulNodeController (V2 controller) and I still have to check what happen when using V1 controller
great !
I just checked with the V1 controller. For 1. the Capsul modifications also solved the issue For 2. renaming child nodes can be done using the same function than for V2 controller
For the second point, I completely agree with you, we should also change the name of the children!
I agree with most, except that I suspect a more subtle problem for 1. Totally OK for 2.
For 1., the thing that puzzles me is that you are calling self.scene.__del__()
manually: this should not be done "by hand": when there are no remaining references on a python object, then it should be deleted automatically, and its __del__
method will be called automatically if it has one. If it is not called then
__del__
method on a still living object is definitely not good... Moreover calling __del__
does not destroy the object at all (__del__
is just the cleanup for an object which is about to be deleted) - basically you can't force an object deletion in python...gc.collect()
can help, but it may be very difficult to track why an objects still has references when it should not. To help debugging this the module objgraph
is very helpful (it saved my life several times)I agree with that, my only concern is : does it worth to look into why scene object is not automatically deleted for a 'minor' issue of renaming ? It seems that looking into that won't be a happy time :)
For you it's possibly not worth ;) For us (me) it's quite important to guarantee that the library works well and without errors...
Of course it is important ! The only thing I wanted to point out is that we can either fix the issue by a simple "patch" ensuring that the library works, or digging more deeply to understand precisely the why it happens and maybe find a better solution. Obviously the second solution is always better for the library, but as we have a lot to do, sometimes the first solution allows to focus on higher priorities...
To get back to our issue, without calling directly __del__
function, we can clean the old scene manually in release_pipeline
function :
if self.scene:
for gnode in self.scene.gnodes.values():
gnode._release()
del self.scene.gnodes
self.scene.changed.disconnect()
del self.scene
import gc
gc.collect()
if self.scene:
for gnode in self.scene.gnodes.values():
gnode._release()
del self.scene.gnodes
self.scene.changed.disconnect()
del self.scene
import gc
gc.collect()
it looks almost clean (for a patch), doesn't it?
If the scene is actually deleted after del self.scene
, or after gc.collect()
, then it's completely good. If not, then we still have a memory leak but it won't crash at once: it will be OK for the current issue, but we should open another one in capsul.
did you try to see if after this patch, self.scene still exists (by doing for example just an if hasattr()) ?
It prevents the crash but the __del__()
method of PipelineScene
is not called, then I guess it is not really deleted and the memory leak remains
Then there is still a leak, yes. We should open another ticket for that in Capsul. And you can push your modif to fix the current issue.
Closed with commit 793f1d26f157a2b1decc495ded9202f3800484ef (Capsul) and commit e7c2a206fe3e79bc581a5f8cf931cee0e59a4b24. The memory leak remains and the corresponding ticket has been open in Capsul.
Minimum steps to reproduce:
MIA close with following standard output:
Note that I do not reproduce this issue when iterating a simple brick (ex. smooth_1 brick renamed my_smooth) but the new iterated brick is named "iterated_smooth_1" instead of "iterated_my_smooth")