Skip to content

napari-widget: Seg Fault When Deleting Data #433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
willGraham01 opened this issue Feb 24, 2025 · 11 comments · May be fixed by #570
Open

napari-widget: Seg Fault When Deleting Data #433

willGraham01 opened this issue Feb 24, 2025 · 11 comments · May be fixed by #570
Labels
bug Something isn't working GUI Graphical User Interface

Comments

@willGraham01
Copy link
Contributor

Describe the bug
We currently get a segmentation fault from inside Qt when deleting layers that the plugin has loaded.

To Reproduce

  • Fire up napari with the movement plugin loaded, napari -w movement
  • Load any valid dataset, EG DLC_single-mouse_EPM.predictions.h5 (as in the user-guide).
  • The slider and the "play" button will allow the user to move through the frames as expected.
  • Delete the imported layer created when loading the dataset, using the napari layers tab.
  • Load any valid dataset (even the same one) in again via the plugin.
  • The slider can now be manually dragged to move through the loaded image, but pressing "play" results in a seg-fault (see below).

Expected behaviour

There should be no segmentation fault here.

Additional context

First identified in #393

@willGraham01
Copy link
Contributor Author

My first thought is that the "deleting a layer" event is not being sent (or received by) the slider / play widget. To check for this;

  • Fire up napari, napari -w movement
  • Load any valid dataset, EG DLC_single-mouse_EPM.predictions.h5 (as in the user-guide).
  • Load another dataset as another layer (this could be a duplicate, worth checking if it is and is not as 2 cases).
  • Check whether the slider and the "play" button will allow the user to move through the frames as expected, and selecting the respective dataset layers and pressing play works as intended.
  • Select one of the two dataset layers using the napari layers tab, and then delete it. Be sure to select it before deleting it, do not do this all in one go.
  • Explicitly select the remaining layer dataset.
  • Check that the slider can now be manually dragged to move through the loaded image, and pressing "play" results doesn't give a seg-fault.

If we don't get the seg-fault, then it likely means that the slider / play button stores a reference to the dataset layer it is displaying. Explicitly clicking on a layer usually emits a signal that updates this reference. If we don't get a seg-fault in this case, then the issue is likely that the slider / play button does not interpret the "delete layer" signal correctly. (If we do get a seg-fault, I'm back at the drawing board).

Following on from this, my next check would be to investigate what napari does when the active / selected layer is deleted. We can repeat the above steps, but skip the "explicitly select the remaining layer dataset".

  • If we get a seg-fault, the culprit is almost certainly the delete action correctly deleting the layer, but the slider / play button NOT setting its reference to the active (now deleted) layer to NULL (or None in Python I guess), to flag that the object is now missing (and the user should not be able to press play).
  • If we don't get a seg-fault, I would be inclined to blame the issue on the fact that everything is being handled correctly, it's just undefined behaviour when the only layer is being deleted (and thus, napari cannot automatically switch to another active layer after deletion). Though I would still expect the internal reference to be cleaned up here. It might be something to do with the signals / slots system of Qt too, but I'm already quite far down the speculation rabbit hole 😅

@DPWebster
Copy link

Hey, I've been looking into how this might get fixed and I'm fairly certain this is a bug in the Napari backend (also referenced here: napari/napari#7668).

In a nutshell, the issue seems to be that Napari's AnimationThread (independent worker which processes the animation) creates a reference to the QtDimsSlider widget (gui for the play button and slider) when you click the play button which becomes stale if you delete the last layer (which deletes the QtDimsSlider object). If you load new data (creating a new QtDimsSlider) and try to push the play button, the AnimationThread will try to disconnect from the deleted widget so it can connect to the new one and fail because it no longer exists.

Therefore, this error will occur if the play button/slider widget is deleted (likely because the last layer was deleted) after you click the play button, then create a new play button/slider widget (likely because you loaded new data) and try to click the new play button.

Re-initializing the AnimationThread after deleting all layers prevents the bug from occurring (probably with unintended side effects). Here's how you can do that if you want to see yourself:

  1. Load sample data (e.g. DLC_single-mouse_EPM.predictions.h5) using movement widget.

  2. Hit play button.

  3. Delete layer from viewer.

  4. Open Napari's integrated Python console.

  5. Input "from napari._qt.widgets.qt_dims_slider import AnimationThread"

  6. Input "viewer.window.qt_viewer.dims._animation_thread = AnimationThread()"

  7. Load sample data again and hit play--bug does not occur.

In any case, since this doesn't actually have anything to do with how we load data/layers I think fixing this is probably outside the scope of movement. I'm interested in contributing to NIU projects more so let me know if there's anything else I can do to help on the matter.

@niksirbi
Copy link
Member

Thanks for the in-depth detective work @DPWebster, it seems that you've managed to pinpoint this one.
I think we should push for having this fixed on the napari side, instead of patching it in movement, as this bug probably has a wider impact. I will comment on the napari issue to let the devs know we are hitting this bug.

I'm interested in contributing to NIU projects more so let me know if there's anything else I can do to help on the matter.

You are welcome to follow up on this matter, depending on what the napari devs say.
In terms of contributing in general, would you be interested on working on something napari-related, or do you have any other preference? It would also be helpful to know how much time you can allocate, to help use scope out the right issue for you.

@Czaki
Copy link

Czaki commented Apr 28, 2025

It will be nice if you could check if napari/napari#7866 solves your issue (If I properly spot the problem).

@niksirbi
Copy link
Member

Cool! Thanks @Czaki, I will test locally and let you know.

@niksirbi
Copy link
Member

Based on my tests, napari/napari#7866 indeed solves this issue!

@DPWebster
Copy link

Good to see that everything's cleared up!

In terms of contributing in general, would you be interested on working on something napari-related, or do you have any other preference? It would also be helpful to know how much time you can allocate, to help use scope out the right issue for you.

I could safely spare around 10 hours a week @niksirbi; I'm open to working on anything, though napari-related issues might be a better fit as both of the issues I've looked into so far have been bugs relating to napari GUIs.

@niksirbi
Copy link
Member

I'm open to working on anything, though napari-related issues might be a better fit as both of the issues I've looked into so far have been bugs relating to napari GUIs.

Great to hear, @sfmig is currently deep into the napari part of the codebase, so she might have some ideas about a simple task to get you started.

@niksirbi
Copy link
Member

To resolve this issue, we only have to wait for the napari 0.6 release on PyPI and conda-forge, and then restrict the napari version to >0.6.0 in our dependencies.

@sfmig
Copy link
Contributor

sfmig commented Apr 30, 2025

Hi @DPWebster, great to hear that you are interested in contributing to our napari widget!

I think a nice first one to tackle may be this issue on visualising bounding boxes #567. I'd recommend starting with the bounding boxes datasets only, but it would be great if we can next tackle issue #17 and expand the functionality to pose datasets as well.

Let me know thoughts!

@Czaki
Copy link

Czaki commented Apr 30, 2025

To resolve this issue, we only have to wait for the napari 0.6 release on PyPI and conda-forge, and then restrict the napari version to >0.6.0 in our dependencies.

napari release should be in one or two days.

@sfmig sfmig moved this from 🤔 Triage to 🚧 In Progress in movement progress tracker May 2, 2025
@niksirbi niksirbi linked a pull request May 2, 2025 that will close this issue
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working GUI Graphical User Interface
Projects
Status: 🚧 In Progress
Development

Successfully merging a pull request may close this issue.

5 participants