diff options
| author | Po Lu | 2023-02-23 18:05:57 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-23 18:05:57 +0800 |
| commit | 8747568d698575d61829358b456077ec3b0deabf (patch) | |
| tree | 389f8238f60f014ee7f8477ac46da6919aa16682 /src/android.c | |
| parent | 1d84465236f82a3791cc40bc53ecac30c93e489d (diff) | |
| download | emacs-8747568d698575d61829358b456077ec3b0deabf.tar.gz emacs-8747568d698575d61829358b456077ec3b0deabf.zip | |
Make android_select more robust
* src/android.c (android_run_select_thread): Lock select_mutex
before signalling condition variable.
(android_select): Unlock event queue mutex prior to waiting for
it.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/src/android.c b/src/android.c index 4639d84a2a1..ffeb4b659d9 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -387,12 +387,15 @@ android_run_select_thread (void *data) | |||
| 387 | android_pselect_rc = rc; | 387 | android_pselect_rc = rc; |
| 388 | pthread_mutex_unlock (&event_queue.select_mutex); | 388 | pthread_mutex_unlock (&event_queue.select_mutex); |
| 389 | 389 | ||
| 390 | /* Signal the main thread that there is now data to read. | 390 | /* Signal the main thread that there is now data to read. Hold |
| 391 | It is ok to signal this condition variable without holding | 391 | the event queue lock during this process to make sure this |
| 392 | the event queue lock, because android_select will always | 392 | does not happen before the main thread begins to wait for the |
| 393 | wait for this to complete before returning. */ | 393 | condition variable. */ |
| 394 | |||
| 395 | pthread_mutex_lock (&event_queue.select_mutex); | ||
| 394 | android_pselect_completed = true; | 396 | android_pselect_completed = true; |
| 395 | pthread_cond_broadcast (&event_queue.read_var); | 397 | pthread_cond_broadcast (&event_queue.read_var); |
| 398 | pthread_mutex_unlock (&event_queue.select_mutex); | ||
| 396 | 399 | ||
| 397 | if (rc != -1 || errno != EINTR) | 400 | if (rc != -1 || errno != EINTR) |
| 398 | /* Now, wait for SIGUSR1, unless pselect was interrupted and | 401 | /* Now, wait for SIGUSR1, unless pselect was interrupted and |
| @@ -635,13 +638,22 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 635 | "write: %s", strerror (errno)); | 638 | "write: %s", strerror (errno)); |
| 636 | #endif | 639 | #endif |
| 637 | 640 | ||
| 638 | /* Wait for pselect to return in any case. */ | 641 | /* Unlock the event queue mutex. */ |
| 642 | pthread_mutex_unlock (&event_queue.mutex); | ||
| 643 | |||
| 644 | /* Wait for pselect to return in any case. This must be done with | ||
| 645 | the event queue mutex unlocked. Otherwise, the pselect thread | ||
| 646 | can hang if it tries to lock the event queue mutex to signal | ||
| 647 | read_var after the UI thread has already done so. */ | ||
| 639 | while (sem_wait (&android_pselect_sem) < 0) | 648 | while (sem_wait (&android_pselect_sem) < 0) |
| 640 | ;; | 649 | ;; |
| 641 | 650 | ||
| 642 | /* If there are now events in the queue, return 1. */ | 651 | /* If there are now events in the queue, return 1. */ |
| 652 | |||
| 653 | pthread_mutex_lock (&event_queue.mutex); | ||
| 643 | if (event_queue.num_events) | 654 | if (event_queue.num_events) |
| 644 | nfds_return = 1; | 655 | nfds_return = 1; |
| 656 | pthread_mutex_unlock (&event_queue.mutex); | ||
| 645 | 657 | ||
| 646 | /* Add the return value of pselect. */ | 658 | /* Add the return value of pselect. */ |
| 647 | if (android_pselect_rc >= 0) | 659 | if (android_pselect_rc >= 0) |
| @@ -650,9 +662,6 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 650 | if (!nfds_return && android_pselect_rc < 0) | 662 | if (!nfds_return && android_pselect_rc < 0) |
| 651 | nfds_return = android_pselect_rc; | 663 | nfds_return = android_pselect_rc; |
| 652 | 664 | ||
| 653 | /* Unlock the event queue mutex. */ | ||
| 654 | pthread_mutex_unlock (&event_queue.mutex); | ||
| 655 | |||
| 656 | /* This is to shut up process.c when pselect gets EINTR. */ | 665 | /* This is to shut up process.c when pselect gets EINTR. */ |
| 657 | if (nfds_return < 0) | 666 | if (nfds_return < 0) |
| 658 | errno = EINTR; | 667 | errno = EINTR; |