@@ -308,6 +308,15 @@ static void android_app_set_window(struct android_app* android_app,
308
308
ANativeWindow * window ) {
309
309
LOGV ("android_app_set_window called" );
310
310
pthread_mutex_lock (& android_app -> mutex );
311
+
312
+ // NB: we have to consider that the native thread could have already
313
+ // (gracefully) exit (setting android_app->destroyed) and so we need
314
+ // to be careful to avoid a deadlock waiting for a thread that's
315
+ // already exit.
316
+ if (android_app -> destroyed ) {
317
+ pthread_mutex_unlock (& android_app -> mutex );
318
+ return ;
319
+ }
311
320
if (android_app -> pendingWindow != NULL ) {
312
321
android_app_write_cmd (android_app , APP_CMD_TERM_WINDOW );
313
322
}
@@ -324,15 +333,30 @@ static void android_app_set_window(struct android_app* android_app,
324
333
static void android_app_set_activity_state (struct android_app * android_app ,
325
334
int8_t cmd ) {
326
335
pthread_mutex_lock (& android_app -> mutex );
327
- android_app_write_cmd (android_app , cmd );
328
- while (android_app -> activityState != cmd ) {
329
- pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
336
+
337
+ // NB: we have to consider that the native thread could have already
338
+ // (gracefully) exit (setting android_app->destroyed) and so we need
339
+ // to be careful to avoid a deadlock waiting for a thread that's
340
+ // already exit.
341
+ if (!android_app -> destroyed ) {
342
+ android_app_write_cmd (android_app , cmd );
343
+ while (android_app -> activityState != cmd ) {
344
+ pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
345
+ }
330
346
}
331
347
pthread_mutex_unlock (& android_app -> mutex );
332
348
}
333
349
334
350
static void android_app_free (struct android_app * android_app ) {
335
351
pthread_mutex_lock (& android_app -> mutex );
352
+
353
+ // It's possible that onDestroy is called after we have already 'destroyed'
354
+ // the app (via `android_app_destroy` due to `android_main` returning.
355
+ //
356
+ // In this case `->destroyed` will already be set (so we won't deadlock in
357
+ // the loop below) but we still need to close the messaging fds and finish
358
+ // freeing the android_app
359
+
336
360
android_app_write_cmd (android_app , APP_CMD_DESTROY );
337
361
while (!android_app -> destroyed ) {
338
362
pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
@@ -372,6 +396,16 @@ static void onSaveInstanceState(GameActivity* activity,
372
396
373
397
struct android_app * android_app = ToApp (activity );
374
398
pthread_mutex_lock (& android_app -> mutex );
399
+
400
+ // NB: we have to consider that the native thread could have already
401
+ // (gracefully) exit (setting android_app->destroyed) and so we need
402
+ // to be careful to avoid a deadlock waiting for a thread that's
403
+ // already exit.
404
+ if (android_app -> destroyed ) {
405
+ pthread_mutex_unlock (& android_app -> mutex );
406
+ return ;
407
+ }
408
+
375
409
android_app -> stateSaved = 0 ;
376
410
android_app_write_cmd (android_app , APP_CMD_SAVE_STATE );
377
411
while (!android_app -> stateSaved ) {
@@ -481,6 +515,15 @@ static bool onTouchEvent(GameActivity* activity,
481
515
struct android_app * android_app = ToApp (activity );
482
516
pthread_mutex_lock (& android_app -> mutex );
483
517
518
+ // NB: we have to consider that the native thread could have already
519
+ // (gracefully) exit (setting android_app->destroyed) and so we need
520
+ // to be careful to avoid a deadlock waiting for a thread that's
521
+ // already exit.
522
+ if (android_app -> destroyed ) {
523
+ pthread_mutex_unlock (& android_app -> mutex );
524
+ return false;
525
+ }
526
+
484
527
if (android_app -> motionEventFilter != NULL &&
485
528
!android_app -> motionEventFilter (event )) {
486
529
pthread_mutex_unlock (& android_app -> mutex );
@@ -563,6 +606,15 @@ static bool onKey(GameActivity* activity, const GameActivityKeyEvent* event) {
563
606
struct android_app * android_app = ToApp (activity );
564
607
pthread_mutex_lock (& android_app -> mutex );
565
608
609
+ // NB: we have to consider that the native thread could have already
610
+ // (gracefully) exit (setting android_app->destroyed) and so we need
611
+ // to be careful to avoid a deadlock waiting for a thread that's
612
+ // already exit.
613
+ if (android_app -> destroyed ) {
614
+ pthread_mutex_unlock (& android_app -> mutex );
615
+ return false;
616
+ }
617
+
566
618
if (android_app -> keyEventFilter != NULL &&
567
619
!android_app -> keyEventFilter (event )) {
568
620
pthread_mutex_unlock (& android_app -> mutex );
@@ -599,8 +651,9 @@ static void onTextInputEvent(GameActivity* activity,
599
651
const GameTextInputState * state ) {
600
652
struct android_app * android_app = ToApp (activity );
601
653
pthread_mutex_lock (& android_app -> mutex );
602
-
603
- android_app -> textInputState = 1 ;
654
+ if (!android_app -> destroyed ) {
655
+ android_app -> textInputState = 1 ;
656
+ }
604
657
pthread_mutex_unlock (& android_app -> mutex );
605
658
}
606
659
0 commit comments