Repository: kivy/kivy

Issue:
App.get_running_app().stop() @ sdl2
Using this in the new android toolchain makes the app to crash appearing the window "Unfortunately, App X has stopped."

It worked fine using pygame, with sdl2 it doesn't.



Discussion:
@inclement, was this a known issue?

It's known to me at least. Though this bug report should include the actual output of the crash from logcat, but I suspect it's the issue where a Python thread is still running (or some code is calling CPython functions) after the interpreter shutdown, leading to a seg fault.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I am seeing this as well, and kived's speculation about the segfault is correct.

My app has an r-u-sure popup that asks the user for exit confirmation, and when the user says yes, the popup calls app.stop(). The crash is a segfault resulting from an onPause call in the SDL library after the python exit has happened. See attached logcat output.

I tried following the pattern of calling Window.close() as suggested in https://github.com/kivy/python-for-android/issues/734
 but it made no difference.

I also tried the patch suggested there, and it too made no difference.

[crash3.txt](https://github.com/kivy/kivy/files/1559729/crash3.txt)

@dlparker I managed to fix it in my app somehow.

1) Redefine your app `stop` method this way:

```
class MyApp(App):
    def stop(self, *largs):
        self.root_window.close()  # Fix app exit on Android.
        return super(MyApp, self).stop(*largs)
```

2) Use  `stopTouchApp` instead of `app.stop` (needed to avoid multiple `on_stop` dispatches):

```
from kivy.base import stopTouchApp

stopTouchApp()
```

---
You may be also interested in [this PR](https://github.com/kivy/kivy/pull/4927). It'll fix home button exit if your app doesn't support sleep mode.
Using method 1 doesn't give error but takes some time to exit the app. It finally exits because it reaches the maximum recursion.

Using method 2 gives the same error "Unfortunately, App X has stopped."

Normal app (without method 1 or 2) gives:

`03-29 15:07:41.371 11265 11282 I python  : [INFO   ] [Base        ] Leaving application in progress...

03-29 15:07:41.706 11265 11282 I python  : Python for android ended.

03-29 15:07:41.711  2751  5071 D InputDispatcher: Focus left window: Window{54bb513 u0 brand.some.thing/org.kivy.android.PythonActivity}

03-29 15:07:41.712 11265 11265 V SDL     : onWindowFocusChanged(): false

03-29 15:07:41.795 11265 11265 V PythonActivity: onPause()

03-29 15:07:41.796 11265 11265 V SDL     : onPause()

03-29 15:07:41.796  4529 21702 D SplitWindowPolicy: updateActivityStateChanged: resumed=false, screenId=7, isScreenFull=true

03-29 15:07:41.796 11265 11265 V SDL     : nativePause()

03-29 15:07:41.796 11265 11265 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 11265 (brand.some.thing)`


I'm using kivy with python3 support with python3crystax.
I can confirm that self.root_window.close() fixed this for us without problems. 
@Huyston. Are there perhaps others threads that stop the app closing? I think we need to assume it's something your app is doing, unless you can provide a minimal run-able example that demonstrates the issue?

Resolving patch:
diff --git a/kivy/core/window/window_sdl2.py b/kivy/core/window/window_sdl2.py
--- a/kivy/core/window/window_sdl2.py
+++ b/kivy/core/window/window_sdl2.py
@@ -208,7 +208,6 @@ def _event_filter(self, action):
         from kivy.app import App
         if action == 'app_terminating':
             EventLoop.quit = True
-            self.close()
 
         elif action == 'app_lowmemory':
             self.dispatch('on_memorywarning')
@@ -490,7 +489,6 @@ def _mainloop(self):
                 if self.dispatch('on_request_close'):
                     continue
                 EventLoop.quit = True
-                self.close()
                 break
 
             elif action in ('fingermotion', 'fingerdown', 'fingerup'):
@@ -708,7 +706,6 @@ def do_pause(self):
             action, args = event[0], event[1:]
             if action == 'quit':
                 EventLoop.quit = True
-                self.close()
                 break
             elif action == 'app_willenterforeground':
                 break
@@ -733,6 +730,8 @@ def mainloop(self):
                     raise
                 else:
                     pass
+        Logger.info("WindowSDL: exiting mainloop and closing.")
+        self.close()
 
     #
     # Pygame wrapper


Test patch: