Subject: Re: bug#12026: 24.1.50; crash in tooltip

From: Eli Zaretskii <[email-masked]>
Date: Mon, 23 Jul 2012 20:51:28 +0300

> From: Johan Bockgård <[email-masked]>
> Date: Mon, 23 Jul 2012 18:56:45 +0200
> Cc: [email-masked]
> 
> The recent change to decode_any_window
> 
>       CHECK_LIVE_FRAME (w->frame);
> 
> signals an error in x_create_tip_frame since f->terminal is still NULL
> at this point
> 
>   [x_create_tip_frame]
> 
>       f = make_frame (1);
>       ...
>       buffer = Fget_buffer_create (build_string (" *tip*"));
>       Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);    <<<<
>       ...
>       f->terminal = dpyinfo->terminal;
> 
> 
> The error is caught by tooltip-show
> 
>     (condition-case error
>           ...
> 	  (x-show-tip ...))
>       (error
>        (message "Error while displaying tooltip: %s" error)
>        ...
> 
> which crashes while trying to print "(wrong-type-argument frame-live-p
> #<dead ...", since f->name is nil.

Where were you an hour ago, when I started working on this, and made
the same way (sans the GTK stuff) to the root cause? ;-)

> The problem can be fixed (error in decode_any_window avoided) by moving
> the initialization of f->terminal earlier:
> 
> === modified file 'src/xfns.c'
> --- src/xfns.c	2012-07-20 07:29:04 +0000
> +++ src/xfns.c	2012-07-23 15:14:17 +0000
> @@ -4591,6 +4591,8 @@ x_create_tip_frame (struct x_display_inf
>    f = make_frame (1);
>    XSETFRAME (frame, f);
>  
> +  f->terminal = dpyinfo->terminal;
> +
>    buffer = Fget_buffer_create (build_string (" *tip*"));
>    Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
>    old_buffer = current_buffer;
> @@ -4605,8 +4607,6 @@ x_create_tip_frame (struct x_display_inf
>    FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
>    record_unwind_protect (unwind_create_tip_frame, frame);
>  
> -  f->terminal = dpyinfo->terminal;
> -

I don't think this is the right fix.  It's not right to have frame
creation code be so fragile as to break badly when a single line is
moved around.

Perhaps we could have a smarter test in decode_any_window instead of
CHECK_LIVE_FRAME.  For example, it could somehow detect that the frame
is just being created (e.g., if its name is nil?) and let it pass.

> But the late initialisation of f->name is a problem in its own right:
> 
>     (setq x-gtk-use-system-tooltips nil)
>     (defun foo (win pos) (message "%S" (window-frame win)))
>     (add-hook 'window-scroll-functions 'foo)
> 
>     Move the mouse over a tooltip area in the mode line.
>     => Crash

This no longer crashes in revno 109194 and later.

> The same problem with f->name also exists in
> Fx_create_frame/make_minibuffer_frame:
> 
>     (defun foo (win pos) (message "%S" (window-frame win)))
>     (add-hook 'window-scroll-functions 'foo)
> 
>     (make-frame '((minibuffer . only)))
>     => Crash

Neither does this.

But the issue with CHECK_LIVE_FRAME is still there.  I just disabled
the test for now.