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/fileio.c | |
| 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/fileio.c')
| -rw-r--r-- | src/fileio.c | 55 |
1 files changed, 23 insertions, 32 deletions
diff --git a/src/fileio.c b/src/fileio.c index a109737240f..38400623793 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -2030,9 +2030,9 @@ permissions. */) | |||
| 2030 | { | 2030 | { |
| 2031 | char buf[MAX_ALLOCA]; | 2031 | char buf[MAX_ALLOCA]; |
| 2032 | ptrdiff_t n; | 2032 | ptrdiff_t n; |
| 2033 | for (newsize = 0; 0 < (n = emacs_read (ifd, buf, sizeof buf)); | 2033 | for (newsize = 0; 0 < (n = emacs_read_quit (ifd, buf, sizeof buf)); |
| 2034 | newsize += n) | 2034 | newsize += n) |
| 2035 | if (emacs_write_sig (ofd, buf, n) != n) | 2035 | if (emacs_write_quit (ofd, buf, n) != n) |
| 2036 | report_file_error ("Write error", newname); | 2036 | report_file_error ("Write error", newname); |
| 2037 | if (n < 0) | 2037 | if (n < 0) |
| 2038 | report_file_error ("Read error", file); | 2038 | report_file_error ("Read error", file); |
| @@ -3396,13 +3396,10 @@ decide_coding_unwind (Lisp_Object unwind_data) | |||
| 3396 | static Lisp_Object | 3396 | static Lisp_Object |
| 3397 | read_non_regular (Lisp_Object state) | 3397 | read_non_regular (Lisp_Object state) |
| 3398 | { | 3398 | { |
| 3399 | int nbytes; | 3399 | int nbytes = emacs_read_quit (XSAVE_INTEGER (state, 0), |
| 3400 | 3400 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE | |
| 3401 | maybe_quit (); | 3401 | + XSAVE_INTEGER (state, 1)), |
| 3402 | nbytes = emacs_read (XSAVE_INTEGER (state, 0), | 3402 | XSAVE_INTEGER (state, 2)); |
| 3403 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE | ||
| 3404 | + XSAVE_INTEGER (state, 1)), | ||
| 3405 | XSAVE_INTEGER (state, 2)); | ||
| 3406 | /* Fast recycle this object for the likely next call. */ | 3403 | /* Fast recycle this object for the likely next call. */ |
| 3407 | free_misc (state); | 3404 | free_misc (state); |
| 3408 | return make_number (nbytes); | 3405 | return make_number (nbytes); |
| @@ -3746,17 +3743,17 @@ by calling `format-decode', which see. */) | |||
| 3746 | int nread; | 3743 | int nread; |
| 3747 | 3744 | ||
| 3748 | if (st.st_size <= (1024 * 4)) | 3745 | if (st.st_size <= (1024 * 4)) |
| 3749 | nread = emacs_read (fd, read_buf, 1024 * 4); | 3746 | nread = emacs_read_quit (fd, read_buf, 1024 * 4); |
| 3750 | else | 3747 | else |
| 3751 | { | 3748 | { |
| 3752 | nread = emacs_read (fd, read_buf, 1024); | 3749 | nread = emacs_read_quit (fd, read_buf, 1024); |
| 3753 | if (nread == 1024) | 3750 | if (nread == 1024) |
| 3754 | { | 3751 | { |
| 3755 | int ntail; | 3752 | int ntail; |
| 3756 | if (lseek (fd, - (1024 * 3), SEEK_END) < 0) | 3753 | if (lseek (fd, - (1024 * 3), SEEK_END) < 0) |
| 3757 | report_file_error ("Setting file position", | 3754 | report_file_error ("Setting file position", |
| 3758 | orig_filename); | 3755 | orig_filename); |
| 3759 | ntail = emacs_read (fd, read_buf + nread, 1024 * 3); | 3756 | ntail = emacs_read_quit (fd, read_buf + nread, 1024 * 3); |
| 3760 | nread = ntail < 0 ? ntail : nread + ntail; | 3757 | nread = ntail < 0 ? ntail : nread + ntail; |
| 3761 | } | 3758 | } |
| 3762 | } | 3759 | } |
| @@ -3861,14 +3858,11 @@ by calling `format-decode', which see. */) | |||
| 3861 | report_file_error ("Setting file position", orig_filename); | 3858 | report_file_error ("Setting file position", orig_filename); |
| 3862 | } | 3859 | } |
| 3863 | 3860 | ||
| 3864 | maybe_quit (); | ||
| 3865 | /* Count how many chars at the start of the file | 3861 | /* Count how many chars at the start of the file |
| 3866 | match the text at the beginning of the buffer. */ | 3862 | match the text at the beginning of the buffer. */ |
| 3867 | while (1) | 3863 | while (true) |
| 3868 | { | 3864 | { |
| 3869 | int nread, bufpos; | 3865 | int nread = emacs_read_quit (fd, read_buf, sizeof read_buf); |
| 3870 | |||
| 3871 | nread = emacs_read (fd, read_buf, sizeof read_buf); | ||
| 3872 | if (nread < 0) | 3866 | if (nread < 0) |
| 3873 | report_file_error ("Read error", orig_filename); | 3867 | report_file_error ("Read error", orig_filename); |
| 3874 | else if (nread == 0) | 3868 | else if (nread == 0) |
| @@ -3890,7 +3884,7 @@ by calling `format-decode', which see. */) | |||
| 3890 | break; | 3884 | break; |
| 3891 | } | 3885 | } |
| 3892 | 3886 | ||
| 3893 | bufpos = 0; | 3887 | int bufpos = 0; |
| 3894 | while (bufpos < nread && same_at_start < ZV_BYTE | 3888 | while (bufpos < nread && same_at_start < ZV_BYTE |
| 3895 | && FETCH_BYTE (same_at_start) == read_buf[bufpos]) | 3889 | && FETCH_BYTE (same_at_start) == read_buf[bufpos]) |
| 3896 | same_at_start++, bufpos++; | 3890 | same_at_start++, bufpos++; |
| @@ -3910,7 +3904,7 @@ by calling `format-decode', which see. */) | |||
| 3910 | del_range_1 (same_at_start, same_at_end, 0, 0); | 3904 | del_range_1 (same_at_start, same_at_end, 0, 0); |
| 3911 | goto handled; | 3905 | goto handled; |
| 3912 | } | 3906 | } |
| 3913 | maybe_quit (); | 3907 | |
| 3914 | /* Count how many chars at the end of the file | 3908 | /* Count how many chars at the end of the file |
| 3915 | match the text at the end of the buffer. But, if we have | 3909 | match the text at the end of the buffer. But, if we have |
| 3916 | already found that decoding is necessary, don't waste time. */ | 3910 | already found that decoding is necessary, don't waste time. */ |
| @@ -3932,7 +3926,8 @@ by calling `format-decode', which see. */) | |||
| 3932 | total_read = nread = 0; | 3926 | total_read = nread = 0; |
| 3933 | while (total_read < trial) | 3927 | while (total_read < trial) |
| 3934 | { | 3928 | { |
| 3935 | nread = emacs_read (fd, read_buf + total_read, trial - total_read); | 3929 | nread = emacs_read_quit (fd, read_buf + total_read, |
| 3930 | trial - total_read); | ||
| 3936 | if (nread < 0) | 3931 | if (nread < 0) |
| 3937 | report_file_error ("Read error", orig_filename); | 3932 | report_file_error ("Read error", orig_filename); |
| 3938 | else if (nread == 0) | 3933 | else if (nread == 0) |
| @@ -4058,16 +4053,13 @@ by calling `format-decode', which see. */) | |||
| 4058 | inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */ | 4053 | inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */ |
| 4059 | unprocessed = 0; /* Bytes not processed in previous loop. */ | 4054 | unprocessed = 0; /* Bytes not processed in previous loop. */ |
| 4060 | 4055 | ||
| 4061 | while (1) | 4056 | while (true) |
| 4062 | { | 4057 | { |
| 4063 | /* Read at most READ_BUF_SIZE bytes at a time, to allow | 4058 | /* Read at most READ_BUF_SIZE bytes at a time, to allow |
| 4064 | quitting while reading a huge file. */ | 4059 | quitting while reading a huge file. */ |
| 4065 | 4060 | ||
| 4066 | /* Allow quitting out of the actual I/O. */ | 4061 | this = emacs_read_quit (fd, read_buf + unprocessed, |
| 4067 | maybe_quit (); | 4062 | READ_BUF_SIZE - unprocessed); |
| 4068 | this = emacs_read (fd, read_buf + unprocessed, | ||
| 4069 | READ_BUF_SIZE - unprocessed); | ||
| 4070 | |||
| 4071 | if (this <= 0) | 4063 | if (this <= 0) |
| 4072 | break; | 4064 | break; |
| 4073 | 4065 | ||
| @@ -4281,11 +4273,10 @@ by calling `format-decode', which see. */) | |||
| 4281 | /* Allow quitting out of the actual I/O. We don't make text | 4273 | /* Allow quitting out of the actual I/O. We don't make text |
| 4282 | part of the buffer until all the reading is done, so a C-g | 4274 | part of the buffer until all the reading is done, so a C-g |
| 4283 | here doesn't do any harm. */ | 4275 | here doesn't do any harm. */ |
| 4284 | maybe_quit (); | 4276 | this = emacs_read_quit (fd, |
| 4285 | this = emacs_read (fd, | 4277 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE |
| 4286 | ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE | 4278 | + inserted), |
| 4287 | + inserted), | 4279 | trytry); |
| 4288 | trytry); | ||
| 4289 | } | 4280 | } |
| 4290 | 4281 | ||
| 4291 | if (this <= 0) | 4282 | if (this <= 0) |
| @@ -5398,7 +5389,7 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end, | |||
| 5398 | : (STRINGP (coding->dst_object) | 5389 | : (STRINGP (coding->dst_object) |
| 5399 | ? SSDATA (coding->dst_object) | 5390 | ? SSDATA (coding->dst_object) |
| 5400 | : (char *) BYTE_POS_ADDR (coding->dst_pos_byte))); | 5391 | : (char *) BYTE_POS_ADDR (coding->dst_pos_byte))); |
| 5401 | coding->produced -= emacs_write_sig (desc, buf, coding->produced); | 5392 | coding->produced -= emacs_write_quit (desc, buf, coding->produced); |
| 5402 | 5393 | ||
| 5403 | if (coding->raw_destination) | 5394 | if (coding->raw_destination) |
| 5404 | { | 5395 | { |