GNOME Bugzilla – Bug 764845
GDK: gdk_window_reparent creates circular reference in 'children' list
Last modified: 2016-04-12 12:58:43 UTC
This bug has been present at least since 8306d26714514f001d49b1cefc182459a44d9724. Referring to lines 1748-1751 in gdkwindow-win32.c as of adff59843b3cd511557ba5a578d2e75e685b3bed (https://github.com/GNOME/gtk/blob/adff59843b3cd511557ba5a578d2e75e685b3bed/gdk/win32/gdkwindow-win32.c#L1748), it updates both the old parent's child window list and the new parent's child window list. However, in the generic reparenting code in gdkwindow.c (lines 1642-1649 and line 1655 as of adff59843b3cd511557ba5a578d2e75e685b3bed (https://github.com/GNOME/gtk/blob/adff59843b3cd511557ba5a578d2e75e685b3bed/gdk/gdkwindow.c#L1642, https://github.com/GNOME/gtk/blob/adff59843b3cd511557ba5a578d2e75e685b3bed/gdk/gdkwindow.c#L1655), these properties are updated again. While this duplicated code has no effect for the old parent, by updating the new parent's child list again, a circular reference is created in the list of children. One effect of this is that calling gdk_window_show on the new parent will result in it entering an infinite loop as it tries to traverse the children. One potential fix would be to remove this code from gdkwindow-win32.c and leave it up to the generic code the layer above. I don't know if this affects other backends or not - I only know that it is an issue on Windows.
Git blame says that this code was modified in 9bda0532 and before that it was modified in 1d838f58 and before that it was modified in 8e06c4d7 and 638ebcee which just moved it from somewhere else (that's when gdkwindow-win32.c was created). I don't know anything about this code in isolation. My best bet would be to see what other backends do (or don't do) and make W32 backend conform with that.
Other backends either don't support reparenting, or they don't change the child list of the parent. Quartz does, but it changes its own internal z-order-sorted list, not the generic gdkwindow children list. The original code dates back to 1999 and tml, and last meaningful change was in 2011 - https://git.gnome.org/browse/gtk+/commit/?id=1d838f58 I think that removing these two lines should be sufficient, as it's clearly a duplicate of what generic gdkwindow code does. Though reparenting is somewhat rarely-used functionality, AFAIU. Do we have tests for it?
Created attachment 325692 [details] Example source that exhibits issue I don't know about existing tests, but I've attached a sample program that exhibits this issue. On builds of GDK that are unpatched, the code will hang on the first call to gdk_window_show (line 54).
Created attachment 325698 [details] [review] GDK W32: Deduplicate reparenting This should do the trick.
Review of attachment 325698 [details] [review]: Looks good to me but a review from Matthias would be great here
Review of attachment 325698 [details] [review]: Looks good to me
Attachment 325698 [details] pushed as c2aa7d0 - GDK W32: Deduplicate reparenting