GNU bug report logs - #79947
31.0.50; TTY child frame problem - Cannot re-root surrogate minibuffer frame

Previous

Package: emacs;

Reported by: Daniel Mendler <mail <at> daniel-mendler.de>

Date: Thu, 4 Dec 2025 11:50:01 UTC

Severity: normal

Found in version 31.0.50

To reply to this bug, email your comments to 79947 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to gerd.moellmann <at> gmail.com, bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 11:50:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Daniel Mendler <mail <at> daniel-mendler.de>:
New bug report received and forwarded. Copy sent to gerd.moellmann <at> gmail.com, bug-gnu-emacs <at> gnu.org. (Thu, 04 Dec 2025 11:50:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; TTY child frame problem - Cannot re-root surrogate
 minibuffer frame 
Date: Thu, 04 Dec 2025 12:49:16 +0100
Hello Gerd,

I am testing Corfu in a mixed GUI/TTY setup, where Emacs is started as
GUI instance, and further TTY frames are created via emacsclient -nw.

I occasionally observe the "Cannot re-root surrogate minibuffer frame"
due to child frames, when switching between the GUI and TTY Emacs
frames. Corfu recreates the child frame when the parent frame changes.

Corfu detected an error:
  (backtrace-to-string)
  (corfu--debug (error "Cannot re-root surrogate minibuffer frame"))
  (tty-create-frame-with-faces ((client . #<process server <2>>)
  (right-divider-width . 4) (buffer-predicate .
  exwm-layout--other-buffer-predicate) (parent-frame . #<frame F2
  0x55ef98dce908>) (minibuffer . #<window 19 on  *Minibuf-0*>) (width .
  0) (height . 0) (visibility) (right-fringe . 0) (left-fringe . 0)
  (no-accept-focus . t) (no-focus-on-map . t) (min-width . t)
  (min-height . t) (border-width . 0) (outer-border-width . 0)
  (internal-border-width . 1) (child-frame-border-width . 1)
  (vertical-scroll-bars) (horizontal-scroll-bars) (menu-bar-lines . 0)
  (tool-bar-lines . 0) (tab-bar-lines . 0) (tab-bar-lines-keep-state .
  t) (no-other-frame . t) (unsplittable . t) (undecorated . t)
  (fullscreen) (cursor-type) (no-special-glyphs . t) (desktop-dont-save
  . t) (inhibit-double-buffering . t)))
  ...

I've seen that frame.c documents an invariant, which seems to be
violated:

      /* Invariant: When a frame F1 uses a surrogate minibuffer frame M1
	 on a tty, both F1 and M1 must have the same root frame.  */

Any suggestions on how to fix this problem? Do I have to treat the
minibuffer window somehow before creating the child frame? Thank you.

In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.49, cairo version 1.18.4) of 2025-11-30
Windowing system distributor 'The X.Org Foundation', version 11.0.12101016
System Description: Debian GNU/Linux 13 (trixie)

Configured using:
 'configure --prefix=$HOME/.local/share/emacs
 --without-compress-install --with-tree-sitter --with-native-compilation
 --with-dbus --without-selinux --without-threads --disable-gc-mark-trace
 --without-gsettings --without-gpm --with-cairo --with-cairo-xcb
 --with-xinput2 --with-x-toolkit=gtk3 --without-toolkit-scroll-bars
 'CFLAGS=-O3 -mtune=native -march=native''

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS HARFBUZZ JPEG LIBOTF LIBSYSTEMD
LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP
SOUND SQLITE3 TIFF TREE_SITTER WEBP X11 XDBE XIM XINERAMA XINPUT2 XPM
XRANDR GTK3 ZLIB




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 13:21:01 GMT) Full text and rfc822 format available.

