emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: --with-cairo Emacs server crash and fix


From: Liam Quinlan
Subject: Re: --with-cairo Emacs server crash and fix
Date: Fri, 9 Aug 2019 11:40:21 -0400

It is definitely specific to cairo builds.  The 'fringe_bmp' array (not to be confused with the 'fringe_bitmaps' array) has a cairo api type and is declared behind #ifdef USE_CAIRO.

I *think* the minimal init file to reproduce is actually '-Q'... provided you can get flymake to display its error fringe indicator, which embarrassingly I cannot (no backends will run... definitely unrelated, probably self inflicted).   Assuming you can accomplish this (flymake-error-bitmap uses flymake-double-exclaimation-mark, flymake-fringe-indicator-position isn't nil, fringe-mode is on, etc), the steps to reproduce are very simple:

1. build --with-cairo, using any x toolkit
2. start an emacs server with --daemon option  (ie don't 'M-x server-mode')
3: connect normally with emacsclient
4: open a file with syntax errors and more than one screen of text
5: get flymake to display its error indicators
6: scroll up and down.  It won't take very long.

Should it prove easier somehow flycheck and sesman also define custom bitmaps, either of which will do.  It can be any fringe-bitmap defined in package that gets loaded during the daemon process's own startup.  Packages that don't load until emacsclient connects are fine, as by that point an x frame exists and SELECTED_FRAME will work.

I'm experiencing this building from head, but last I checked building the 26 branch didn't change anything.



Possibly also useful: the following gdb script is more or less what my actual investigation lead to.  It will start the server process, and break each time a fringe bitmap initialization needs to call rif->define_fringe_bitmap but isn't able to. The values of 'which' when this occurs will be the fringe_bmp indexes that go uninitialized and cause the crash (culprit index for a given crash can be recovered from the coredump).  It is possible to monkey-patch a server instance during startup by manually calling x_redisplay_interface.define_fringe_bitmap yourself each time the breakpoint fires.


set print pretty on
set print array on 
set print array-indexes on

file path/to/built/emacs
set args --fg-daemon=cairo

break src/fringe.c:1481 if ! rif
commands 
  printf "\nwhich: %d\n\n",which
  print "init_fringe_bitmap(): !(once_p || rif)"
  print "  after [...]"
  print "  if (!once_p) {"
  print "     struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());'\n"
  list
end





also, improved diff below: exposes the x_redisplay_interface structure via const pointer instead of directly

diff --git a/src/frame.h b/src/frame.h
index fa45a32d6b..fa4659eed0 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1587,6 +1587,9 @@ #define EMACS_CLASS "Emacs"
 
 #if defined HAVE_X_WINDOWS
 extern void x_wm_set_icon_position (struct frame *, int, int);
+  #if defined USE_CAIRO
+  extern struct redisplay_interface const * const x_redisplay_interface_ptr;
+  #endif
 #if !defined USE_X_TOOLKIT
 extern const char *x_get_resource_string (const char *, const char *);
 #endif
diff --git a/src/fringe.c b/src/fringe.c
index d0d599223d..a97c5e98c1 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1482,6 +1482,10 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
 
       if (rif && rif->define_fringe_bitmap)
        rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
+#if (defined HAVE_X_WINDOWS) && (defined USE_CAIRO)
+      else
+        x_redisplay_interface_ptr->define_fringe_bitmap(which, fb->bits, fb->height, fb->width);
+#endif
 
       fringe_bitmaps[which] = fb;
       if (which >= max_used_fringe_bitmap)
diff --git a/src/xterm.c b/src/xterm.c
index bbe68ef622..3cb779b39c 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13334,6 +13334,7 @@ x_activate_timeout_atimer (void)
     x_hide_hourglass
   };
 
+struct redisplay_interface const * const x_redisplay_interface_ptr = &x_redisplay_interface;
 
 /* This function is called when the last frame on a display is deleted. */
 void


reply via email to

[Prev in Thread] Current Thread [Next in Thread]