aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-09-01 18:43:43 +0300
committerEli Zaretskii2013-09-01 18:43:43 +0300
commitbed10876dba330b24419a6144dc62db52bb273ab (patch)
treea5480db866493e1fa7db43bdc2c8b4bbde0ac4a6 /src
parente57df8f77901a3964d21c3d57fb6769cf4511dc2 (diff)
downloademacs-bed10876dba330b24419a6144dc62db52bb273ab.tar.gz
emacs-bed10876dba330b24419a6144dc62db52bb273ab.zip
Fix crashes when unbind_for_thread_switch signals an error.
src/eval.c (unbind_for_thread_switch): Accept a 'struct thread_state *' argument and use specpdl_ptr and specpdl of that thread. Fixes crashes if find_symbol_value signals an error. src/thread.c (post_acquire_global_lock): Update current_thread before calling unbind_for_thread_switch. Pass the previous thread to unbind_for_thread_switch.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog10
-rw-r--r--src/eval.c4
-rw-r--r--src/lisp.h2
-rw-r--r--src/thread.c15
4 files changed, 23 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 3e901d84db9..705b9c771df 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
12013-09-01 Eli Zaretskii <eliz@gnu.org>
2
3 * eval.c (unbind_for_thread_switch): Accept a 'struct
4 thread_state *' argument and use specpdl_ptr and specpdl of that
5 thread. Fixes crashes if find_symbol_value signals an error.
6
7 * thread.c (post_acquire_global_lock): Update current_thread
8 before calling unbind_for_thread_switch. Pass the previous thread
9 to unbind_for_thread_switch.
10
12013-08-31 Eli Zaretskii <eliz@gnu.org> 112013-08-31 Eli Zaretskii <eliz@gnu.org>
2 12
3 * systhread.c (sys_cond_init): Set the 'initialized' member to 13 * systhread.c (sys_cond_init): Set the 'initialized' member to
diff --git a/src/eval.c b/src/eval.c
index 68a3691ad9b..b8a61590387 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3484,11 +3484,11 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
3484} 3484}
3485 3485
3486void 3486void
3487unbind_for_thread_switch (void) 3487unbind_for_thread_switch (struct thread_state *thr)
3488{ 3488{
3489 union specbinding *bind; 3489 union specbinding *bind;
3490 3490
3491 for (bind = specpdl_ptr; bind != specpdl; --bind) 3491 for (bind = thr->m_specpdl_ptr; bind != thr->m_specpdl; --bind)
3492 { 3492 {
3493 if (bind->kind >= SPECPDL_LET) 3493 if (bind->kind >= SPECPDL_LET)
3494 { 3494 {
diff --git a/src/lisp.h b/src/lisp.h
index 51c09e0abb3..03628e13ac2 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3828,7 +3828,7 @@ extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object);
3828extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *); 3828extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
3829extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object); 3829extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
3830extern void rebind_for_thread_switch (void); 3830extern void rebind_for_thread_switch (void);
3831extern void unbind_for_thread_switch (void); 3831extern void unbind_for_thread_switch (struct thread_state *);
3832extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); 3832extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
3833extern _Noreturn void verror (const char *, va_list) 3833extern _Noreturn void verror (const char *, va_list)
3834 ATTRIBUTE_FORMAT_PRINTF (1, 0); 3834 ATTRIBUTE_FORMAT_PRINTF (1, 0);
diff --git a/src/thread.c b/src/thread.c
index 39a21518ec6..f060a002a3a 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -55,15 +55,20 @@ static void
55post_acquire_global_lock (struct thread_state *self) 55post_acquire_global_lock (struct thread_state *self)
56{ 56{
57 Lisp_Object buffer; 57 Lisp_Object buffer;
58 struct thread_state *prev_thread = current_thread;
58 59
59 if (self != current_thread) 60 /* Do this early on, so that code below could signal errors (e.g.,
61 unbind_for_thread_switch might) correctly, because we are already
62 running in the context of the thread pointed by SELF. */
63 current_thread = self;
64
65 if (prev_thread != current_thread)
60 { 66 {
61 /* CURRENT_THREAD is NULL if the previously current thread 67 /* PREV_THREAD is NULL if the previously current thread
62 exited. In this case, there is no reason to unbind, and 68 exited. In this case, there is no reason to unbind, and
63 trying will crash. */ 69 trying will crash. */
64 if (current_thread != NULL) 70 if (prev_thread != NULL)
65 unbind_for_thread_switch (); 71 unbind_for_thread_switch (prev_thread);
66 current_thread = self;
67 rebind_for_thread_switch (); 72 rebind_for_thread_switch ();
68 } 73 }
69 74