Message #8 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 14:20:43 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> Hello Gerd,
>
> I am testing Corfu in a mixed GUI/TTY setup, where Emacs is started as
> GUI instance, and further TTY frames are created via emacsclient -nw.
>
> I occasionally observe the "Cannot re-root surrogate minibuffer frame"
> due to child frames, when switching between the GUI and TTY Emacs
> frames. Corfu recreates the child frame when the parent frame changes.
>
> Corfu detected an error:
>   (backtrace-to-string)
>   (corfu--debug (error "Cannot re-root surrogate minibuffer frame"))
>   (tty-create-frame-with-faces ((client . #<process server <2>>)
>   (right-divider-width . 4) (buffer-predicate .
>   exwm-layout--other-buffer-predicate) (parent-frame . #<frame F2
>   0x55ef98dce908>) (minibuffer . #<window 19 on  *Minibuf-0*>) (width .
>   0) (height . 0) (visibility) (right-fringe . 0) (left-fringe . 0)
>   (no-accept-focus . t) (no-focus-on-map . t) (min-width . t)
>   (min-height . t) (border-width . 0) (outer-border-width . 0)
>   (internal-border-width . 1) (child-frame-border-width . 1)
>   (vertical-scroll-bars) (horizontal-scroll-bars) (menu-bar-lines . 0)
>   (tool-bar-lines . 0) (tab-bar-lines . 0) (tab-bar-lines-keep-state .
>   t) (no-other-frame . t) (unsplittable . t) (undecorated . t)
>   (fullscreen) (cursor-type) (no-special-glyphs . t) (desktop-dont-save
>   . t) (inhibit-double-buffering . t)))
>   ...
>
> I've seen that frame.c documents an invariant, which seems to be
> violated:
>
>       /* Invariant: When a frame F1 uses a surrogate minibuffer frame M1
> 	 on a tty, both F1 and M1 must have the same root frame.  */
>
> Any suggestions on how to fix this problem? Do I have to treat the
> minibuffer window somehow before creating the child frame? Thank you.
>
> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
>  3.24.49, cairo version 1.18.4) of 2025-11-30
> Windowing system distributor 'The X.Org Foundation', version 11.0.12101016
> System Description: Debian GNU/Linux 13 (trixie)
>
> Configured using:
>  'configure --prefix=$HOME/.local/share/emacs
>  --without-compress-install --with-tree-sitter --with-native-compilation
>  --with-dbus --without-selinux --without-threads --disable-gc-mark-trace
>  --without-gsettings --without-gpm --with-cairo --with-cairo-xcb
>  --with-xinput2 --with-x-toolkit=gtk3 --without-toolkit-scroll-bars
>  'CFLAGS=-O3 -mtune=native -march=native''
>
> Configured features:
> CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS HARFBUZZ JPEG LIBOTF LIBSYSTEMD
> LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP
> SOUND SQLITE3 TIFF TREE_SITTER WEBP X11 XDBE XIM XINERAMA XINPUT2 XPM
> XRANDR GTK3 ZLIB

Hallo Daniel.

I hope Martin (in CC) can help here. I've always avoided multi-tty, and
emacs-mac, which I'M using nowadays, doesn't even support it. And I've
never used a minibuffer surrogate frame in my life :-).

AFAIU the problem one would have to somehow "transport" the child frame
from one root frame (tty) to another root frame (GUI) for this to be
possible.

I don't have an idea right now if this is theoretically possible and
even less how one would do that.

Maybe Martin has an idea.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 13:53:01 GMT) Full text and rfc822 format available.

Message #11 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 14:52:04 +0100
Hello Gerd,

thanks for the quick response!

Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> I hope Martin (in CC) can help here. I've always avoided multi-tty, and
> emacs-mac, which I'M using nowadays, doesn't even support it. And I've
> never used a minibuffer surrogate frame in my life :-).

Yes, it is a bit of a special setup and I mainly use it for testing. In
my setup Emacs takes over the whole screen via EXWM. Then I can enter
the same Emacs instance via the emacsclient from a terminal. I was
astonished that this works so smoothly, when I tried it the first time.

But such a setup could actually be practical when SSHing into a GUI
instance where Emacs is running.

> AFAIU the problem one would have to somehow "transport" the child frame
> from one root frame (tty) to another root frame (GUI) for this to be
> possible.

