Fix quitting bug when buffers are frozen

Problem noted by Eli Zaretskii in:
http://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00721.html
This patch also fixes some other issues in that report.
* src/lisp.h (incr_rarely_quit): Remove.
All callers changed to use rarely_quit directly.
* src/search.c (freeze_buffer_relocation)
(thaw_buffer_relocation): New functions.
(looking_at_1, fast_looking_at, search_buffer):
Use them to fix bug when quitting when buffers are frozen.
* src/sysdep.c (emacs_intr_read): Rename from emacs_nointr_read.
All uses changed.
This commit is contained in:
Paul Eggert 2017-02-01 15:18:44 -08:00
parent b01ac672be
commit b4c9f9120d
7 changed files with 70 additions and 80 deletions

View file

@ -198,7 +198,10 @@ call_process_cleanup (Lisp_Object buffer)
{
kill (-synch_process_pid, SIGINT);
message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
/* This will quit on C-g. */
wait_for_termination (synch_process_pid, 0, 1);
synch_process_pid = 0;
message1 ("Waiting for process to die...done");
}

View file

@ -1389,7 +1389,7 @@ The value is actually the tail of LIST whose car is ELT. */)
{
if (! NILP (Fequal (elt, XCAR (tail))))
return tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1406,7 +1406,7 @@ The value is actually the tail of LIST whose car is ELT. */)
{
if (EQ (XCAR (tail), elt))
return tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1427,7 +1427,7 @@ The value is actually the tail of LIST whose car is ELT. */)
Lisp_Object tem = XCAR (tail);
if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
return tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1445,7 +1445,7 @@ Elements of LIST that are not conses are ignored. */)
{
if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
return XCAR (tail);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1476,7 +1476,7 @@ The value is actually the first element of LIST whose car equals KEY. */)
if (CONSP (car)
&& (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
return car;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1509,7 +1509,7 @@ The value is actually the first element of LIST whose cdr is KEY. */)
{
if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
return XCAR (tail);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1528,7 +1528,7 @@ The value is actually the first element of LIST whose cdr equals KEY. */)
if (CONSP (car)
&& (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key))))
return car;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
@ -1684,7 +1684,7 @@ changing the value of a sequence `foo'. */)
}
else
prev = tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, seq);
}
@ -1712,7 +1712,7 @@ This function may destructively modify SEQ to produce the value. */)
next = XCDR (tail);
Fsetcdr (tail, prev);
prev = tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, seq);
seq = prev;
@ -1759,7 +1759,7 @@ See also the function `nreverse', which is used more often. */)
for (new = Qnil; CONSP (seq); seq = XCDR (seq))
{
new = Fcons (XCAR (seq), new);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (seq, seq);
}
@ -2062,7 +2062,7 @@ The PLIST is modified by side effects. */)
}
prev = tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
Lisp_Object newcell
= Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
@ -2100,7 +2100,7 @@ one of the properties on the list. */)
{
if (! NILP (Fequal (prop, XCAR (tail))))
return XCAR (XCDR (tail));
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
CHECK_LIST_END (tail, prop);
@ -2130,7 +2130,7 @@ The PLIST is modified by side effects. */)
}
prev = tail;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
Lisp_Object newcell = list2 (prop, val);
if (NILP (prev))
@ -2210,7 +2210,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
unsigned short int quit_count = 0;
tail_recurse:
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
if (EQ (o1, o2))
return 1;
if (XTYPE (o1) != XTYPE (o2))
@ -2419,7 +2419,7 @@ usage: (nconc &rest LISTS) */)
{
tail = tem;
tem = XCDR (tail);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
while (CONSP (tem));
@ -2848,7 +2848,7 @@ The value is actually the tail of PLIST whose car is PROP. */)
{
plist = XCDR (plist);
plist = CDR (plist);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
return plist;
}

View file

