aboutsummaryrefslogtreecommitdiffstats
path: root/src/thread.c
diff options
context:
space:
mode:
authorEli Zaretskii2017-10-04 10:27:49 +0300
committerEli Zaretskii2017-10-04 10:27:49 +0300
commitea39d470bf35e45f1d8e39795f06ac74b3c37fc7 (patch)
tree406dbe320ffd5c9e2a31fd1b8568e119e50e9279 /src/thread.c
parentfdbaebde08f4e53e3fc06fae99398c68a4e285fb (diff)
downloademacs-ea39d470bf35e45f1d8e39795f06ac74b3c37fc7.tar.gz
emacs-ea39d470bf35e45f1d8e39795f06ac74b3c37fc7.zip
Avoid crashes on C-g when several threads wait for input
* src/thread.h (m_getcjmp): New member of 'struct thread_state'. (getcjmp): Define to current thread's 'm_getcjmp'. * src/thread.c (maybe_reacquire_global_lock): Switch to main thread, since this is called from a SIGINT handler, which always runs in the context of the main thread. * src/lisp.h (sys_jmp_buf, sys_setjmp, sys_longjmp): Move the definitions before thread.h is included, as thread.h now uses sys_jmp_buf. * src/keyboard.c (getcjmp): Remove declaration. (read_char): Don't call maybe_reacquire_global_lock here. (handle_interrupt): Call maybe_reacquire_global_lock here, if invoked from the SIGINT handler, to make sure quit_throw_to_read_char runs with main thread's Lisp bindings and uses the main thread's jmp_buf buffer. (Bug#28630)
Diffstat (limited to 'src/thread.c')
-rw-r--r--src/thread.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/thread.c b/src/thread.c
index 42d7791ad0f..d075bdb3a13 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -101,14 +101,20 @@ acquire_global_lock (struct thread_state *self)
101 post_acquire_global_lock (self); 101 post_acquire_global_lock (self);
102} 102}
103 103
104/* This is called from keyboard.c when it detects that SIGINT 104/* This is called from keyboard.c when it detects that SIGINT was
105 interrupted thread_select before the current thread could acquire 105 delivered to the main thread and interrupted thread_select before
106 the lock. We must acquire the lock to prevent a thread from 106 the main thread could acquire the lock. We must acquire the lock
107 running without holding the global lock, and to avoid repeated 107 to prevent a thread from running without holding the global lock,
108 calls to sys_mutex_unlock, which invokes undefined behavior. */ 108 and to avoid repeated calls to sys_mutex_unlock, which invokes
109 undefined behavior. */
109void 110void
110maybe_reacquire_global_lock (void) 111maybe_reacquire_global_lock (void)
111{ 112{
113 /* SIGINT handler is always run on the main thread, see
114 deliver_process_signal, so reflect that in our thread-tracking
115 variables. */
116 current_thread = &main_thread;
117
112 if (current_thread->not_holding_lock) 118 if (current_thread->not_holding_lock)
113 { 119 {
114 struct thread_state *self = current_thread; 120 struct thread_state *self = current_thread;