@@ -326,6 +326,15 @@ static void android_app_set_window(struct android_app* android_app,
326
326
ANativeWindow * window ) {
327
327
LOGV ("android_app_set_window called" );
328
328
pthread_mutex_lock (& android_app -> mutex );
329
+
330
+ // NB: we have to consider that the native thread could have already
331
+ // (gracefully) exit (setting android_app->destroyed) and so we need
332
+ // to be careful to avoid a deadlock waiting for a thread that's
333
+ // already exit.
334
+ if (android_app -> destroyed ) {
335
+ pthread_mutex_unlock (& android_app -> mutex );
336
+ return ;
337
+ }
329
338
if (android_app -> pendingWindow != NULL ) {
330
339
android_app_write_cmd (android_app , APP_CMD_TERM_WINDOW );
331
340
}
@@ -342,9 +351,16 @@ static void android_app_set_window(struct android_app* android_app,
342
351
static void android_app_set_activity_state (struct android_app * android_app ,
343
352
int8_t cmd ) {
344
353
pthread_mutex_lock (& android_app -> mutex );
345
- android_app_write_cmd (android_app , cmd );
346
- while (android_app -> activityState != cmd ) {
347
- pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
354
+
355
+ // NB: we have to consider that the native thread could have already
356
+ // (gracefully) exit (setting android_app->destroyed) and so we need
357
+ // to be careful to avoid a deadlock waiting for a thread that's
358
+ // already exit.
359
+ if (!android_app -> destroyed ) {
360
+ android_app_write_cmd (android_app , cmd );
361
+ while (android_app -> activityState != cmd ) {
362
+ pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
363
+ }
348
364
}
349
365
pthread_mutex_unlock (& android_app -> mutex );
350
366
}
@@ -353,6 +369,14 @@ static void android_app_free(struct android_app* android_app) {
353
369
int input_buf_idx = 0 ;
354
370
355
371
pthread_mutex_lock (& android_app -> mutex );
372
+
373
+ // It's possible that onDestroy is called after we have already 'destroyed'
374
+ // the app (via `android_app_destroy` due to `android_main` returning.
375
+ //
376
+ // In this case `->destroyed` will already be set (so we won't deadlock in
377
+ // the loop below) but we still need to close the messaging fds and finish
378
+ // freeing the android_app
379
+
356
380
android_app_write_cmd (android_app , APP_CMD_DESTROY );
357
381
while (!android_app -> destroyed ) {
358
382
pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
@@ -400,6 +424,16 @@ static void onSaveInstanceState(GameActivity* activity,
400
424
401
425
struct android_app * android_app = ToApp (activity );
402
426
pthread_mutex_lock (& android_app -> mutex );
427
+
428
+ // NB: we have to consider that the native thread could have already
429
+ // (gracefully) exit (setting android_app->destroyed) and so we need
430
+ // to be careful to avoid a deadlock waiting for a thread that's
431
+ // already exit.
432
+ if (android_app -> destroyed ) {
433
+ pthread_mutex_unlock (& android_app -> mutex );
434
+ return ;
435
+ }
436
+
403
437
android_app -> stateSaved = 0 ;
404
438
android_app_write_cmd (android_app , APP_CMD_SAVE_STATE );
405
439
while (!android_app -> stateSaved ) {
@@ -505,6 +539,15 @@ static bool onTouchEvent(GameActivity* activity,
505
539
struct android_app * android_app = ToApp (activity );
506
540
pthread_mutex_lock (& android_app -> mutex );
507
541
542
+ // NB: we have to consider that the native thread could have already
543
+ // (gracefully) exit (setting android_app->destroyed) and so we need
544
+ // to be careful to avoid a deadlock waiting for a thread that's
545
+ // already exit.
546
+ if (android_app -> destroyed ) {
547
+ pthread_mutex_unlock (& android_app -> mutex );
548
+ return false;
549
+ }
550
+
508
551
if (android_app -> motionEventFilter != NULL &&
509
552
!android_app -> motionEventFilter (event )) {
510
553
pthread_mutex_unlock (& android_app -> mutex );
@@ -582,6 +625,15 @@ static bool onKey(GameActivity* activity, const GameActivityKeyEvent* event) {
582
625
struct android_app * android_app = ToApp (activity );
583
626
pthread_mutex_lock (& android_app -> mutex );
584
627
628
+ // NB: we have to consider that the native thread could have already
629
+ // (gracefully) exit (setting android_app->destroyed) and so we need
630
+ // to be careful to avoid a deadlock waiting for a thread that's
631
+ // already exit.
632
+ if (android_app -> destroyed ) {
633
+ pthread_mutex_unlock (& android_app -> mutex );
634
+ return false;
635
+ }
636
+
585
637
if (android_app -> keyEventFilter != NULL &&
586
638
!android_app -> keyEventFilter (event )) {
587
639
pthread_mutex_unlock (& android_app -> mutex );
@@ -620,8 +672,9 @@ static void onTextInputEvent(GameActivity* activity,
620
672
const GameTextInputState * state ) {
621
673
struct android_app * android_app = ToApp (activity );
622
674
pthread_mutex_lock (& android_app -> mutex );
623
-
624
- android_app -> textInputState = 1 ;
675
+ if (!android_app -> destroyed ) {
676
+ android_app -> textInputState = 1 ;
677
+ }
625
678
pthread_mutex_unlock (& android_app -> mutex );
626
679
}
627
680
0 commit comments