@ -1215,7 +1215,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
while (true)
{
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
while (pos == next_boundary)
{
@ -1282,7 +1282,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
pos_byte = CHAR_TO_BYTE (pos);
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
/* Handle right margin. */
@ -1605,7 +1605,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
pos = find_before_next_newline (pos, to, 1, &pos_byte);
if (pos < to)
INC_BOTH (pos, pos_byte);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
while (pos < to
&& indented_beyond_p (pos, pos_byte,

View file

@ -3145,14 +3145,6 @@ rarely_quit (unsigned short int count)
if (! (count & (QUIT_COUNT_HEURISTIC - 1)))
maybe_quit ();
}
/* Increment *QUIT_COUNT and rarely quit. */
INLINE void
incr_rarely_quit (unsigned short int *quit_count)
{
rarely_quit (++*quit_count);
}
extern Lisp_Object Vascii_downcase_table;
extern Lisp_Object Vascii_canon_table;

View file

@ -99,6 +99,25 @@ matcher_overflow (void)
error ("Stack overflow in regexp matcher");
}
static void
freeze_buffer_relocation (void)
{
#ifdef REL_ALLOC
/* Prevent ralloc.c from relocating the current buffer while
searching it. */
r_alloc_inhibit_buffer_relocation (1);
record_unwind_protect_int (r_alloc_inhibit_buffer_relocation, 0);
#endif
}
static void
thaw_buffer_relocation (void)
{
#ifdef REL_ALLOC
unbind_to (SPECPDL_INDEX () - 1, Qnil);
#endif
}
/* Compile a regexp and signal a Lisp error if anything goes wrong.
PATTERN is the pattern to compile.
CP is the place to put the result.
@ -300,19 +319,13 @@ looking_at_1 (Lisp_Object string, bool posix)
re_match_object = Qnil;
#ifdef REL_ALLOC
/* Prevent ralloc.c from relocating the current buffer while
searching it. */
r_alloc_inhibit_buffer_relocation (1);
#endif
freeze_buffer_relocation ();
i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
PT_BYTE - BEGV_BYTE,
(NILP (Vinhibit_changing_match_data)
? &search_regs : NULL),
ZV_BYTE - BEGV_BYTE);
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
#endif
thaw_buffer_relocation ();
if (i == -2)
matcher_overflow ();
@ -553,16 +566,10 @@ fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
}
buf = compile_pattern (regexp, 0, Qnil, 0, multibyte);
#ifdef REL_ALLOC
/* Prevent ralloc.c from relocating the current buffer while
searching it. */
r_alloc_inhibit_buffer_relocation (1);
#endif
freeze_buffer_relocation ();
len = re_match_2 (buf, (char *) p1, s1, (char *) p2, s2,
pos_byte, NULL, limit_byte);
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
#endif
thaw_buffer_relocation ();
return len;
}
@ -1204,11 +1211,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
}
re_match_object = Qnil;
#ifdef REL_ALLOC
/* Prevent ralloc.c from relocating the current buffer while
searching it. */
r_alloc_inhibit_buffer_relocation (1);
#endif
freeze_buffer_relocation ();
while (n < 0)
{
@ -1250,9 +1253,7 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
}
else
{
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
#endif
thaw_buffer_relocation ();
return (n);
}
n++;
@ -1295,17 +1296,13 @@ search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
}
else
{
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
#endif
thaw_buffer_relocation ();
return (0 - n);
}
n--;
maybe_quit ();
}
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
#endif
thaw_buffer_relocation ();
return (pos);
}
else /* non-RE case */

View file

