Subject: Re: bug#25265: make-thread crashes in OS X 10.6

From: Alan Third <[email-masked]>
Date: Tue, 13 Jun 2017 21:46:43 +0100

On Mon, Jun 12, 2017 at 09:32:21PM +0200, Charles A. Roelli wrote:
> The issue seems to be improved now (not sure what changed it).
> 
> I tried this sample code, and it worked without a crash:
> 
> (dotimes (i 100)
>   (make-thread (lambda () "string")))
> 
> Then I tried this code, and there's a crash every few runs (or
> sometimes, an infinite loop that can't be exited without killing the
> process).  The crash normally happens when I supply input (via the
> keyboard), and the loop seems to be happen randomly.
> 
> (make-thread (lambda ()
>            (dotimes (i 10)
>               (sit-for 1)
>               (goto-char (random (buffer-size))))))

I went back and noticed an approach Eli suggested that I had given up
on, but understood this time round.

I’ve attached a patch that seems to not crash. It introduces a warning
or two, and test/src/thread-tests.el randomly fails up to two tests,
but no crashes afaics.

> I also noticed GDB's I/O buffer printing many of these warnings as
> soon as the `make-thread' form was called:
> 
> 2017-06-12 21:13:55.943 Emacs[10829:6683] *** __NSAutoreleaseNoPool():
> Object 0x10216bf50 of class NSBezierPath autoreleased with no pool in place
> - just leaking
> 2017-06-12 21:13:55.944 Emacs[10829:6683] *** __NSAutoreleaseNoPool():
> Object 0x101ec41b0 of class NSBezierPath autoreleased with no pool in place
> - just leaking
> 2017-06-12 21:13:56.443 Emacs[10829:6683] *** __NSAutoreleaseNoPool():
> Object 0x10216c0f0 of class NSBezierPath autoreleased with no pool in place
> - just leaking
> 2017-06-12 21:13:56.444 Emacs[10829:6683] *** __NSAutoreleaseNoPool():
> Object 0x101ec43e0 of class NSBezierPath autoreleased with no pool in place
> - just leaking

It must be a sub‐thread running some objective c code without an
autorelease pool. It would be nice to be able to work out where that’s
happening. Perhaps threads will need to define an autorelease pool on
creation, and drain it on ending...
-- 
Alan Third
>From 22c33d9f2516dd488c3d76ccb3360e4855df7bb6 Mon Sep 17 00:00:00 2001
From: Alan Third <[email-masked]>
Date: Tue, 13 Jun 2017 21:40:25 +0100
Subject: [PATCH] Fix threads on NS (bug#25265)

---
 src/nsterm.h  |  2 +-
 src/nsterm.m  | 10 ++++++++--
 src/process.c |  4 ++++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/nsterm.h b/src/nsterm.h
index bed0b92c79..10d5db2cff 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1226,7 +1226,7 @@ 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);
+		      sigset_t *sigmask);
 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 e05dbf45fb..8fc27ed752 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -4294,7 +4294,7 @@ in certain situations (rapid incoming events).
 int
 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
 	   fd_set *exceptfds, struct timespec const *timeout,
-	   sigset_t const *sigmask)
+	   sigset_t *sigmask)
 /* --------------------------------------------------------------------------
      Replacement for select, checking for events
    -------------------------------------------------------------------------- */
@@ -4327,7 +4327,13 @@ in certain situations (rapid incoming events).
   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];
diff --git a/src/process.c b/src/process.c
index 2a1c2eecde..eec907e14a 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5371,6 +5371,10 @@ 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
+          nfds = ns_select (max_desc + 1,
+			    &Available, (check_write ? &Writeok : 0),
+			    NULL, &timeout, NULL);
 #else  /* !HAVE_GLIB */
 	  nfds = thread_select (
 # ifdef HAVE_NS
-- 
2.12.0