nanogui icon indicating copy to clipboard operation
nanogui copied to clipboard

Bug report: remove widget in callback

Open jzrake opened this issue 6 years ago • 2 comments

Attempting to remove a button from its parent on click results in a seg fault:

class TestApp : public nanogui::Screen {
public:
    TestApp() : nanogui::Screen(Vector2i(400, 400), "") {
        auto b = new Button(this, "Click to remove");
        b->setCallback([this] () { removeChild(0); });
        performLayout();
    }
};
class TestApp(nanogui.Screen):
    def __init__(self):
        super(TestApp, self).__init__((400, 400), "")
        nanogui.Button(self, "Click to remove me").setCallback(lambda: self.removeChild(0))
        self.performLayout()

This appears to be a bug, because according to button.cpp, the button should be retained until after any callbacks are finished:

    /* button.cpp, line 52
       Temporarily increase the reference count of the button in case the
       button causes the parent window to be destructed */
    ref<Button> self = this;

jzrake avatar Apr 18 '18 13:04 jzrake

You should capture b and remove it explicitly:

b->setCallback([this, b]() { removeChild(b); });

For python you'll need to be more explicit. Untested, but something like this should work

b = nanogui.Button(self, "Click to remove me")
b.setCallback(lambda: self.removeChild(b))

The implementation differences are here:

https://github.com/wjakob/nanogui/blob/885e4fccc69bbfdd4c527009eef8ed33641d9765/src/widget.cpp#L154-L163

Basically, you should prefer the explicit Widget * version. IIRC the callback is executed twice (put some print statements in to confirm), once for push and once for release? If so, then the second one is where the segfault comes from, because it was already removed in the first execution.

svenevs avatar Apr 18 '18 13:04 svenevs

UhOh. I just added that and tested, and if you do the explicit capture of b then you'll get a segfault later. First click removes it, but then if you click in the same spot you'll get a segfault...

svenevs avatar Apr 18 '18 13:04 svenevs