From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Liam Quinlan Newsgroups: gmane.emacs.devel Subject: Re: --with-cairo Emacs server crash and fix Date: Fri, 9 Aug 2019 11:40:21 -0400 Message-ID: Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="00000000000094a049058fb0fef3" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="215420"; mail-complaints-to="usenet@blaine.gmane.org" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Aug 09 17:41:11 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1hw70x-000tup-FK for ged-emacs-devel@m.gmane.org; Fri, 09 Aug 2019 17:41:11 +0200 Original-Received: from localhost ([::1]:60244 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hw70w-0006sn-Ff for ged-emacs-devel@m.gmane.org; Fri, 09 Aug 2019 11:41:10 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:50356) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hw70M-0006nf-Lh for emacs-devel@gnu.org; Fri, 09 Aug 2019 11:40:36 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hw70L-0007fb-25 for emacs-devel@gnu.org; Fri, 09 Aug 2019 11:40:34 -0400 Original-Received: from mail-ot1-x32c.google.com ([2607:f8b0:4864:20::32c]:34438) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hw70K-0007fI-QE for emacs-devel@gnu.org; Fri, 09 Aug 2019 11:40:33 -0400 Original-Received: by mail-ot1-x32c.google.com with SMTP id n5so134292217otk.1 for ; Fri, 09 Aug 2019 08:40:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=nWibMk4Az1YfPIrEmvGyIrmL0929Gah+GL/gAnSknsk=; b=ZUf83gbwwExQu8npXeuEOT9xW5B0kC8GVeqC6bz6x5GvtZ4Yp5QdN5KYPO4HlxRlOm H6xo5W2NXHiI5Wjf7vxAE/7ezBjK4XvChWvggptQgKjIwIlLytrfKjm88Ob80iVZD3DU Wuuk1bKmjMEqVmocO2vnI68M0i4FE2xqmtVQiWN5LiwnQNTt0bD85G0lPPBhFBraAJLy IDYT6svlaJFm+htxRb5C/f0XvmK/gN+UGtP6EDqn8FUWDrwmKgXbPhGQ1pIuYaZ9Uzkl i8OTaHxR1Yk+OhliJZiGGzD6oQnDu24J1mK6AvBljafmVeP0nXhGUl6xTqAa17ptnq3I P2LQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=nWibMk4Az1YfPIrEmvGyIrmL0929Gah+GL/gAnSknsk=; b=q+7alOXz/9/74MT/Yx/yisss8ebM85+m0fi3aen0MmA+MVKve12CUXMzqc4+pt7iVx PS3zibNcQ8WqDTrMir6Jr31DMHl38oZVgmDc8x8vnpWD7MGM+FwzZ9P0ypC73N5z+QAE ZyCUwQRulrwVnGZc3LOriSIeqIl6WVpE9IB10J+kWPpy43sebfJY+yxhgSUvbEx3e5i1 6j6c/ShYJ+Xo5TrXCu85eh46+zHU051OKQd3EU7OJJWlGXa8CLrm9oVBy4QCWSvs4/xR p1Z1zaVmyrJdOGbH9pfgeap1W3V7cjP18WrUP76V6/FZuaB4yK+pf4ffxpw9EHc/f5p5 40Pw== X-Gm-Message-State: APjAAAW2pKLJaPx3umLbVJs9RSkFudbenicSkZMjhtx7MWggOZX1H3ic CJ1wQAE2vw3EPTzlO6EhbRcfAjJJ9zzpe/D7SdxJJw== X-Google-Smtp-Source: APXvYqx3YYvRo5AQIgq/k50Di4gYlzL4q+ys9F03h2PWBv6rHHwX5vHv2fCyKxWq3wVqBG30DHSnMXOMzWq2S/Vnfvw= X-Received: by 2002:a05:6638:40c:: with SMTP id q12mr23372043jap.17.1565365231720; Fri, 09 Aug 2019 08:40:31 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::32c X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:239281 Archived-At: --00000000000094a049058fb0fef3 Content-Type: text/plain; charset="UTF-8" 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 --00000000000094a049058fb0fef3 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
It is definitely specific to cairo buil= ds.=C2=A0 The 'fringe_bmp' array (not to be confused with the '= fringe_bitmaps' array) has a cairo api type and is declared behind #ifd= ef 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 embarrassingl= y I cannot (no backends will run... definitely unrelated, probably self inf= licted).=C2=A0 =C2=A0Assuming you can accomplish this (flymake-error-bitmap= uses flymake-double-exclaimation-mark, flymake-fringe-indicator-position i= sn't nil, fringe-mode is on, etc), the steps to reproduce are very simp= le:

