Repository: kivy/kivy

Issue:
Kivy 1.8.0 dev branch occasional error on_touch_down
I'm getting a seemingly random crash occasionally on touch down. I've had it occur on the very first touch of my app, but occasionally it takes quite some time, longest ~10 minutes of use with no crash.

```
 File "/home/jacob/Documents/chaosbuffalo/kivent/buildfolder/main.py", line 182, in <module>
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/app.py", line 612, in run
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/base.py", line 454, in runTouchApp
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/core/window/window_pygame.py", line 329, in mainloop
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/core/window/window_pygame.py", line 235, in _mainloop
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/base.py", line 297, in idle
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/base.py", line 284, in dispatch_input
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/base.py", line 209, in post_dispatch_input
I/python  ( 4736):    File "_event.pyx", line 303, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4256)
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/core/window/__init__.py", line 630, in on_motion
I/python  ( 4736):    File "_event.pyx", line 303, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4256)
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/core/window/__init__.py", line 642, in on_touch_down
I/python  ( 4736):    File "_event.pyx", line 303, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4256)
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/uix/widget.py", line 272, in on_touch_down
I/python  ( 4736):    File "_event.pyx", line 303, in kivy._event.EventDispatcher.dispatch (kivy/_event.c:4256)
I/python  ( 4736):    File "/home/jacob/Libraries/python-for-android/build/python-install/lib/python2.7/site-packages/kivy/uix/widget.py", line 272, in on_touch_down
I/python  ( 4736):  ReferenceError: weakly-referenced object no longer exists
I/python  ( 4736): Python for android ended.
```



Discussion:
We can't help until you give us more information. This is a standard touch dispatching backtrace :)

Recently, we fixed the garbage collections of widgets. Most of them, as soon as some kv magic was used, was never deleted from memory. For examples, the id collected in a kv rule are now weak references, not a direct references. If you are using them, be careful to not remove the widget from the tree and have only one weak-ref.

I'm interested about the construction you got in order to maybe inform users about things to NOT do, or enhance kivy to take care of your construction.

I'm trying to isolate what is going on, however, I've failed to reproduce the behaviour in a smaller app. I do think it has something to do with my use of add and remove widget. I have also been unable to reproduce the error in ubuntu using the same kivy 1.8.0-dev, it seems to only effect the android devices.