Hmm, but in Corfu I explicitly try to avoid such problems in the first
place. I recreate the child frame when the parent (or root) frame
changes. Nevertheless the invariant is still violated?

> I don't have an idea right now if this is theoretically possible and
> even less how one would do that.
>
> Maybe Martin has an idea.

Daniel




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 14:21:02 GMT) Full text and rfc822 format available.

Message #14 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 15:20:49 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> Hello Gerd,
>
> thanks for the quick response!
>
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>> I hope Martin (in CC) can help here. I've always avoided multi-tty, and
>> emacs-mac, which I'M using nowadays, doesn't even support it. And I've
>> never used a minibuffer surrogate frame in my life :-).
>
> Yes, it is a bit of a special setup and I mainly use it for testing. In
> my setup Emacs takes over the whole screen via EXWM. Then I can enter
> the same Emacs instance via the emacsclient from a terminal. I was
> astonished that this works so smoothly, when I tried it the first time.
>
> But such a setup could actually be practical when SSHing into a GUI
> instance where Emacs is running.
>
>> AFAIU the problem one would have to somehow "transport" the child frame
>> from one root frame (tty) to another root frame (GUI) for this to be
>> possible.
>
> Hmm, but in Corfu I explicitly try to avoid such problems in the first
> place. I recreate the child frame when the parent (or root) frame
> changes. Nevertheless the invariant is still violated?

Hmm, good question. The code is:

frame.c:
 3843   /* The parent frame parameter for ttys must be handled specially.  */
 3844   if (is_tty_frame (f) && EQ (prop, Qparent_frame))
 3845     {
 3846       /* Invariant: When a frame F1 uses a surrogate minibuffer frame M1
 3847          on a tty, both F1 and M1 must have the same root frame.  */
 3848       Lisp_Object frames, frame1, old_val = f->parent_frame;
 3849 
 3850       FOR_EACH_FRAME (frames, frame1)
 3851         {
 3852           struct frame *f1 = XFRAME (frame1);
 3853           struct frame *m1 = WINDOW_XFRAME (XWINDOW (f1->minibuffer_window));
 3854           bool mismatch = false;
 3855 
 3856           /* Temporarily install VAL and check whether our invariant
 3857              above gets violated.  */
 3858           f->parent_frame = val;
 3859           mismatch = root_frame (f1) != root_frame (m1);
 3860           f->parent_frame = old_val;
 3861 
 3862           if (mismatch)
 3863             error ("Cannot re-root surrogate minibuffer frame");
 3864         }

I assumed that the code above checks the case where F above is the Corfu
frame, whose parent-frame is to be set. For each frame known, F1, the
code checks what would happen if the Corfu frame's parent would be set
to the new parent. And it finds that there is this root frame mismatch.

So, maybe VAL is not right in this case, which is the new parent of the
Corfu frame? That would come from Corfu code, IIUC.

Pretty much guessing here, without having a clue :-).





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 14:42:02 GMT) Full text and rfc822 format available.

Message #17 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
 Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 4 Dec 2025 15:41:09 +0100
>> I occasionally observe the "Cannot re-root surrogate minibuffer frame"
>> due to child frames, when switching between the GUI and TTY Emacs
>> frames. Corfu recreates the child frame when the parent frame changes.

