aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-01-20 21:21:15 +0800
committerPo Lu2023-01-20 21:21:15 +0800
commit26f0dd508982b9680a3cc5d7c56d5f978e06dc8f (patch)
tree6d9f3c132bbe16d8fef0cbebc45e65f7fda983fc /src
parent01ee2bd07be203987c003b8155ae10b89b0dc08a (diff)
downloademacs-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')
-rw-r--r--src/android.c112
-rw-r--r--src/androidterm.c13
2 files changed, 107 insertions, 18 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. */
258static sem_t android_pselect_sem, android_pselect_start_sem; 258static sem_t android_pselect_sem, android_pselect_start_sem;
259 259
260#if __ANDROID_API__ < 16
261
262/* Select self-pipe. */
263static int select_pipe[2];
264
265#endif
266
260static void * 267static void *
261android_run_select_thread (void *data) 268android_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
328static void 389static void
329android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) 390android_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,
4425int 4513int
4426android_ftruncate (int fd, off_t length) 4514android_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),
diff --git a/src/androidterm.c b/src/androidterm.c
index 3024890d789..1141f50f266 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -966,6 +966,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
966 touchpoint->x = event->touch.x; 966 touchpoint->x = event->touch.x;
967 touchpoint->y = event->touch.x; 967 touchpoint->y = event->touch.x;
968 touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points; 968 touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points;
969 touchpoint->tool_bar_p = false;
969 FRAME_OUTPUT_DATA (any)->touch_points = touchpoint; 970 FRAME_OUTPUT_DATA (any)->touch_points = touchpoint;
970 971
971 /* Figure out whether or not the tool was pressed on the tool 972 /* Figure out whether or not the tool was pressed on the tool
@@ -1072,13 +1073,10 @@ handle_one_android_event (struct android_display_info *dpyinfo,
1072 { 1073 {
1073 *last = touchpoint->next; 1074 *last = touchpoint->next;
1074 1075
1075 /* The tool was unlinked. Free it and generate the
1076 appropriate Emacs event (assuming that it was not
1077 grabbed by the tool bar). */
1078 xfree (touchpoint);
1079
1080 if (touchpoint->tool_bar_p) 1076 if (touchpoint->tool_bar_p)
1081 { 1077 {
1078 xfree (touchpoint);
1079
1082 /* Do what is necessary to release the tool bar and 1080 /* Do what is necessary to release the tool bar and
1083 possibly trigger a click. */ 1081 possibly trigger a click. */
1084 1082
@@ -1094,6 +1092,11 @@ handle_one_android_event (struct android_display_info *dpyinfo,
1094 goto OTHER; 1092 goto OTHER;
1095 } 1093 }
1096 1094
1095 /* The tool was unlinked. Free it and generate the
1096 appropriate Emacs event (assuming that it was not
1097 grabbed by the tool bar). */
1098 xfree (touchpoint);
1099
1097 inev.ie.kind = TOUCHSCREEN_END_EVENT; 1100 inev.ie.kind = TOUCHSCREEN_END_EVENT;
1098 inev.ie.timestamp = event->touch.time; 1101 inev.ie.timestamp = event->touch.time;
1099 1102