Package: emacs;
Reported by: Juri Linkov <juri <at> linkov.net>
Date: Mon, 25 Aug 2025 06:34:01 UTC
Severity: normal
Done: Stefan Monnier <monnier <at> iro.umontreal.ca>
Message #8 received at 79306 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Juri Linkov <juri <at> linkov.net>, Stefan Monnier <monnier <at> iro.umontreal.ca> Cc: 79306 <at> debbugs.gnu.org Subject: Re: bug#79306: Broken follow-mode Date: Mon, 25 Aug 2025 15:54:17 +0300
> From: Juri Linkov <juri <at> linkov.net> > Date: Mon, 25 Aug 2025 09:30:10 +0300 > > Some recent change in master broke display for follow-mode: > > 0. emacs -Q > 1. visit a file in fundamental-mode, e.g. > C-x C-f etc/COPYING RET > 2. split horizontally > C-x 3 > 3. M-x follow-mode RET > 4. scroll down a few screens > 5. type 'M-<' (beginning-of-buffer) > > It displays the message "Back to top level", > but doesn't move to the beginning of the buffer. Looks like the trap set by Stefan a month ago finally caught its first victim: follow-mode calls redisplay recursively, from pre-redisplay-function: Thread 1 hit Breakpoint 4, redisplay_internal () at xdisp.c:17122 17122 struct window *w = XWINDOW (selected_window); (gdb) bt #0 redisplay_internal () at xdisp.c:17122 #1 0x0104197e in redisplay_preserve_echo_area (from_where=2) at xdisp.c:18040 #2 0x00fe51f4 in Fredisplay (force=XIL(0)) at dispnew.c:7004 #3 0x0123da19 in funcall_subr (subr=0x13ee240 <Sredisplay>, numargs=0, args=0xa019120) at eval.c:3242 #4 0x012aa6a8 in exec_byte_code (fun=XIL(0xa0000000103368c0), args_template=514, nargs=2, args=0xa019128) at bytecode.c:805 #5 0x0123e30c in funcall_lambda (fun=XIL(0xa000000010336cd0), nargs=1, arg_vector=0xa019050) at eval.c:3333 #6 0x0123d3d2 in funcall_general (fun=XIL(0xa000000010336cd0), numargs=1, args=0xa019050) at eval.c:3125 #7 0x0123d6fb in Ffuncall (nargs=2, args=0xa019048) at eval.c:3174 #8 0x0123c472 in Fapply (nargs=2, args=0xa019048) at eval.c:2788 #9 0x0123dea4 in funcall_subr (subr=0x13fc600 <Sapply>, numargs=2, args=0xa019048) at eval.c:3265 #10 0x012aa6a8 in exec_byte_code (fun=XIL(0xa00000001033a090), args_template=128, nargs=1, args=0xbfdcd0) at bytecode.c:805 #11 0x0123e30c in funcall_lambda (fun=XIL(0xa00000001033a090), nargs=1, arg_vector=0xbfdcd0) at eval.c:3333 #12 0x0123d3d2 in funcall_general (fun=XIL(0xa00000001033a090), numargs=1, args=0xbfdcd0) at eval.c:3125 #13 0x0123d6fb in Ffuncall (nargs=2, args=0xbfdcc8) at eval.c:3174 #14 0x012386f0 in internal_condition_case_n (bfun=0x123d5af <Ffuncall>, nargs=2, args=0xbfdcc8, handlers=XIL(0x30), hfun=0x10151d3 <dsafe_eval_handler>) at eval.c:1770 #15 0x01015307 in dsafe__call (inhibit_quit=true, f=0x123d5af <Ffuncall>, nargs=2, args=0xbfdcc8) at xdisp.c:3102 #16 0x0103711d in prepare_menu_bars () at xdisp.c:14054 #17 0x0103f95e in redisplay_internal () at xdisp.c:17283 #18 0x0103e65d in redisplay () at xdisp.c:16844 #19 0x011456ef in read_char (commandflag=1, map=XIL(0xc00000001711a630), prev_event=XIL(0), used_mouse_menu=0xbff31f, end_time=0x0) at keyboard.c:2672 #20 0x0115ee45 in read_key_sequence (keybuf=0xbff5f8, prompt=XIL(0), dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false, disable_text_conversion_p=false) at keyboard.c:11146 #21 0x011412ca in command_loop_1 () at keyboard.c:1424 #22 0x01238416 in internal_condition_case (bfun=0x1140c68 <command_loop_1>, handlers=XIL(0x90), hfun=0x113fcc1 <cmd_error>) at eval.c:1690 #23 0x011406cd in command_loop_2 (handlers=XIL(0x90)) at keyboard.c:1163 #24 0x012375a2 in internal_catch (tag=XIL(0x12a80), func=0x1140696 <command_loop_2>, arg=XIL(0x90)) at eval.c:1370 #25 0x01140638 in command_loop () at keyboard.c:1141 #26 0x0113f721 in recursive_edit_1 () at keyboard.c:749 #27 0x0113f9bf in Frecursive_edit () at keyboard.c:832 #28 0x0113a9aa in main (argc=2, argv=0xf02638) at emacs.c:2629 Lisp Backtrace: "redisplay" (0xa019120) "follow-adjust-window" (0xa0190b8) "follow-post-command-hook" (0xa019080) "follow-pre-redisplay-function" (0xa019050) "apply" (0xa019048) 0x1033a090 PVEC_CLOSURE "redisplay_internal (C function)" (0x0) Then we catch this and throw to top-level: int redisplay_counter_before = redisplay_counter; /* Use Qt to ensure debugger does not run, to reduce the risk of wanting to redisplay. */ val = internal_condition_case_n (f, nargs, args, Qt, dsafe_eval_handler); if (redisplay_counter_before != redisplay_counter) /* A nested redisplay happened, abort this one! */ /* FIXME: Rather than jump all the way to `top-level` we should exit only the current redisplay. */ Ftop_level (); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Is it allowed to perform redisplay from pre-redisplay-function? If so, we need to refine the above test, or maybe disable it when we call pre-redisplay-function.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.