@@ -327,6 +327,15 @@ static void android_app_set_window(struct android_app* android_app,
327
327
ANativeWindow * window ) {
328
328
LOGV ("android_app_set_window called" );
329
329
pthread_mutex_lock (& android_app -> mutex );
330
+
331
+ // NB: we have to consider that the native thread could have already
332
+ // (gracefully) exit (setting android_app->destroyed) and so we need
333
+ // to be careful to avoid a deadlock waiting for a thread that's
334
+ // already exit.
335
+ if (android_app -> destroyed ) {
336
+ pthread_mutex_unlock (& android_app -> mutex );
337
+ return ;
338
+ }
330
339
if (android_app -> pendingWindow != NULL ) {
331
340
android_app_write_cmd (android_app , APP_CMD_TERM_WINDOW );
332
341
}
@@ -343,9 +352,16 @@ static void android_app_set_window(struct android_app* android_app,
343
352
static void android_app_set_activity_state (struct android_app * android_app ,
344
353
int8_t cmd ) {
345
354
pthread_mutex_lock (& android_app -> mutex );
346
- android_app_write_cmd (android_app , cmd );
347
- while (android_app -> activityState != cmd ) {
348
- pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
355
+
356
+ // NB: we have to consider that the native thread could have already
357
+ // (gracefully) exit (setting android_app->destroyed) and so we need
358
+ // to be careful to avoid a deadlock waiting for a thread that's
359
+ // already exit.
360
+ if (!android_app -> destroyed ) {
361
+ android_app_write_cmd (android_app , cmd );
362
+ while (android_app -> activityState != cmd ) {
363
+ pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
364
+ }
349
365
}
350
366
pthread_mutex_unlock (& android_app -> mutex );
351
367
}
@@ -354,6 +370,14 @@ static void android_app_free(struct android_app* android_app) {
354
370
int input_buf_idx = 0 ;
355
371
356
372
pthread_mutex_lock (& android_app -> mutex );
373
+
374
+ // It's possible that onDestroy is called after we have already 'destroyed'
375
+ // the app (via `android_app_destroy` due to `android_main` returning.
376
+ //
377
+ // In this case `->destroyed` will already be set (so we won't deadlock in
378
+ // the loop below) but we still need to close the messaging fds and finish
379
+ // freeing the android_app
380
+
357
381
android_app_write_cmd (android_app , APP_CMD_DESTROY );
358
382
while (!android_app -> destroyed ) {
359
383
pthread_cond_wait (& android_app -> cond , & android_app -> mutex );
@@ -403,6 +427,16 @@ static void onSaveInstanceState(GameActivity* activity,
403
427
404
428
struct android_app * android_app = ToApp (activity );
405
429
pthread_mutex_lock (& android_app -> mutex );
430
+
431
+ // NB: we have to consider that the native thread could have already
432
+ // (gracefully) exit (setting android_app->destroyed) and so we need
433
+ // to be careful to avoid a deadlock waiting for a thread that's
434
+ // already exit.
435
+ if (android_app -> destroyed ) {
436
+ pthread_mutex_unlock (& android_app -> mutex );
437
+ return ;
438
+ }
439
+
406
440
android_app -> stateSaved = 0 ;
407
441
android_app_write_cmd (android_app , APP_CMD_SAVE_STATE );
408
442
while (!android_app -> stateSaved ) {
@@ -508,6 +542,15 @@ static bool onTouchEvent(GameActivity* activity,
508
542
struct android_app * android_app = ToApp (activity );
509
543
pthread_mutex_lock (& android_app -> mutex );
510
544
545
+ // NB: we have to consider that the native thread could have already
546
+ // (gracefully) exit (setting android_app->destroyed) and so we need
547
+ // to be careful to avoid a deadlock waiting for a thread that's
548
+ // already exit.
549
+ if (android_app -> destroyed ) {
550
+ pthread_mutex_unlock (& android_app -> mutex );
551
+ return false;
552
+ }
553
+
511
554
if (android_app -> motionEventFilter != NULL &&
512
555
!android_app -> motionEventFilter (event )) {
513
556
pthread_mutex_unlock (& android_app -> mutex );
@@ -586,6 +629,15 @@ static bool onKey(GameActivity* activity, const GameActivityKeyEvent* event) {
586
629
struct android_app * android_app = ToApp (activity );
587
630
pthread_mutex_lock (& android_app -> mutex );
588
631
632
+ // NB: we have to consider that the native thread could have already
633
+ // (gracefully) exit (setting android_app->destroyed) and so we need
634
+ // to be careful to avoid a deadlock waiting for a thread that's
635
+ // already exit.
636
+ if (android_app -> destroyed ) {
637
+ pthread_mutex_unlock (& android_app -> mutex );
638
+ return false;
639
+ }
640
+
589
641
if (android_app -> keyEventFilter != NULL &&
590
642
!android_app -> keyEventFilter (event )) {
591
643
pthread_mutex_unlock (& android_app -> mutex );
@@ -626,8 +678,9 @@ static void onTextInputEvent(GameActivity* activity,
626
678
const GameTextInputState * state ) {
627
679
struct android_app * android_app = ToApp (activity );
628
680
pthread_mutex_lock (& android_app -> mutex );
629
-
630
- android_app -> textInputState = 1 ;
681
+ if (!android_app -> destroyed ) {
682
+ android_app -> textInputState = 1 ;
683
+ }
631
684
pthread_mutex_unlock (& android_app -> mutex );
632
685
}
633
686
0 commit comments