]> git.eshelyaron.com Git - emacs.git/commitdiff
Add variable main-thread, fix Bug#32169
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 17 Jul 2018 10:03:43 +0000 (12:03 +0200)
committerMichael Albinus <michael.albinus@gmx.de>
Tue, 17 Jul 2018 10:03:43 +0000 (12:03 +0200)
* doc/lispref/threads.texi (Basic Thread Functions): Add example,
how to propagate signals to the main thread.  Describe variable
`main-thread'.  Document optional argument CLEANUP of
`thread-last-error'.

* src/thread.c (Fthread_last_error): Add optional argument
CLEANUP.  (Bug#32169)
(main-thread): New defvar.

* test/src/thread-tests.el (thread-last-error): Adapt declaration.
(main-thread): Declare.
(threads-main-thread): New test.
(threads-errors): Extend test.

doc/lispref/threads.texi
src/thread.c
test/src/thread-tests.el

index f05af496188c3657add28ab27feff612b4251797..4cef9c9c6e82e29b96bb7fe6a0664e2b34a444fd 100644 (file)
@@ -87,6 +87,15 @@ thread, then this just calls @code{signal} immediately.  Otherwise,
 If @var{thread} was blocked by a call to @code{mutex-lock},
 @code{condition-wait}, or @code{thread-join}; @code{thread-signal}
 will unblock it.
+
+Since signal handlers in Emacs are located in the main thread, a
+signal must be propagated there in order to become visible.  The
+second @code{signal} call let the thread die:
+
+@example
+(thread-signal main-thread 'error data)
+(signal 'error data)
+@end example
 @end defun
 
 @defun thread-yield
@@ -127,15 +136,21 @@ Return a list of all the live thread objects.  A new list is returned
 by each invocation.
 @end defun
 
+@defvar main-thread
+This variable keeps the main thread Emacs is running, or @code{nil} if
+Emacs is compiled without thread support.
+@end defvar
+
 When code run by a thread signals an error that is unhandled, the
 thread exits.  Other threads can access the error form which caused
 the thread to exit using the following function.
 
-@defun thread-last-error
+@defun thread-last-error &optional cleanup
 This function returns the last error form recorded when a thread
 exited due to an error.  Each thread that exits abnormally overwrites
 the form stored by the previous thread's error with a new value, so
-only the last one can be accessed.
+only the last one can be accessed.  If @var{cleanup} is
+non-@code{nil}, the stored form is reset to @code{nil}.
 @end defun
 
 @node Mutexes
index 3eba25b7b43769008b27c542b98b370e1310e625..754d286e9f896ae3af422bc5e72d5d253e37f99a 100644 (file)
@@ -973,11 +973,17 @@ DEFUN ("all-threads", Fall_threads, Sall_threads, 0, 0, 0,
   return result;
 }
 
-DEFUN ("thread-last-error", Fthread_last_error, Sthread_last_error, 0, 0, 0,
-       doc: /* Return the last error form recorded by a dying thread.  */)
-  (void)
+DEFUN ("thread-last-error", Fthread_last_error, Sthread_last_error, 0, 1, 0,
+       doc: /* Return the last error form recorded by a dying thread.
+If CLEANUP is non-nil, remove this error form from history.  */)
+     (Lisp_Object cleanup)
 {
-  return last_thread_error;
+  Lisp_Object result = last_thread_error;
+
+  if (!NILP (cleanup))
+    last_thread_error = Qnil;
+
+  return result;
 }
 
 \f
@@ -1083,4 +1089,13 @@ syms_of_threads (void)
   DEFSYM (Qthreadp, "threadp");
   DEFSYM (Qmutexp, "mutexp");
   DEFSYM (Qcondition_variable_p, "condition-variable-p");
+
+  DEFVAR_LISP ("main-thread",
+              Vmain_thread,
+    doc: /* The main thread of Emacs.  */);
+#ifdef THREADS_ENABLED
+  XSETTHREAD (Vmain_thread, &main_thread);
+#else
+  Vmain_thread = Qnil;
+#endif
 }
index a00a9c84bd6affde303876c27f8d0f245602378d..a447fb3914e5061e5a761fd31dad7f8451cbd11d 100644 (file)
 (declare-function thread--blocker "thread.c" (thread))
 (declare-function thread-alive-p "thread.c" (thread))
 (declare-function thread-join "thread.c" (thread))
-(declare-function thread-last-error "thread.c" ())
+(declare-function thread-last-error "thread.c" (&optional cleanup))
 (declare-function thread-name "thread.c" (thread))
 (declare-function thread-signal "thread.c" (thread error-symbol data))
 (declare-function thread-yield "thread.c" ())
+(defvar main-thread)
 
 (ert-deftest threads-is-one ()
   "Test for existence of a thread."
   (skip-unless (featurep 'threads))
   (should (listp (all-threads))))
 
+(ert-deftest threads-main-thread ()
+  "Simple test for all-threads."
+  (skip-unless (featurep 'threads))
+  (should (eq main-thread (car (all-threads)))))
+
 (defvar threads-test-global nil)
 
 (defun threads-test-thread1 ()
       (thread-yield))
     (should (equal (thread-last-error)
                    '(error "Error is called")))
+    (should (equal (thread-last-error 'cleanup)
+                   '(error "Error is called")))
+    (should-not (thread-last-error))
     (setq th2 (make-thread #'threads-custom "threads-custom"))
     (should (threadp th2))))