diff options
| author | Michael Albinus | 2018-08-30 21:29:04 +0200 |
|---|---|---|
| committer | Michael Albinus | 2018-08-30 21:29:04 +0200 |
| commit | 54b92132e1ec16565d59d6d9f8ff8910f38843b2 (patch) | |
| tree | 894a20a1c835c5da28d0b74a26667efed5aac189 /src | |
| parent | 3cc42bb60099c32f64e57d2ee33c8321adba7942 (diff) | |
| download | emacs-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.c | 27 | ||||
| -rw-r--r-- | src/termhooks.h | 4 | ||||
| -rw-r--r-- | src/thread.c | 33 |
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 | ||
| 29 | static struct thread_state main_thread; | 30 | static struct thread_state main_thread; |
| 30 | 31 | ||
| @@ -34,7 +35,6 @@ static struct thread_state *all_threads = &main_thread; | |||
| 34 | 35 | ||
| 35 | static sys_mutex_t global_lock; | 36 | static sys_mutex_t global_lock; |
| 36 | 37 | ||
| 37 | extern int poll_suppress_count; | ||
| 38 | extern volatile int interrupt_input_blocked; | 38 | extern volatile int interrupt_input_blocked; |
| 39 | 39 | ||
| 40 | 40 | ||
| @@ -863,7 +863,8 @@ DEFUN ("thread-signal", Fthread_signal, Sthread_signal, 3, 3, 0, | |||
| 863 | This acts like `signal', but arranges for the signal to be raised | 863 | This acts like `signal', but arranges for the signal to be raised |
| 864 | in THREAD. If THREAD is the current thread, acts just like `signal'. | 864 | in THREAD. If THREAD is the current thread, acts just like `signal'. |
| 865 | This will interrupt a blocked call to `mutex-lock', `condition-wait', | 865 | This will interrupt a blocked call to `mutex-lock', `condition-wait', |
| 866 | or `thread-join' in the target thread. */) | 866 | or `thread-join' in the target thread. |
| 867 | If 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 | } |