1. build --with-cair= o, using any x toolkit
2. start an emacs server with= --daemon option=C2=A0 (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.=C2=A0 It won't take very long.

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

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



Poss= ibly also useful: the following gdb script is more or less what my actual i= nvestigation lead to.=C2=A0 It will start the server process, and break eac= h time a fringe bitmap initialization needs to call rif->define_fringe_b= itmap 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).=C2=A0 = 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=C2=A0
set print array-indexes on

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

break src/fringe.c:1481 if ! rif
= commands=C2=A0
=C2=A0 printf "\nwhich: %d\n\n&q= uot;,which
=C2=A0 print "init_fringe_bitmap(): = !(once_p || rif)"
=C2=A0 print "=C2=A0 aft= er [...]"
=C2=A0 print "=C2=A0 if (!once_p= ) {"
=C2=A0 print "=C2=A0 =C2=A0 =C2=A0str= uct redisplay_interface *rif =3D FRAME_RIF (SELECTED_FRAME ());'\n"= ;
=C2=A0 list
end





also, improved diff below: exposes the x_redisplay_interface structure vi= a const pointer instead of directly

diff --git a/src/frame.h b/src/frame.h
<= div dir=3D"auto">index fa45a32d6b..fa4659eed0 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1587,6 +1587,9 @@ #define EMACS_CLASS "Emacs"
=
=C2=A0
=C2=A0#if defined HAVE_X_WI= NDOWS
=C2=A0extern void x_wm_set_icon_position (stru= ct frame *, int, int);
+=C2=A0 #if defined USE_CAIRO=
+=C2=A0 extern struct redisplay_interface const * c= onst x_redisplay_interface_ptr;
+=C2=A0 #endif
=
=C2=A0#if !defined USE_X_TOOLKIT
= =C2=A0extern const char *x_get_resource_string (const char *, const char *)= ;
=C2=A0#endif
diff --git a/s= rc/fringe.c b/src/fringe.c
index d0d599223d..a97c5e9= 8c1 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1482,6 +1482,10 @@ init_frin= ge_bitmap (int which, struct fringe_bitmap *fb, int once_p)
=C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (rif = && rif->define_fringe_bitmap)
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 rif->define_fringe_bitmap (which, fb->bits, fb->= height, fb->width);
+#if (defined HAVE_X_WINDOWS)= && (defined USE_CAIRO)
+=C2=A0 =C2=A0 =C2= =A0 else
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 x_redisplay_in= terface_ptr->define_fringe_bitmap(which, fb->bits, fb->height, fb-= >width);
+#endif
=C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0fringe_bitmaps[which] =3D f= b;
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (which >=3D max_= used_fringe_bitmap)
diff --git a/src/xterm.c b/src/x= term.c
index bbe68ef622..3cb779b39c 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13334,6 +13334,7 @@ x_activate_timeout_atimer (voi= d)
=C2=A0 =C2=A0 =C2=A0x_hide_hourglass
=C2=A0 =C2=A0};
=C2=A0
+struct redisplay_interface const * const x_redisplay_interface_ptr = =3D &x_redisplay_interface;
=C2=A0
=C2=A0/* This function is called when the last frame on a display= is deleted. */
=C2=A0void

--00000000000094a049058fb0fef3--