diff options
| author | Pip Cet | 2025-06-28 09:33:01 +0000 |
|---|---|---|
| committer | Pip Cet | 2025-06-28 10:46:08 +0000 |
| commit | 6b19eb53c5048cfec1f3601afb44f94ebbb9d138 (patch) | |
| tree | 201e5d624f38626ef24e26fb243b644656e585b7 /src | |
| parent | c64b2bf113eaa2044c24860d0610c3b8ebd7e742 (diff) | |
| download | emacs-6b19eb53c5048cfec1f3601afb44f94ebbb9d138.tar.gz emacs-6b19eb53c5048cfec1f3601afb44f94ebbb9d138.zip | |
Avoid extra output in Vprin1_to_string_buffer (bug#78842)
print_error_message can throw after producing some output, so use
unwind-protect to ensure prin1-to-string-buffer is cleared.
* src/print.c (erase_prin1_to_string_buffer): New.
(Ferror_message_string): Use it to catch errors thrown in
'print_error_message'.
* test/src/print-tests.el (error-message-string-circular): Expand
test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/print.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/print.c b/src/print.c index b6ee89478c7..138a21f18ab 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1023,6 +1023,14 @@ debug_format (const char *fmt, Lisp_Object arg) | |||
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | 1025 | ||
| 1026 | /* Erase the Vprin1_to_string_buffer, potentially switching to it. */ | ||
| 1027 | static void | ||
| 1028 | erase_prin1_to_string_buffer (void) | ||
| 1029 | { | ||
| 1030 | set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); | ||
| 1031 | Ferase_buffer (); | ||
| 1032 | } | ||
| 1033 | |||
| 1026 | DEFUN ("error-message-string", Ferror_message_string, Serror_message_string, | 1034 | DEFUN ("error-message-string", Ferror_message_string, Serror_message_string, |
| 1027 | 1, 1, 0, | 1035 | 1, 1, 0, |
| 1028 | doc: /* Convert an error value (ERROR-SYMBOL . DATA) to an error message. | 1036 | doc: /* Convert an error value (ERROR-SYMBOL . DATA) to an error message. |
| @@ -1030,9 +1038,6 @@ See Info anchor `(elisp)Definition of signal' for some details on how this | |||
| 1030 | error message is constructed. */) | 1038 | error message is constructed. */) |
| 1031 | (Lisp_Object obj) | 1039 | (Lisp_Object obj) |
| 1032 | { | 1040 | { |
| 1033 | struct buffer *old = current_buffer; | ||
| 1034 | Lisp_Object value; | ||
| 1035 | |||
| 1036 | /* If OBJ is (error STRING), just return STRING. | 1041 | /* If OBJ is (error STRING), just return STRING. |
| 1037 | That is not only faster, it also avoids the need to allocate | 1042 | That is not only faster, it also avoids the need to allocate |
| 1038 | space here when the error is due to memory full. */ | 1043 | space here when the error is due to memory full. */ |
| @@ -1042,15 +1047,15 @@ error message is constructed. */) | |||
| 1042 | && NILP (XCDR (XCDR (obj)))) | 1047 | && NILP (XCDR (XCDR (obj)))) |
| 1043 | return XCAR (XCDR (obj)); | 1048 | return XCAR (XCDR (obj)); |
| 1044 | 1049 | ||
| 1050 | /* print_error_message can throw after producing some output, in which | ||
| 1051 | case we need to ensure the buffer is cleared again (bug#78842). */ | ||
| 1052 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 1053 | record_unwind_current_buffer (); | ||
| 1054 | record_unwind_protect_void (erase_prin1_to_string_buffer); | ||
| 1045 | print_error_message (obj, Vprin1_to_string_buffer, 0, Qnil); | 1055 | print_error_message (obj, Vprin1_to_string_buffer, 0, Qnil); |
| 1046 | 1056 | ||
| 1047 | set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); | 1057 | set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); |
| 1048 | value = Fbuffer_string (); | 1058 | return unbind_to (count, Fbuffer_string ()); |
| 1049 | |||
| 1050 | Ferase_buffer (); | ||
| 1051 | set_buffer_internal (old); | ||
| 1052 | |||
| 1053 | return value; | ||
| 1054 | } | 1059 | } |
| 1055 | 1060 | ||
| 1056 | /* Print an error message for the error DATA onto Lisp output stream | 1061 | /* Print an error message for the error DATA onto Lisp output stream |