From 0ad5fd4b6cac1824e50e5e8c1a43878825e7d3de Mon Sep 17 00:00:00 2001 From: Alan Third Date: Sat, 1 Jul 2017 12:58:49 +0100 Subject: [PATCH] Fix threads on NS (bug#25265) src/nsterm.h (ns_select): Compiler doesn't like sigmask being const. (ns_run_loop_break) [HAVE_PTHREAD]: New function. src/nsterm.m (ns_select): Call thread_select from within ns_select. (ns_run_loop_break) [HAVE_PTHREAD]: New function. (ns_send_appdefined): Don't wait for main thread when sending app defined event. src/process.c (wait_reading_process_output): Call thread_select from within ns_select. src/systhread.c (sys_cond_broadcast) [HAVE_NS]: Break ns_select out of its event loop using ns_run_loop_break. --- src/nsterm.h | 7 +++++-- src/nsterm.m | 26 ++++++++++++++++++++++---- src/process.c | 13 ++++++------- src/systhread.c | 11 +++++++++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/nsterm.h b/src/nsterm.h index 84f7f0ab574..0f1b36db7b2 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1233,8 +1233,11 @@ extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, extern void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timespec const *timeout, - sigset_t const *sigmask); + fd_set *exceptfds, struct timespec *timeout, + sigset_t *sigmask); +#ifdef HAVE_PTHREAD +extern void ns_run_loop_break (void); +#endif extern unsigned long ns_get_rgb_color (struct frame *f, float r, float g, float b, float a); diff --git a/src/nsterm.m b/src/nsterm.m index e05dbf45fbc..bf83550b3d7 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4068,7 +4068,7 @@ ns_send_appdefined (int value) app->nextappdefined = value; [app performSelectorOnMainThread:@selector (sendFromMainThread:) withObject:nil - waitUntilDone:YES]; + waitUntilDone:NO]; return; } @@ -4293,8 +4293,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) int ns_select (int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timespec const *timeout, - sigset_t const *sigmask) + fd_set *exceptfds, struct timespec *timeout, + sigset_t *sigmask) /* -------------------------------------------------------------------------- Replacement for select, checking for events -------------------------------------------------------------------------- */ @@ -4327,7 +4327,13 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, if (NSApp == nil || ![NSThread isMainThread] || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) - return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); + return thread_select(pselect, nfds, readfds, writefds, + exceptfds, timeout, sigmask); + else + { + struct timespec t = {0, 0}; + thread_select(pselect, 0, NULL, NULL, NULL, &t, sigmask); + } [outerpool release]; outerpool = [[NSAutoreleasePool alloc] init]; @@ -4430,6 +4436,18 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, return result; } +#ifdef HAVE_PTHREAD +void +ns_run_loop_break () +/* Break out of the NS run loop in ns_select or ns_read_socket. */ +{ + NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_run_loop_break"); + + /* If we don't have a GUI, don't send the event. */ + if (NSApp != NULL) + ns_send_appdefined(-1); +} +#endif /* ========================================================================== diff --git a/src/process.c b/src/process.c index 2a1c2eecde3..abd017bb907 100644 --- a/src/process.c +++ b/src/process.c @@ -5371,14 +5371,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, nfds = xg_select (max_desc + 1, &Available, (check_write ? &Writeok : 0), NULL, &timeout, NULL); +#elif defined HAVE_NS + /* And NS builds call thread_select in ns_select. */ + nfds = ns_select (max_desc + 1, + &Available, (check_write ? &Writeok : 0), + NULL, &timeout, NULL); #else /* !HAVE_GLIB */ - nfds = thread_select ( -# ifdef HAVE_NS - ns_select -# else - pselect -# endif - , max_desc + 1, + nfds = thread_select (pselect, max_desc + 1, &Available, (check_write ? &Writeok : 0), NULL, &timeout, NULL); diff --git a/src/systhread.c b/src/systhread.c index a84060c18f0..aee12a9b482 100644 --- a/src/systhread.c +++ b/src/systhread.c @@ -20,6 +20,10 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#ifdef HAVE_NS +#include "nsterm.h" +#endif + #ifndef THREADS_ENABLED void @@ -130,6 +134,13 @@ void sys_cond_broadcast (sys_cond_t *cond) { pthread_cond_broadcast (cond); +#ifdef HAVE_NS + /* Send an app defined event to break out of the NS run loop. + It seems that if ns_select is running the NS run loop, this + broadcast has no effect until the loop is done, breaking a couple + of tests in thread-tests.el. */ + ns_run_loop_break (); +#endif } void -- 2.39.2