diff options
| author | Po Lu | 2023-01-20 21:21:15 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-20 21:21:15 +0800 |
| commit | 26f0dd508982b9680a3cc5d7c56d5f978e06dc8f (patch) | |
| tree | 6d9f3c132bbe16d8fef0cbebc45e65f7fda983fc /src/android.c | |
| parent | 01ee2bd07be203987c003b8155ae10b89b0dc08a (diff) | |
| download | emacs-26f0dd508982b9680a3cc5d7c56d5f978e06dc8f.tar.gz emacs-26f0dd508982b9680a3cc5d7c56d5f978e06dc8f.zip | |
Update Android port
* src/android.c (android_run_select_thread, android_init_events)
(android_select): Add alternative android_select implementation
for API 16 and lower.
* src/androidterm.c (handle_one_android_event): Fix
use-after-frees.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 112 |
1 files changed, 99 insertions, 13 deletions
diff --git a/src/android.c b/src/android.c index 43ac3b3f754..47120a6b5f5 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -257,30 +257,88 @@ static struct android_event_queue event_queue; | |||
| 257 | /* Semaphores used to signal select completion and start. */ | 257 | /* Semaphores used to signal select completion and start. */ |
| 258 | static sem_t android_pselect_sem, android_pselect_start_sem; | 258 | static sem_t android_pselect_sem, android_pselect_start_sem; |
| 259 | 259 | ||
| 260 | #if __ANDROID_API__ < 16 | ||
| 261 | |||
| 262 | /* Select self-pipe. */ | ||
| 263 | static int select_pipe[2]; | ||
| 264 | |||
| 265 | #endif | ||
| 266 | |||
| 260 | static void * | 267 | static void * |
| 261 | android_run_select_thread (void *data) | 268 | android_run_select_thread (void *data) |
| 262 | { | 269 | { |
| 270 | int rc; | ||
| 271 | #if __ANDROID_API__ < 16 | ||
| 272 | int nfds; | ||
| 273 | fd_set readfds; | ||
| 274 | char byte; | ||
| 275 | #else | ||
| 263 | sigset_t signals, waitset; | 276 | sigset_t signals, waitset; |
| 264 | int rc, sig; | 277 | #endif |
| 265 | |||
| 266 | sigfillset (&signals); | ||
| 267 | 278 | ||
| 268 | #if __ANDROID_API__ < 16 | 279 | #if __ANDROID_API__ < 16 |
| 269 | /* sigprocmask must be used instead of pthread_sigmask due to a bug | 280 | /* A completely different implementation is used when building for |
| 270 | in Android versions earlier than 16. It only affects the calling | 281 | Android versions earlier than 16, because pselect with a signal |
| 271 | thread on Android anyhow. */ | 282 | mask does not work there. Instead of blocking SIGUSR1 and |
| 283 | unblocking it inside pselect, a file descriptor is used instead. | ||
| 284 | Something is written to the file descriptor every time select is | ||
| 285 | supposed to return. */ | ||
| 272 | 286 | ||
| 273 | if (sigprocmask (SIG_BLOCK, &signals, NULL)) | 287 | while (true) |
| 274 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 288 | { |
| 275 | "sigprocmask: %s", | 289 | /* Wait for the thread to be released. */ |
| 276 | strerror (errno)); | 290 | while (sem_wait (&android_pselect_start_sem) < 0) |
| 291 | ;; | ||
| 292 | |||
| 293 | /* Get the select lock and call pselect. API 8 does not have | ||
| 294 | working pselect in any sense. Instead, pselect wakes up on | ||
| 295 | select_pipe[0]. */ | ||
| 296 | |||
| 297 | pthread_mutex_lock (&event_queue.select_mutex); | ||
| 298 | nfds = android_pselect_nfds; | ||
| 299 | readfds = *android_pselect_readfds; | ||
| 300 | |||
| 301 | if (nfds < select_pipe[0] + 1) | ||
| 302 | nfds = select_pipe[0] + 1; | ||
| 303 | FD_SET (select_pipe[0], &readfds); | ||
| 304 | |||
| 305 | rc = pselect (nfds, &readfds, | ||
| 306 | android_pselect_writefds, | ||
| 307 | android_pselect_exceptfds, | ||
| 308 | android_pselect_timeout, | ||
| 309 | NULL); | ||
| 310 | |||
| 311 | /* Subtract 1 from rc if writefds contains the select pipe. */ | ||
| 312 | if (FD_ISSET (select_pipe[0], | ||
| 313 | android_pselect_writefds)) | ||
| 314 | rc -= 1; | ||
| 315 | |||
| 316 | android_pselect_rc = rc; | ||
| 317 | pthread_mutex_unlock (&event_queue.select_mutex); | ||
| 318 | |||
| 319 | /* Signal the main thread that there is now data to read. | ||
| 320 | It is ok to signal this condition variable without holding | ||
| 321 | the event queue lock, because android_select will always | ||
| 322 | wait for this to complete before returning. */ | ||
| 323 | android_pselect_completed = true; | ||
| 324 | pthread_cond_signal (&event_queue.read_var); | ||
| 325 | |||
| 326 | /* Read a single byte from the select pipe. */ | ||
| 327 | read (select_pipe[0], &byte, 1); | ||
| 328 | |||
| 329 | |||
| 330 | /* Signal the Emacs thread that pselect is done. If read_var | ||
| 331 | was signaled by android_write_event, event_queue.mutex could | ||
| 332 | still be locked, so this must come before. */ | ||
| 333 | sem_post (&android_pselect_sem); | ||
| 334 | } | ||
| 277 | #else | 335 | #else |
| 278 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) | 336 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) |
| 279 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 337 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 280 | "pthread_sigmask: %s", | 338 | "pthread_sigmask: %s", |
| 281 | strerror (errno)); | 339 | strerror (errno)); |
| 282 | #endif | ||
| 283 | 340 | ||
| 341 | sigfillset (&signals); | ||
| 284 | sigdelset (&signals, SIGUSR1); | 342 | sigdelset (&signals, SIGUSR1); |
| 285 | sigemptyset (&waitset); | 343 | sigemptyset (&waitset); |
| 286 | sigaddset (&waitset, SIGUSR1); | 344 | sigaddset (&waitset, SIGUSR1); |
| @@ -321,10 +379,13 @@ android_run_select_thread (void *data) | |||
| 321 | still be locked, so this must come before. */ | 379 | still be locked, so this must come before. */ |
| 322 | sem_post (&android_pselect_sem); | 380 | sem_post (&android_pselect_sem); |
| 323 | } | 381 | } |
| 382 | #endif | ||
| 324 | 383 | ||
| 325 | return NULL; | 384 | return NULL; |
| 326 | } | 385 | } |
| 327 | 386 | ||
| 387 | #if __ANDROID_API__ >= 16 | ||
| 388 | |||
| 328 | static void | 389 | static void |
| 329 | android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) | 390 | android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) |
| 330 | { | 391 | { |
| @@ -332,6 +393,8 @@ android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) | |||
| 332 | sure the disposition of SIGUSR1 is enough. */ | 393 | sure the disposition of SIGUSR1 is enough. */ |
| 333 | } | 394 | } |
| 334 | 395 | ||
| 396 | #endif | ||
| 397 | |||
| 335 | /* Set up the global event queue by initializing the mutex and two | 398 | /* Set up the global event queue by initializing the mutex and two |
| 336 | condition variables, and the linked list of events. This must be | 399 | condition variables, and the linked list of events. This must be |
| 337 | called before starting the Emacs thread. Also, initialize the | 400 | called before starting the Emacs thread. Also, initialize the |
| @@ -366,12 +429,29 @@ android_init_events (void) | |||
| 366 | event_queue.events.next = &event_queue.events; | 429 | event_queue.events.next = &event_queue.events; |
| 367 | event_queue.events.last = &event_queue.events; | 430 | event_queue.events.last = &event_queue.events; |
| 368 | 431 | ||
| 432 | #if __ANDROID_API__ >= 16 | ||
| 433 | |||
| 369 | /* Before starting the select thread, make sure the disposition for | 434 | /* Before starting the select thread, make sure the disposition for |
| 370 | SIGUSR1 is correct. */ | 435 | SIGUSR1 is correct. */ |
| 371 | sigfillset (&sa.sa_mask); | 436 | sigfillset (&sa.sa_mask); |
| 372 | sa.sa_sigaction = android_handle_sigusr1; | 437 | sa.sa_sigaction = android_handle_sigusr1; |
| 373 | sa.sa_flags = SA_SIGINFO; | 438 | sa.sa_flags = SA_SIGINFO; |
| 374 | 439 | ||
| 440 | #else | ||
| 441 | |||
| 442 | /* Set up the file descriptor used to wake up pselect. */ | ||
| 443 | if (pipe2 (select_pipe, O_CLOEXEC) < 0) | ||
| 444 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 445 | "pipe2: %s", strerror (errno)); | ||
| 446 | |||
| 447 | /* Make sure the read end will fit in fd_set. */ | ||
| 448 | if (select_pipe[0] >= FD_SETSIZE) | ||
| 449 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 450 | "read end of select pipe" | ||
| 451 | " lies outside FD_SETSIZE!"); | ||
| 452 | |||
| 453 | #endif | ||
| 454 | |||
| 375 | if (sigaction (SIGUSR1, &sa, NULL)) | 455 | if (sigaction (SIGUSR1, &sa, NULL)) |
| 376 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 456 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 377 | "sigaction: %s", | 457 | "sigaction: %s", |
| @@ -479,6 +559,7 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 479 | fd_set *exceptfds, struct timespec *timeout) | 559 | fd_set *exceptfds, struct timespec *timeout) |
| 480 | { | 560 | { |
| 481 | int nfds_return; | 561 | int nfds_return; |
| 562 | static char byte; | ||
| 482 | 563 | ||
| 483 | pthread_mutex_lock (&event_queue.mutex); | 564 | pthread_mutex_lock (&event_queue.mutex); |
| 484 | 565 | ||
| @@ -505,9 +586,16 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 505 | /* Start waiting for the event queue condition to be set. */ | 586 | /* Start waiting for the event queue condition to be set. */ |
| 506 | pthread_cond_wait (&event_queue.read_var, &event_queue.mutex); | 587 | pthread_cond_wait (&event_queue.read_var, &event_queue.mutex); |
| 507 | 588 | ||
| 589 | #if __ANDROID_API__ >= 16 | ||
| 508 | /* Interrupt the select thread now, in case it's still in | 590 | /* Interrupt the select thread now, in case it's still in |
| 509 | pselect. */ | 591 | pselect. */ |
| 510 | pthread_kill (event_queue.select_thread, SIGUSR1); | 592 | pthread_kill (event_queue.select_thread, SIGUSR1); |
| 593 | #else | ||
| 594 | /* Interrupt the select thread by writing to the select pipe. */ | ||
| 595 | if (write (select_pipe[1], &byte, 1) != 1) | ||
| 596 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 597 | "write: %s", strerror (errno)); | ||
| 598 | #endif | ||
| 511 | 599 | ||
| 512 | /* Wait for pselect to return in any case. */ | 600 | /* Wait for pselect to return in any case. */ |
| 513 | while (sem_wait (&android_pselect_sem) < 0) | 601 | while (sem_wait (&android_pselect_sem) < 0) |
| @@ -4425,8 +4513,6 @@ android_project_image_nearest (struct android_image *image, | |||
| 4425 | int | 4513 | int |
| 4426 | android_ftruncate (int fd, off_t length) | 4514 | android_ftruncate (int fd, off_t length) |
| 4427 | { | 4515 | { |
| 4428 | int rc; | ||
| 4429 | |||
| 4430 | #if defined __arm__ || defined __mips__ | 4516 | #if defined __arm__ || defined __mips__ |
| 4431 | return syscall (SYS_ftruncate64, fd, 0, | 4517 | return syscall (SYS_ftruncate64, fd, 0, |
| 4432 | (unsigned int) (length & 0xffffffff), | 4518 | (unsigned int) (length & 0xffffffff), |