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/thread.c | |
| 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/thread.c')
| -rw-r--r-- | src/thread.c | 33 |
1 files changed, 25 insertions, 8 deletions
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 | } |