I will share a little about the construction of the widget.
Most everything in my app is controlled by a widget known as GameWorld.
https://github.com/Kovak/KivEnt/blob/master/kivent_cython/kivent_cython/gameworld.pyx
Which is used in the apps .kv like this:
https://github.com/Kovak/KivEnt/blob/master/kivent.kv
GameWorld contains a number of custom widgets known as GameSystem, some of which render graphics other of which do not. These widgets are added to a dictionary, using a unique string property to identify each widget. This way a reference to the widget is always kept to easily facilitate adding and removing those widgets. (Line 136 - 144 of GameWorld.pyx

 GameWorld also owns a screenmanager which allows me to easily sync up which UI elements are displayed with the current state of the game. Add and remove widget is used on gamesystems that render graphics in order to control what is on screen at a given time.

GameWorld has a state that allows me to determine which widgets should be being updated, which should be added and which should be displayed, and which screen is current for the screenmanager. On state the GameSystems are added or removed as necessary. My screenmanager is than removed and re-added in order to make sure it is on top of all the other widgets. (Line 39-59 of GameWorld.pyx)

The easiest way for me to replicate the crash is to open up my app, and let it sit with no interaction for about 30 seconds to 1 minute. Then click the 'Play Button' which changes the gameworld's state from main menu to main game. The app then crashes with the aforementioned error before the button even animates as being pressed or the code to change state of gameworld is run. The widget that is receiving the touch in this case is my GameScreenManager (https://github.com/Kovak/KivEnt/blob/master/kivent_cython/kivent_cython/gamescreens.pyx) it does not run any special code though. 

My best guess is that adding and removing the GameScreenManager is causing something to lose the reference to it. Most likely there is an error in the way I am going about using the kv to link some properties. (Line 16-86 of kivent.kv 

If there is any other information I could provide or some kind of testing I can run, I'd be happy to give it a go. I was unable to replicate the crashing behaviour just switching between 2 screens with a button to press to affect the switch and adding and removing the ScreenManager after each switch. 

The crash is always reproducible doing the following:

Open App
The first screen is nothing but a button in the center
Allow to Sit with no interaction for 30+ seconds
Touch Down Anywhere on Screen (empty space or button)
Root Widget receives Touch, does nothing
GameWorld  receives Touch, does nothing
GameScreenManager receives touch, crashes.

Found the error I believe: 
Readings on the Widgets and some of their properties:
Touching down without crash:

```
07-01 15:30:08.934 20868 20885 I python  : gameworld:  <kivent_cython.__init__.GameWorld object at 0x519864c8>
07-01 15:30:08.934 20868 20885 I python  : children:  [<kivent_cython.__init__.GameWorld object at 0x519864c8>]
07-01 15:30:08.934 20868 20885 I python  : gameworld_children:  [<weakproxy at 0x521d2240 to GameScreenManager at 0x519869d0>, <levels.AsteroidsLevel object at 0x51986998>, <kivent_cython.__init__.CymunkPhysics object at 0x51986848>, <levels.AsteroidSystem object at 0x51986810>, <player_character.PlayerCharacter object at 0x519867d8>, <projectiles.ProjectileSystem object at 0x519867a0>, <kivent_cython.__init__.GameSystem object at 0x51986768>, <kivent_cython.__init__.QuadTreePointRenderer object at 0x51986730>, <kivent_cython.__init__.QuadRenderer object at 0x519866f8>, <kivent_cython.__init__.GameMap object at 0x519866c0>, <kivent_cython.__init__.GameView object at 0x51986688>, <musiccontroller.MusicController object at 0x51986618>]
07-01 15:30:08.934 20868 20885 I python  : gamescreenmanager:  <kivent_cython.__init__.GameScreenManager object at 0x519869d0>
```

touching down with crash

```
07-01 15:30:23.388 20868 20885 I python  : gameworld:  <kivent_cython.__init__.GameWorld object at 0x519864c8>
07-01 15:30:23.388 20868 20885 I python  : children:  [<kivent_cython.__init__.GameWorld object at 0x519864c8>]
07-01 15:30:23.388 20868 20885 I python  : gameworld_children:  [<weakproxy at 0x521d2240 to NoneType at 0x5252070c>, <levels.AsteroidsLevel object at 0x51986998>, <kivent_cython.__init__.CymunkPhysics object at 0x51986848>, <levels.AsteroidSystem object at 0x51986810>, <player_character.PlayerCharacter object at 0x519867d8>, <projectiles.ProjectileSystem object at 0x519867a0>, <kivent_cython.__init__.GameSystem object at 0x51986768>, <kivent_cython.__init__.QuadTreePointRenderer object at 0x51986730>, <kivent_cython.__init__.QuadRenderer object at 0x519866f8>, <kivent_cython.__init__.GameMap object at 0x519866c0>, <kivent_cython.__init__.GameView object at 0x51986688>, <musiccontroller.MusicController object at 0x51986618>]
07-01 15:30:23.388 20868 20885 I python  : gamescreenmanager: 
```

 Ends with same error as posted originally. So it looks like it's because the gamescreenmanager is only referenced as a weakreference. What is the best way to ensure that this Widget is referenced like the other widgets rather than weak referenced. Also at this point the gamescreenmanager has been removed and re-added, however the weakreference gets garbage collected and a new entry for the widget in children is not created while leaving the old one as a nonetype

Qua-non suggested adding this chat to bug report:

[16:39] <kovak> still exists on latest branch, so actually the objectproperty correctly stores a reference to the widget, however when parent.add_widget(screenmanager) is called, this adds a weak reference to the parent.children array instead of a regular reference like all other widgets
[16:40] <+qua-non> you can keep the reference to the widget byt storing it before removing it ...
[16:41] <kovak> it is being kept, however when it is re-added a new weakreference is not added to the parent.children array, then after a little while garbage collect deletes the object of this weak reference, so the screenmanager is actually present in the parent's widget tree however the reference kept inside widget's children array is losing track of the object
[16:42] <kovak> printing widget.children you get something like `[<weakproxy at 0x3601418 to GameScreenManager at 0x3568870>, <levels.AsteroidsLevel object at 0x3568808>]`, all objects except this screenmanager are kept as references like the AsteroidsLevel
[16:43] <kovak> then after a gc: you get gameworld_children:  `[<weakproxy at 0x3601418 to NoneType at 0x89e6e0>, <levels.AsteroidsLevel object at 0x3568808>]`, however the gamescreenmanager and it's children are visible
[16:43] <kovak> kivy will then error as it tries to dispatch a touch to `<weakproxy at 0x3601418 to NoneType at 0x89e6e0>`


Resolving patch:
diff --git a/kivy/uix/widget.py b/kivy/uix/widget.py
--- a/kivy/uix/widget.py
+++ b/kivy/uix/widget.py
@@ -179,8 +179,8 @@ def __init__(self, **kwargs):
     def proxy_ref(self):
         '''Return a proxy reference to the widget, ie, without taking a
         reference of the widget. See `weakref.proxy
-        <http://docs.python.org/2/library/weakref.html?highlight=proxy#weakref.proxy>`_
-        for more information about it.
+        <http://docs.python.org/2/library/weakref.html?highlight\
+        =proxy#weakref.proxy>`_ for more information about it.
 
         .. versionadded:: 1.7.2
         '''
@@ -316,11 +316,13 @@ def add_widget(self, widget, index=0):
         >>> slider = Slider()
         >>> root.add_widget(slider)
         '''
-        if widget is self:
-            raise WidgetException('You cannot add yourself in a Widget')
         if not isinstance(widget, Widget):
             raise WidgetException(
                 'add_widget() can be used only with Widget classes.')
+
+        widget = widget.__self__
+        if widget is self:
+            raise WidgetException('You cannot add yourself in a Widget')
         parent = widget.parent
         # check if widget is already a child of another widget
         if parent:


Test patch: