aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Albinus2018-08-30 21:29:04 +0200
committerMichael Albinus2018-08-30 21:29:04 +0200
commit54b92132e1ec16565d59d6d9f8ff8910f38843b2 (patch)
tree894a20a1c835c5da28d0b74a26667efed5aac189 /src
parent3cc42bb60099c32f64e57d2ee33c8321adba7942 (diff)
downloademacs-54b92132e1ec16565d59d6d9f8ff8910f38843b2.tar.gz
emacs-54b92132e1ec16565d59d6d9f8ff8910f38843b2.zip
Handle thread-signal towards the main thread (Bug#32502)
* doc/lispref/threads.texi (Basic Thread Functions): * etc/NEWS: Document thread-signal towards the main thread. * lisp/emacs-lisp/thread.el: New package. * src/keyboard.c (read_char): Check for Qthread_event. (kbd_buffer_get_event, make_lispy_event): Handle THREAD_EVENT. (syms_of_keyboard): Declare Qthread_event. (keys_of_keyboard): Add thread-handle-event to special-event-map. * src/termhooks.h (enum event_kind): Add THREAD_EVENT. * src/thread.c: Include "keyboard.h". (poll_suppress_count) Don't declare extern. (Fthread_signal): Raise event if THREAD is the main thread. (Bug#32502) * test/src/thread-tests.el (thread): Require it. (threads-signal-main-thread): New test.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c27
-rw-r--r--src/termhooks.h4
-rw-r--r--src/thread.c33
3 files changed, 54 insertions, 10 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 7fafb41fcc5..008d3b9d7c0 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2828,6 +2828,9 @@ read_char (int commandflag, Lisp_Object map,
2828#ifdef USE_FILE_NOTIFY 2828#ifdef USE_FILE_NOTIFY
2829 || EQ (XCAR (c), Qfile_notify) 2829 || EQ (XCAR (c), Qfile_notify)
2830#endif 2830#endif
2831#ifdef THREADS_ENABLED
2832 || EQ (XCAR (c), Qthread_event)
2833#endif
2831 || EQ (XCAR (c), Qconfig_changed_event)) 2834 || EQ (XCAR (c), Qconfig_changed_event))
2832 && !end_time) 2835 && !end_time)
2833 /* We stopped being idle for this event; undo that. This 2836 /* We stopped being idle for this event; undo that. This
@@ -3739,7 +3742,7 @@ kbd_buffer_get_event (KBOARD **kbp,
3739 } 3742 }
3740#endif /* subprocesses */ 3743#endif /* subprocesses */
3741 3744
3742#if !defined HAVE_DBUS && !defined USE_FILE_NOTIFY 3745#if !defined HAVE_DBUS && !defined USE_FILE_NOTIFY && !defined THREADS_ENABLED
3743 if (noninteractive 3746 if (noninteractive
3744 /* In case we are running as a daemon, only do this before 3747 /* In case we are running as a daemon, only do this before
3745 detaching from the terminal. */ 3748 detaching from the terminal. */
@@ -3750,7 +3753,7 @@ kbd_buffer_get_event (KBOARD **kbp,
3750 *kbp = current_kboard; 3753 *kbp = current_kboard;
3751 return obj; 3754 return obj;
3752 } 3755 }
3753#endif /* !defined HAVE_DBUS && !defined USE_FILE_NOTIFY */ 3756#endif /* !defined HAVE_DBUS && !defined USE_FILE_NOTIFY && !defined THREADS_ENABLED */
3754 3757
3755 /* Wait until there is input available. */ 3758 /* Wait until there is input available. */
3756 for (;;) 3759 for (;;)
@@ -3900,6 +3903,9 @@ kbd_buffer_get_event (KBOARD **kbp,
3900#ifdef HAVE_DBUS 3903#ifdef HAVE_DBUS
3901 case DBUS_EVENT: 3904 case DBUS_EVENT:
3902#endif 3905#endif
3906#ifdef THREADS_ENABLED
3907 case THREAD_EVENT:
3908#endif
3903#ifdef HAVE_XWIDGETS 3909#ifdef HAVE_XWIDGETS
3904 case XWIDGET_EVENT: 3910 case XWIDGET_EVENT:
3905#endif 3911#endif
@@ -5983,6 +5989,13 @@ make_lispy_event (struct input_event *event)
5983 } 5989 }
5984#endif /* HAVE_DBUS */ 5990#endif /* HAVE_DBUS */
5985 5991
5992#ifdef THREADS_ENABLED
5993 case THREAD_EVENT:
5994 {
5995 return Fcons (Qthread_event, event->arg);
5996 }
5997#endif /* THREADS_ENABLED */
5998
5986#ifdef HAVE_XWIDGETS 5999#ifdef HAVE_XWIDGETS
5987 case XWIDGET_EVENT: 6000 case XWIDGET_EVENT:
5988 { 6001 {
@@ -11078,6 +11091,10 @@ syms_of_keyboard (void)
11078 DEFSYM (Qdbus_event, "dbus-event"); 11091 DEFSYM (Qdbus_event, "dbus-event");
11079#endif 11092#endif
11080 11093
11094#ifdef THREADS_ENABLED
11095 DEFSYM (Qthread_event, "thread-event");
11096#endif
11097
11081#ifdef HAVE_XWIDGETS 11098#ifdef HAVE_XWIDGETS
11082 DEFSYM (Qxwidget_event, "xwidget-event"); 11099 DEFSYM (Qxwidget_event, "xwidget-event");
11083#endif 11100#endif
@@ -11929,6 +11946,12 @@ keys_of_keyboard (void)
11929 "dbus-handle-event"); 11946 "dbus-handle-event");
11930#endif 11947#endif
11931 11948
11949#ifdef THREADS_ENABLED
11950 /* Define a special event which is raised for thread signals. */
11951 initial_define_lispy_key (Vspecial_event_map, "thread-event",
11952 "thread-handle-event");
11953#endif
11954
11932#ifdef USE_FILE_NOTIFY 11955#ifdef USE_FILE_NOTIFY
11933 /* Define a special event which is raised for notification callback 11956 /* Define a special event which is raised for notification callback
11934 functions. */ 11957 functions. */
diff --git a/src/termhooks.h b/src/termhooks.h
index 160bd2f4803..8b5f648b43d 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -222,6 +222,10 @@ enum event_kind
222 , DBUS_EVENT 222 , DBUS_EVENT
223#endif 223#endif
224 224
225#ifdef THREADS_ENABLED
226 , THREAD_EVENT
227#endif
228
225 , CONFIG_CHANGED_EVENT 229 , CONFIG_CHANGED_EVENT
226 230
227#ifdef HAVE_NTGUI 231#ifdef HAVE_NTGUI
diff --git a/src/thread.c b/src/thread.c
index 1c73d938655..78cb2161993 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
25#include "process.h" 25#include "process.h"
26#include "coding.h" 26#include "coding.h"
27#include "syssignal.h" 27#include "syssignal.h"
28#include "keyboard.h"
28 29
29static struct thread_state main_thread; 30static struct thread_state main_thread;
30 31
@@ -34,7 +35,6 @@ static struct thread_state *all_threads = &main_thread;
34 35
35static sys_mutex_t global_lock; 36static sys_mutex_t global_lock;
36 37
37extern int poll_suppress_count;
38extern volatile int interrupt_input_blocked; 38extern volatile int interrupt_input_blocked;
39 39
40 40
@@ -863,7 +863,8 @@ DEFUN ("thread-signal", Fthread_signal, Sthread_signal, 3, 3, 0,
863This acts like `signal', but arranges for the signal to be raised 863This acts like `signal', but arranges for the signal to be raised
864in THREAD. If THREAD is the current thread, acts just like `signal'. 864in THREAD. If THREAD is the current thread, acts just like `signal'.
865This will interrupt a blocked call to `mutex-lock', `condition-wait', 865This will interrupt a blocked call to `mutex-lock', `condition-wait',
866or `thread-join' in the target thread. */) 866or `thread-join' in the target thread.
867If THREAD is the main thread, just the error message is shown. */)
867 (Lisp_Object thread, Lisp_Object error_symbol, Lisp_Object data) 868 (Lisp_Object thread, Lisp_Object error_symbol, Lisp_Object data)
868{ 869{
869 struct thread_state *tstate; 870 struct thread_state *tstate;
@@ -874,13 +875,29 @@ or `thread-join' in the target thread. */)
874 if (tstate == current_thread) 875 if (tstate == current_thread)
875 Fsignal (error_symbol, data); 876 Fsignal (error_symbol, data);
876 877
877 /* What to do if thread is already signaled? */ 878 if (main_thread_p (tstate))
878 /* What if error_symbol is Qnil? */ 879 {
879 tstate->error_symbol = error_symbol; 880 /* Construct an event. */
880 tstate->error_data = data; 881 struct input_event event;
882 EVENT_INIT (event);
883 event.kind = THREAD_EVENT;
884 event.frame_or_window = Qnil;
885 event.arg = list3 (Fcurrent_thread (), error_symbol, data);
886
887 /* Store it into the input event queue. */
888 kbd_buffer_store_event (&event);
889 }
890
891 else
892 {
893 /* What to do if thread is already signaled? */
894 /* What if error_symbol is Qnil? */
895 tstate->error_symbol = error_symbol;
896 tstate->error_data = data;
881 897
882 if (tstate->wait_condvar) 898 if (tstate->wait_condvar)
883 flush_stack_call_func (thread_signal_callback, tstate); 899 flush_stack_call_func (thread_signal_callback, tstate);
900 }
884 901
885 return Qnil; 902 return Qnil;
886} 903}