Subject: Re: bug#23813: 24.5; undo warning while find-file

From: Eli Zaretskii <[email-masked]>
Date: Sat, 09 Jul 2016 15:27:47 +0300

> From: [email-masked]
> Date: Tue, 21 Jun 2016 20:48:30 +0900
> 
> When `post-read-conversion' changes the buffer many times,
> undo warning buffer popups.
> This may occur while `find-file', even though undo info is not needed.
> 
> (let ((tmpfile "/tmp/test-hz.txt"))
>   (with-temp-buffer
>     (dotimes (i 100000) (insert "一\n"))
>     (write-region (point-min) (point-max) tmpfile)
>     (let ((coding-system-for-read 'hz))
>       (find-file tmpfile))))
> 
> Evaluating the form above, *Warnings* buffer shows this text.
>   Warning (undo): Buffer `test-hz.txt' undo info was 12765470 bytes long.
>   The undo info was discarded because it exceeded `undo-outer-limit'.
>   
>   This is normal if you executed a command that made a huge change
>   to the buffer.  In that case, to prevent similar problems in the
>   future, set `undo-outer-limit' to a value that is large enough to
>   cover the maximum size of normal changes you expect a single
>   command to make, but not so large that it might exceed the
>   maximum memory allotted to Emacs.
>   
>   If you did not execute any such command, the situation is
>   probably due to a bug and you should report it.
>   
>   You can disable the popping up of this buffer by adding the entry
>   (undo discard-info) to the user option `warning-suppress-types',
>   which is defined in the `warnings' library.

Phillip, what do you think about the patch below?

diff --git a/src/coding.c b/src/coding.c
index 29c90f0..b959f7d 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -7851,6 +7851,15 @@ code_conversion_save (bool with_work_buf, bool multibyte)
   return workbuf;
 }
 
+static void
+coding_restore_undo_list (Lisp_Object arg)
+{
+  Lisp_Object undo_list = XCAR (arg);
+  struct buffer *buf = XBUFFER (XCDR (arg));
+
+  bset_undo_list (buf, undo_list);
+}
+
 void
 decode_coding_gap (struct coding_system *coding,
 		   ptrdiff_t chars, ptrdiff_t bytes)
@@ -7963,13 +7972,19 @@ decode_coding_gap (struct coding_system *coding,
     {
       ptrdiff_t prev_Z = Z, prev_Z_BYTE = Z_BYTE;
       Lisp_Object val;
+      Lisp_Object undo_list = BVAR (current_buffer, undo_list);
+      ptrdiff_t count1 = SPECPDL_INDEX ();
 
+      record_unwind_protect (coding_restore_undo_list,
+			     Fcons (undo_list, Fcurrent_buffer ()));
+      bset_undo_list (current_buffer, Qt);
       TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte);
       val = call1 (CODING_ATTR_POST_READ (attrs),
 		   make_number (coding->produced_char));
       CHECK_NATNUM (val);
       coding->produced_char += Z - prev_Z;
       coding->produced += Z_BYTE - prev_Z_BYTE;
+      unbind_to (count1, Qnil);
     }
 
   unbind_to (count, Qnil);
@@ -8110,13 +8125,19 @@ decode_coding_object (struct coding_system *coding,
     {
       ptrdiff_t prev_Z = Z, prev_Z_BYTE = Z_BYTE;
       Lisp_Object val;
+      Lisp_Object undo_list = BVAR (current_buffer, undo_list);
+      ptrdiff_t count1 = SPECPDL_INDEX ();
 
+      record_unwind_protect (coding_restore_undo_list,
+			     Fcons (undo_list, Fcurrent_buffer ()));
+      bset_undo_list (current_buffer, Qt);
       TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte);
       val = safe_call1 (CODING_ATTR_POST_READ (attrs),
 			make_number (coding->produced_char));
       CHECK_NATNUM (val);
       coding->produced_char += Z - prev_Z;
       coding->produced += Z_BYTE - prev_Z_BYTE;
+      unbind_to (count1, Qnil);
     }
 
   if (EQ (dst_object, Qt))