2012-09-11 Paul Eggert <eggert@cs.ucla.edu>
+ Avoid _setjmp/_longjmp problems with local nonvolatile variables.
+ If a nonvolatile local variable is written before a _longjmp to
+ the frame containing the variable, and is read after the _longjmp,
+ the value read is indeterminate. Some local variables of type
+ 'struct handler' and 'struct catchtag' are used in this way, so
+ mark each of their slots as volatile if the slot can be set before
+ _longjmp and read afterwards.
+ * lisp.h (struct handler): var and chosen_clause are now volatile.
+ (struct catchtag): val, next, and pdlcount are now volatile.
+
* bidi.c (bidi_push_it, bidi_pop_it):
* fns.c (copy_hash_table):
* image.c (define_image_type):
#define SPECPDL_INDEX() (specpdl_ptr - specpdl)
-/* Everything needed to describe an active condition case. */
+/* Everything needed to describe an active condition case.
+
+ Members are volatile if their values need to survive _longjmp when
+ a 'struct handler' is a local variable. */
struct handler
{
/* The handler clauses and variable from the condition-case form. */
error: handle all conditions, and errors can run the debugger
or display a backtrace. */
Lisp_Object handler;
- Lisp_Object var;
+
+ Lisp_Object volatile var;
+
/* Fsignal stores here the condition-case clause that applies,
and Fcondition_case thus knows which clause to run. */
- Lisp_Object chosen_clause;
+ Lisp_Object volatile chosen_clause;
/* Used to effect the longjump out to the handler. */
struct catchtag *tag;
of the catch form.
All the other members are concerned with restoring the interpreter
- state. */
+ state.
+ Members are volatile if their values need to survive _longjmp when
+ a 'struct catchtag' is a local variable. */
struct catchtag
{
Lisp_Object tag;
- Lisp_Object val;
- struct catchtag *next;
+ Lisp_Object volatile val;
+ struct catchtag *volatile next;
struct gcpro *gcpro;
jmp_buf jmp;
struct backtrace *backlist;
struct handler *handlerlist;
EMACS_INT lisp_eval_depth;
- ptrdiff_t pdlcount;
+ ptrdiff_t volatile pdlcount;
int poll_suppress_count;
int interrupt_input_blocked;
struct byte_stack *byte_stack;