-
Notifications
You must be signed in to change notification settings - Fork 611
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
Remove dangling children from Screen #341
base: master
Are you sure you want to change the base?
Remove dangling children from Screen #341
Conversation
@wjakob I'd appreciate your feedback on this. |
Ok, I can confirm that in "my" project. I have had the same issue ( segmentation fault ) in |
@carmel4a Glad I could help! |
Hi @chpatton013 sorry for never responding to this. Here are my thoughts
Basically, I agree this is more thorough than #332, but I think it could be cleaner if (1) is removed / (3) is incorporated. What are your thoughts? I'm closing that PR, can you edit the text of the top-comment at the beginning to say Edit: see also #198 and #262, all circling around this same issue. |
@svenevs I should have time this weekend to properly respond to your comment. I'm posting now to hold myself accountable to that :P |
1
Not "necessary", but I found it to be the cleanest way to get code-reuse and performance across two different signatures. I won't dispute the convenience of just calling the pointer impl from the index impl, however I would point out the unnecessary use of
Both of these implementations erase based on a calculated iterator (either However, the pragmatist in me recognizes that there is a lot of extra code introduced to get a little bit of re-use. Since all I've needed to do is add a call to a single function in each of these implementations, it would be more succinct just to do that and keep the implementations separate. All that said, I personally (and without much conviction, mind you) do not think it is appropriate to coerce one of these implementations to call the other. If we were to stick with the iterator-based helper function there would naturally be a logical intersection point, but without it I think this just makes the relationship between them complicated. 2
I prescribe to the "fail fast and hard" methodology of defensive coding, but I won't enforce that preference on someone else's code. I'm happy to replace those asserts with an early return. 3
This is the actual meat and potatoes of my PR. Everything else is just an implementation detail. When a Widget is focused, it and its whole ancestry are included in As you said:
With that in mind, it seemed like the appropriate function to call to clean up those member variables. Unfortunately,
I don't think that would have any effect, since this problem can occur when removing a widget from any parent. We need every call to
I think you're right about this. I had a whole big scenario typed out where this could still break, but I talked myself out of it. The loop is not necessary.
This is kind of a repurposing of the As I mentioned earlier, I don't have very strong convictions about the finer details here. The important result is that We currently have a couple of small changes that I think we're both in agreement on:
And we still have a couple of open questions:
Let me know what you'd like to see on each of these points. |
@svenevs poke |
I've also just run into this. Thanks @chpatton013 for your fix - this looks good. I've made a further change to this (#389) that may resolve also some of the other points. Essentially it just enforces a |
As an alternative to #389 I’ve also implemented the changes as suggested in this PR. This is probably the simplest fix with the least impact on the existing code. On the discussion points I went with the changes that make the fewest changes. It makes the same point shared by @chpatton013 that it puts the responsibility on |
@chpatton013 I'm sorry :( I'm re-investigating right now and comparing with the destructor approach by @wardw. I'm inclined to say that the |
I think it's ok to leave the asserts, there's plenty of other
I think we do need it. Say we have Do you agree?
Personally I prefer having Edit: the approach in #332 is a little more wasteful than the iterator, it's just easier to look at / understand. Emphasis: I just want to get this issue fixed :) @wjakob what would you prefer? Summary:
Disregard this. I was very wrong... @chpatton013 I'm adding a task list to the message at the top to indicate what needs to happen before asking @wjakob for final review so that you can edit it. I am hesitant to rebase / make changes myself by committing directly to the branch because I was not sure if you are actively using it (aka if you green light me I can rebase / do the pydoc stuff for you if you like). |
github is being fucking stupid (or i am)
yea, i force pushed. sue me
I am upstreaming some of the changes my team has made to nanovg and nanogui.
Note: I think this is a more thorough implementation of #332
We found that removing widgets during an event callback sometimes raised segfaults either later on during event processing or on the subsequent draw frame. A little bit of digging showed that
Screen
was holding onto references to widgets that may have been de-allocated.Our solution was to invoke a slightly altered form of
Screen::disposeWindow
fromremoveChild
to ensuremDragActive
,mDragWidget
, andmFocusPath
do not contain references to deallocated pointers.A quick summary of changes:
Widget::removeChild(int)
is within range of[0, Widget::childCount - 1]
Widget::removeChildHelper
: a common helper function forWidget::removeChild
that operates on iterators.Screen::disposeWindow
toScreen::disposeWidget
, change the argument type toWidget*
, and recurse to dispose of children as well.Screen::disposeWindow
to callScreen::removeChild
(which will eventually callScreen::disposeWidget
now).This may break a few users because:
TODO
py_doc.h
to be a docstring comment inscreen.h
:/// Remove any internal references to a widget and its children.
make mkdoc
target to regeneratepy_doc.h
removeChildHelper
vsremoveChild(Widget *)
Remove dangling children from Screen #341 (comment)disposeWidget(Widget *)
=>disposeWidget(const Widget *)