Subject: bug#12026: 24.1.50; crash in tooltip

From: Johan Bockgård <[email-masked]>
Date: Mon, 23 Jul 2012 18:56:45 +0200

Sam Steingold <[email-masked]> writes:

> Lisp Backtrace:
> "message" (0xffffb300)
> "byte-code" (0xffffb3e0)
> "tooltip-show" (0xffffb800)
> "tooltip-help-tips" (0xffffbaa8)
> "run-hook-with-args-until-success" (0xffffbaa0)

1.

I can reproduce it by

    (setq x-gtk-use-system-tooltips nil)

    Move the mouse over a tooltip area in the mode line.
    => Crash

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.

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;
-
   /* By setting the output method, we're essentially saying that
      the frame is live, as per FRAME_LIVE_P.  If we get a signal
      from this point on, x_destroy_window might screw up reference

2.

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

(Also crashes in Emacs 23.)

3.

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

(Also crashes in Emacs 23.)