@ -593,7 +593,6 @@ static ptrdiff_t
find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
{
ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
unsigned short int quit_count = 0;
/* Use previous finding, if it's valid and applies to this inquiry. */
if (current_buffer == find_start_buffer
@ -636,7 +635,6 @@ find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
}
/* Move to beg of previous line. */
scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -2, 1);
incr_rarely_quit (&quit_count);
}
/* Record what we found, for the next try. */
@ -725,7 +723,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
that determines quote parity to the comment-end. */
while (from != stop)
{
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
ptrdiff_t temp_byte;
int prev_syntax;
@ -954,7 +952,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
defun_start_byte = CHAR_TO_BYTE (defun_start);
}
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
while (defun_start < comment_end);
@ -2386,7 +2384,7 @@ forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
nesting++;
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
*charpos_ptr = from;
*bytepos_ptr = from_byte;
@ -2460,7 +2458,7 @@ between them, return t; otherwise return nil. */)
INC_BOTH (from, from_byte);
UPDATE_SYNTAX_TABLE_FORWARD (from);
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
while (code == Swhitespace || (code == Sendcomment && c == '\n'));
@ -2544,7 +2542,7 @@ between them, return t; otherwise return nil. */)
}
else if (from == stop)
break;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
if (fence_found == 0)
{
@ -2592,7 +2590,7 @@ between them, return t; otherwise return nil. */)
return Qnil;
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
count1++;
@ -2648,7 +2646,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
{
while (from < stop)
{
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
bool comstart_first, prefix;
int syntax, other_syntax;
UPDATE_SYNTAX_TABLE_FORWARD (from);
@ -2717,7 +2715,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
goto done;
}
INC_BOTH (from, from_byte);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
goto done;
@ -2789,7 +2787,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
if (c_code == Scharquote || c_code == Sescape)
INC_BOTH (from, from_byte);
INC_BOTH (from, from_byte);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
INC_BOTH (from, from_byte);
if (!depth && sexpflag) goto done;
@ -2815,7 +2813,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
{
while (from > stop)
{
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
DEC_BOTH (from, from_byte);
UPDATE_SYNTAX_TABLE_BACKWARD (from);
c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
@ -2891,7 +2889,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
default: goto done2;
}
DEC_BOTH (from, from_byte);
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
goto done2;
@ -2954,7 +2952,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
if (syntax_multibyte (c, multibyte_symbol_p) == code)
break;
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
if (code == Sstring_fence && !depth && sexpflag) goto done2;
break;
@ -2975,7 +2973,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
== Sstring))
break;
}
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
if (!depth && sexpflag) goto done2;
break;
@ -3229,7 +3227,7 @@ do { prev_from = from; \
while (from < end)
{
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
INC_FROM;
if ((from < end)
@ -3286,7 +3284,7 @@ do { prev_from = from; \
goto symdone;
}
INC_FROM;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
symdone:
curlevel->prev = curlevel->last;
@ -3397,7 +3395,7 @@ do { prev_from = from; \
break;
}
INC_FROM;
incr_rarely_quit (&quit_count);
rarely_quit (++quit_count);
}
}
string_end:

View file

@ -2508,12 +2508,12 @@ emacs_close (int fd)
#endif
/* Read from FD to a buffer BUF with size NBYTE.
If interrupted, either quit or retry the read.
Process any quits and pending signals immediately if INTERRUPTIBLE.
If interrupted, process any quits and pending signals immediately
if INTERRUPTIBLE, and then retry the read unless quitting.
Return the number of bytes read, which might be less than NBYTE.
On error, set errno to a value other than EINTR, and return -1. */
static ptrdiff_t
emacs_nointr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
emacs_intr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
{
ssize_t result;
@ -2537,14 +2537,14 @@ emacs_nointr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
ptrdiff_t
emacs_read (int fd, void *buf, ptrdiff_t nbyte)
{
return emacs_nointr_read (fd, buf, nbyte, false);
return emacs_intr_read (fd, buf, nbyte, false);
}
/* Like emacs_read, but also process quits and pending signals. */
ptrdiff_t
emacs_read_quit (int fd, void *buf, ptrdiff_t nbyte)
{
return emacs_nointr_read (fd, buf, nbyte, true);
return emacs_intr_read (fd, buf, nbyte, true);
}
/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if