Via 'corfu--make-frame'?  That is via

      (when frame (delete-frame frame))
      (setq frame (make-frame
                   `((parent-frame . ,parent)
                     (minibuffer . ,(minibuffer-window parent))

I presume.  So you enter the

      FOR_EACH_FRAME (frames, frame1)
	{
	  struct frame *f1 = XFRAME (frame1);
	  struct frame *m1 = WINDOW_XFRAME (XWINDOW (f1->minibuffer_window));
	  bool mismatch = false;

	  /* Temporarily install VAL and check whether our invariant
	     above gets violated.  */
	  f->parent_frame = val;
	  mismatch = root_frame (f1) != root_frame (m1);
	  f->parent_frame = old_val;

	  if (mismatch)
	    error ("Cannot re-root surrogate minibuffer frame");
	}

loop and it throws its error.

>> Any suggestions on how to fix this problem? Do I have to treat the
>> minibuffer window somehow before creating the child frame? Thank you.

You would have to run the loop above with the debugger to find out what
causes the mismatch of the root frames.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 14:57:01 GMT) Full text and rfc822 format available.

Message #20 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root surrogate minibuffer frame
Date: Thu, 04 Dec 2025 15:56:04 +0100

Am 4. Dezember 2025 15:20:49 MEZ schrieb "Gerd Möllmann" <gerd.moellmann <at> gmail.com>:
 
>I assumed that the code above checks the case where F above is the Corfu
>frame, whose parent-frame is to be set. For each frame known, F1, the
>code checks what would happen if the Corfu frame's parent would be set
>to the new parent. And it finds that there is this root frame mismatch.
>
>So, maybe VAL is not right in this case, which is the new parent of the
>Corfu frame? That would come from Corfu code, IIUC.

Corfu uses the frame of the currently selected window as parent. So far I didn't have issues with that, neither in GUI nor TTY. 

The error occurs only sporadically. But as soon as the error happened once, make-frame of the Corfu frame always errors.

What I find suspicious is the loop over the frames, but I don't really get what's going on.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 15:20:03 GMT) Full text and rfc822 format available.

Message #23 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 16:19:30 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> Am 4. Dezember 2025 15:20:49 MEZ schrieb "Gerd Möllmann" <gerd.moellmann <at> gmail.com>:
>  
>>I assumed that the code above checks the case where F above is the Corfu
>>frame, whose parent-frame is to be set. For each frame known, F1, the
>>code checks what would happen if the Corfu frame's parent would be set
>>to the new parent. And it finds that there is this root frame mismatch.
>>
>>So, maybe VAL is not right in this case, which is the new parent of the
>>Corfu frame? That would come from Corfu code, IIUC.
>
> Corfu uses the frame of the currently selected window as parent. So
> far I didn't have issues with that, neither in GUI nor TTY.
>
> The error occurs only sporadically. But as soon as the error happened
> once, make-frame of the Corfu frame always errors.

If it happens "randomly", then maybe there something wrong with
selected-window or whatever. Maybe logging the value of
(selected-window), (selected-frame), and (frame-selected-window) shows
if that's the case.

> What I find suspicious is the loop over the frames, but I don't really
> get what's going on.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 15:39:02 GMT) Full text and rfc822 format available.

Message #26 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 16:38:22 +0100
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> Daniel Mendler <mail <at> daniel-mendler.de> writes:
>
>> Am 4. Dezember 2025 15:20:49 MEZ schrieb "Gerd Möllmann" <gerd.moellmann <at> gmail.com>:
>>  
>>>I assumed that the code above checks the case where F above is the Corfu
>>>frame, whose parent-frame is to be set. For each frame known, F1, the
>>>code checks what would happen if the Corfu frame's parent would be set
>>>to the new parent. And it finds that there is this root frame mismatch.
>>>
>>>So, maybe VAL is not right in this case, which is the new parent of the
>>>Corfu frame? That would come from Corfu code, IIUC.
>>
>> Corfu uses the frame of the currently selected window as parent. So
>> far I didn't have issues with that, neither in GUI nor TTY.
>>
>> The error occurs only sporadically. But as soon as the error happened
>> once, make-frame of the Corfu frame always errors.
>
> If it happens "randomly", then maybe there something wrong with
> selected-window or whatever. Maybe logging the value of
> (selected-window), (selected-frame), and (frame-selected-window) shows
> if that's the case.

Not really randomly. But the overall setup is complex and I cannot
really tell what causes it and when it happens, but as soon as it
happens it happens always. There are many components (Mixed GUI+TTY,
EXWM, tab-bar-mode which also changes frame configurations).

I doubt that selected-window is wrong, since this would lead to much
bigger problems across Emacs, which many would have noticed by now. But
I will check if it occurs again.

I found another potential source for the problem. Corfu unparents the
child frame in EXWM, and maybe this is the reason for the problem. I've
now removed the unparenting for TTY child frames at least.

I'll investigate a bit more and report back.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 16:12:02 GMT) Full text and rfc822 format available.

Message #29 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 17:11:22 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> I doubt that selected-window is wrong, since this would lead to much
> bigger problems across Emacs, which many would have noticed by now. But
> I will check if it occurs again.

(Only as a side note: IIRC, there were times when selected-frame and the
frame of selected-window differed or something, temporarily.)

>
> I found another potential source for the problem. Corfu unparents the
> child frame in EXWM, and maybe this is the reason for the problem. I've
> now removed the unparenting for TTY child frames at least.
>
> I'll investigate a bit more and report back.

Good luck!




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 17:02:02 GMT) Full text and rfc822 format available.

Message #32 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 18:01:40 +0100
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> Daniel Mendler <mail <at> daniel-mendler.de> writes:
>
>> I doubt that selected-window is wrong, since this would lead to much
>> bigger problems across Emacs, which many would have noticed by now. But
>> I will check if it occurs again.
>
> (Only as a side note: IIRC, there were times when selected-frame and the
> frame of selected-window differed or something, temporarily.)
>
>>
>> I found another potential source for the problem. Corfu unparents the
>> child frame in EXWM, and maybe this is the reason for the problem. I've
>> now removed the unparenting for TTY child frames at least.
>>
>> I'll investigate a bit more and report back.
>
> Good luck!

I think I've understood now what is going on. Corfu can actually create
two child frames - the main one, and one for the help. Now if I use
Corfu on the GUI and create both frames they will get the minibuffer as
surrogate.

Now when I switch to TTY, the main frame will be recreated. But then the
help frame will still be bound to the GUI. In this case the error
appears reproducibly. I assume that the minibuffer sharing heres
violates the surrogate invariant.

I could maybe rework the frame creation code to prevent such a
situation. Otoh I don't understand why the restriction is needed in the
first place.

Daniel




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 17:07:02 GMT) Full text and rfc822 format available.

Message #35 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 18:06:25 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> I could maybe rework the frame creation code to prevent such a
> situation. Otoh I don't understand why the restriction is needed in the
> first place.

Regarding the invariant - does this mean that I cannot create two child
frames on different root frames, where one root frame lives on TTY and
another one lives on the GUI? I think this should be supported if
possible, in particular if multiple child frame packages interact.

While I could rework Corfu to delete all its child frames, I cannot do
the same about other potentially invariant violating child frames from
other packages. In this sense corfu and corfu-popupinfo are also somehow
two packages, where each creates its own child frame.

Daniel




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 17:23:02 GMT) Full text and rfc822 format available.

Message #38 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Mendler <mail <at> daniel-mendler.de>
Cc: 79947 <at> debbugs.gnu.org, Martin Rudalics <rudalics <at> gmx.at>
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 18:22:35 +0100
Daniel Mendler <mail <at> daniel-mendler.de> writes:

> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Daniel Mendler <mail <at> daniel-mendler.de> writes:
>>
>>> I doubt that selected-window is wrong, since this would lead to much
>>> bigger problems across Emacs, which many would have noticed by now. But
>>> I will check if it occurs again.
>>
>> (Only as a side note: IIRC, there were times when selected-frame and the
>> frame of selected-window differed or something, temporarily.)
>>
>>>
>>> I found another potential source for the problem. Corfu unparents the
>>> child frame in EXWM, and maybe this is the reason for the problem. I've
>>> now removed the unparenting for TTY child frames at least.
>>>
>>> I'll investigate a bit more and report back.
>>
>> Good luck!
>
> I think I've understood now what is going on. Corfu can actually create
> two child frames - the main one, and one for the help. Now if I use
> Corfu on the GUI and create both frames they will get the minibuffer as
> surrogate.
>
> Now when I switch to TTY, the main frame will be recreated. But then the
> help frame will still be bound to the GUI. In this case the error
> appears reproducibly. I assume that the minibuffer sharing heres
> violates the surrogate invariant.
>
> I could maybe rework the frame creation code to prevent such a
> situation. Otoh I don't understand why the restriction is needed in the
> first place.
>
> Daniel

For me, multi-tty is a dark corner. Just look at admin/notes/multi-tty.
But maybe Martin knows.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 17:31:01 GMT) Full text and rfc822 format available.

Message #41 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Daniel Mendler <mail <at> daniel-mendler.de>,
 Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 79947 <at> debbugs.gnu.org
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 4 Dec 2025 18:30:44 +0100
> Regarding the invariant - does this mean that I cannot create two child
> frames on different root frames, where one root frame lives on TTY and
> another one lives on the GUI? I think this should be supported if
> possible, in particular if multiple child frame packages interact.
>
> While I could rework Corfu to delete all its child frames, I cannot do
> the same about other potentially invariant violating child frames from
> other packages. In this sense corfu and corfu-popupinfo are also somehow
> two packages, where each creates its own child frame.

Does it work when you rewrite the loop as

      FOR_EACH_FRAME (frames, frame1)
	{
	  struct frame *f1 = XFRAME (frame1);
	  struct frame *m1 = WINDOW_XFRAME (XWINDOW (f1->minibuffer_window));
	  bool mismatch = false;

	  if (is_tty_frame (f1))
	    /* Temporarily install VAL and check whether our invariant
	       above gets violated.  */
	    {
	      f->parent_frame = val;
	      mismatch = root_frame (f1) != root_frame (m1);
	      f->parent_frame = old_val;

	      if (mismatch)
		error ("Cannot re-root surrogate minibuffer frame");
	    }
	}

I never thought about the idea of mixing tty and GUI frames.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79947; Package emacs. (Thu, 04 Dec 2025 18:06:02 GMT) Full text and rfc822 format available.

Message #44 received at 79947 <at> debbugs.gnu.org (full text, mbox):

From: Daniel Mendler <mail <at> daniel-mendler.de>
To: martin rudalics <rudalics <at> gmx.at>
Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
 79947 <at> debbugs.gnu.org
Subject: Re: bug#79947: 31.0.50; TTY child frame problem - Cannot re-root
 surrogate minibuffer frame
Date: Thu, 04 Dec 2025 19:04:58 +0100
martin rudalics <rudalics <at> gmx.at> writes:

>> Regarding the invariant - does this mean that I cannot create two child
>> frames on different root frames, where one root frame lives on TTY and
>> another one lives on the GUI? I think this should be supported if
>> possible, in particular if multiple child frame packages interact.
>>
>> While I could rework Corfu to delete all its child frames, I cannot do
>> the same about other potentially invariant violating child frames from
>> other packages. In this sense corfu and corfu-popupinfo are also somehow
>> two packages, where each creates its own child frame.
>
> Does it work when you rewrite the loop as
>
>       FOR_EACH_FRAME (frames, frame1)
> 	{
> 	  struct frame *f1 = XFRAME (frame1);
> 	  struct frame *m1 = WINDOW_XFRAME (XWINDOW (f1->minibuffer_window));
> 	  bool mismatch = false;
>
> 	  if (is_tty_frame (f1))
> 	    /* Temporarily install VAL and check whether our invariant
> 	       above gets violated.  */
> 	    {
> 	      f->parent_frame = val;
> 	      mismatch = root_frame (f1) != root_frame (m1);
> 	      f->parent_frame = old_val;
>
> 	      if (mismatch)
> 		error ("Cannot re-root surrogate minibuffer frame");
> 	    }
> 	}
>
> I never thought about the idea of mixing tty and GUI frames.

Thanks! Yes, it works! It looks reasonable to only check the invariant
for the tty frames - confirms my suspicion about the iteration over all
frames.

Can you please install this fix if you find no other issues with it? On
a related note, what is the status on the `set-frame-position-and-size'?
I am running your patch for a few weeks now on Gtk/X11. It seems to work
well, also in mixed scenarios :)

Daniel




This bug report was last modified today.

Previous


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.