diff options
| author | Paul Eggert | 2017-02-01 15:18:44 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-02-01 15:23:19 -0800 |
| commit | b01ac672be1277833964d2d53f6dd26560c70343 (patch) | |
| tree | 31b886a5084f20135bec50fe831dcfeed229c619 /src/lisp.h | |
| parent | 33be50037c2b4cdb002538534e9915c6bad253b7 (diff) | |
| download | emacs-b01ac672be1277833964d2d53f6dd26560c70343.tar.gz emacs-b01ac672be1277833964d2d53f6dd26560c70343.zip | |
Revamp quitting and fix infloops
This fixes some infinite loops that cannot be quitted out of,
e.g., (defun foo () (nth most-positive-fixnum '#1=(1 . #1#)))
when byte-compiled and when run under X. See:
http://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00577.html
This also attempts to keep the performance improvements I recently
added, as much as possible under the constraint that the infloops
must be caught. In some cases this fixes infloop bugs recently
introduced when I removed immediate_quit.
* src/alloc.c (Fmake_list):
Use rarely_quit, not maybe_quit, for speed in the usual case.
* src/bytecode.c (exec_byte_code):
* src/editfns.c (Fcompare_buffer_substrings):
* src/fns.c (Fnthcdr):
* src/syntax.c (scan_words, skip_chars, skip_syntaxes)
(Fbackward_prefix_chars):
Use rarely_quit so that users can C-g out of long loops.
* src/callproc.c (call_process_cleanup, call_process):
* src/fileio.c (read_non_regular, Finsert_file_contents):
* src/indent.c (compute_motion):
* src/syntax.c (scan_words, Fforward_comment):
Remove now-unnecessary maybe_quit calls.
* src/callproc.c (call_process):
* src/doc.c (get_doc_string, Fsnarf_documentation):
* src/fileio.c (Fcopy_file, read_non_regular, Finsert_file_contents):
* src/lread.c (safe_to_load_version):
* src/sysdep.c (system_process_attributes) [GNU_LINUX]:
Use emacs_read_quit instead of emacs_read in places where
C-g handling is safe.
* src/eval.c (maybe_quit): Move comment here from lisp.h.
* src/fileio.c (Fcopy_file, e_write):
Use emacs_write_quit instead of emacs_write_sig in places where
C-g handling is safe.
* src/filelock.c (create_lock_file): Use emacs_write, not
plain write, as emacs_write no longer has a problem.
(read_lock_data): Use emacs_read, not read, as emacs_read
no longer has a problem.
* src/fns.c (rarely_quit): Move to lisp.h and rename to
incr_rarely_quit. All uses changed..
* src/fns.c (Fmemq, Fmemql, Fassq, Frassq, Fplist_put, Fplist_member):
* src/indent.c (compute_motion):
* src/syntax.c (find_defun_start, back_comment, forw_comment)
(Fforward_comment, scan_lists, scan_sexps_forward):
Use incr_rarely_quit so that users can C-g out of long loops.
* src/fns.c (Fnconc): Move incr_rarely_quit call to within
inner loop, so that it catches C-g there too.
* src/keyboard.c (tty_read_avail_input): Remove commented-out
and now-obsolete code dealing with interrupts.
* src/lisp.h (rarely_quit, incr_rarely_quit): New functions,
the latter moved here from fns.c and renamed from rarely_quit.
(emacs_read_quit, emacs_write_quit): New decls.
* src/search.c (find_newline, search_buffer, find_newline1):
Add maybe_quit to catch C-g.
* src/sysdep.c (get_child_status): Always invoke maybe_quit
if interruptible, so that the caller need not bother.
(emacs_nointr_read, emacs_read_quit, emacs_write_quit):
New functions.
(emacs_read): Rewrite in terms of emacs_nointr_read.
Do not handle C-g or signals; that is now for emacs_read_quit.
(emacs_full_write): Replace PROCESS_SIGNALS two-way arg
with INTERRUPTIBLE three-way arg. All uses changed.
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/lisp.h b/src/lisp.h index a18e4da1cfd..2d67e7edddb 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3123,24 +3123,36 @@ struct handler | |||
| 3123 | 3123 | ||
| 3124 | extern Lisp_Object memory_signal_data; | 3124 | extern Lisp_Object memory_signal_data; |
| 3125 | 3125 | ||
| 3126 | /* Check quit-flag and quit if it is non-nil. Typing C-g does not | ||
| 3127 | directly cause a quit; it only sets Vquit_flag. So the program | ||
| 3128 | needs to call maybe_quit at times when it is safe to quit. Every | ||
| 3129 | loop that might run for a long time or might not exit ought to call | ||
| 3130 | maybe_quit at least once, at a safe place. Unless that is | ||
| 3131 | impossible, of course. But it is very desirable to avoid creating | ||
| 3132 | loops where maybe_quit is impossible. | ||
| 3133 | |||
| 3134 | If quit-flag is set to `kill-emacs' the SIGINT handler has received | ||
| 3135 | a request to exit Emacs when it is safe to do. | ||
| 3136 | |||
| 3137 | When not quitting, process any pending signals. */ | ||
| 3138 | |||
| 3139 | extern void maybe_quit (void); | 3126 | extern void maybe_quit (void); |
| 3140 | 3127 | ||
| 3141 | /* True if ought to quit now. */ | 3128 | /* True if ought to quit now. */ |
| 3142 | 3129 | ||
| 3143 | #define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) | 3130 | #define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) |
| 3131 | |||
| 3132 | /* Heuristic on how many iterations of a tight loop can be safely done | ||
| 3133 | before it's time to do a quit. This must be a power of 2. It | ||
| 3134 | is nice but not necessary for it to equal USHRT_MAX + 1. */ | ||
| 3135 | |||
| 3136 | enum { QUIT_COUNT_HEURISTIC = 1 << 16 }; | ||
| 3137 | |||
| 3138 | /* Process a quit rarely, based on a counter COUNT, for efficiency. | ||
| 3139 | "Rarely" means once per QUIT_COUNT_HEURISTIC or per USHRT_MAX + 1 | ||
| 3140 | times, whichever is smaller (somewhat arbitrary, but often faster). */ | ||
| 3141 | |||
| 3142 | INLINE void | ||
| 3143 | rarely_quit (unsigned short int count) | ||
| 3144 | { | ||
| 3145 | if (! (count & (QUIT_COUNT_HEURISTIC - 1))) | ||
| 3146 | maybe_quit (); | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | /* Increment *QUIT_COUNT and rarely quit. */ | ||
| 3150 | |||
| 3151 | INLINE void | ||
| 3152 | incr_rarely_quit (unsigned short int *quit_count) | ||
| 3153 | { | ||
| 3154 | rarely_quit (++*quit_count); | ||
| 3155 | } | ||
| 3144 | 3156 | ||
| 3145 | extern Lisp_Object Vascii_downcase_table; | 3157 | extern Lisp_Object Vascii_downcase_table; |
| 3146 | extern Lisp_Object Vascii_canon_table; | 3158 | extern Lisp_Object Vascii_canon_table; |
| @@ -4216,8 +4228,10 @@ extern int emacs_open (const char *, int, int); | |||
| 4216 | extern int emacs_pipe (int[2]); | 4228 | extern int emacs_pipe (int[2]); |
| 4217 | extern int emacs_close (int); | 4229 | extern int emacs_close (int); |
| 4218 | extern ptrdiff_t emacs_read (int, void *, ptrdiff_t); | 4230 | extern ptrdiff_t emacs_read (int, void *, ptrdiff_t); |
| 4231 | extern ptrdiff_t emacs_read_quit (int, void *, ptrdiff_t); | ||
| 4219 | extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t); | 4232 | extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t); |
| 4220 | extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t); | 4233 | extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t); |
| 4234 | extern ptrdiff_t emacs_write_quit (int, void const *, ptrdiff_t); | ||
| 4221 | extern void emacs_perror (char const *); | 4235 | extern void emacs_perror (char const *); |
| 4222 | 4236 | ||
| 4223 | extern void unlock_all_files (void); | 4237 | extern void unlock_all_files (void); |