bug-gnu-emacs
[Top][All Lists]
Advanced

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

bug#26097: Segmentation fault due to missing faces in face_cache.


From: Codrut Gusoi
Subject: bug#26097: Segmentation fault due to missing faces in face_cache.
Date: Tue, 14 Mar 2017 15:49:49 +0200

Hello,

This is a bit weird to describe so please bear with me.

I am using emacs for my day to day editing, and using Spacemacs
(http://spacemacs.org/) as a bundle of predefined configurations. Some
times, while opening files trough helm I would get a segfault. I took
a look in the coredump and also attached gdb to emacs and this is the
backtrace:
```
#0  0x00000000004ab2e0 in turn_on_face (f=0xc1c680, face_id=33) at term.c:1895
#1  0x00000000004af432 in tty_write_glyphs (f=<optimized out>,
string=<optimized out>, len=<optimized out>) at term.c:767
#2  0x000000000041c2ea in update_frame_line (address@hidden,
address@hidden) at dispnew.c:4838
#3  0x000000000041f9e6 in update_frame_1 (address@hidden,
address@hidden, inhibit_id_p=<optimized out>,
    address@hidden, address@hidden) at
dispnew.c:4540
#4  0x00000000004210fe in update_frame (address@hidden,
force_p=<optimized out>, address@hidden,
address@hidden)
    at dispnew.c:3122
#5  0x0000000000452ebc in redisplay_internal () at xdisp.c:14085
#6  0x0000000000454ad5 in redisplay () at xdisp.c:13255
#7  0x00000000004f3d1b in read_char (address@hidden,
address@hidden, prev_event=0,
address@hidden,
address@hidden) at keyboard.c:2482
#8  0x00000000004f66f0 in read_key_sequence
(address@hidden, address@hidden,
address@hidden,
address@hidden,
address@hidden,
address@hidden, bufsize=30)
    at keyboard.c:9068
#9  0x00000000004f8216 in command_loop_1 () at keyboard.c:1370
#10 0x0000000000559742 in internal_condition_case
(address@hidden <command_loop_1>,
address@hidden, address@hidden <cmd_error>)
    at eval.c:1315
#11 0x00000000004ea3fc in command_loop_2 (address@hidden) at
keyboard.c:1112
#12 0x00000000005596e3 in internal_catch (address@hidden,
address@hidden <command_loop_2>, address@hidden) at
eval.c:1080
#13 0x00000000004ea3b9 in command_loop () at keyboard.c:1091
#14 0x00000000004ee8e7 in recursive_edit_1 () at keyboard.c:697
#15 0x00000000004eec28 in Frecursive_edit () at keyboard.c:768
#16 0x00000000004182bb in main (argc=3, argv=0x7fffe9ed0908) at emacs.c:1629
```

This led me to the term.c file at 1895 (emacs 25.1.90), inside the
turn_on_face function.
Notice face_id=33 on frame 0 args. That was equal to
f->face_cache->used which means FACE_FROM_ID returns NULL and causes
the segfault in turn_on_face.

I tried looking around to understand why this was happening but I did
not uncover much.
Then I tried finding a fix for the problem at hand, more exactly what
to do when FACE_FROM_ID returns a NULL and how to deal with it so that
it would no longer segfault. Here is what I came up with:
* I could simply return; from turn_on_face (and the complementary
turn_off_face) function on NULL. From what I understand this means
leave text on the screen as is, don't redraw. This is inside the
attached 001.patch
* I could return the defualt face from FACE_FROM_ID. This would mean
text would be displayed on screen with an unexpected default face, but
at least it would not crash. The fix is inside the attached 002.patch
(emacs 25) and 004.patch (emacs 26).
* I could get the default face directly in the turn_on_face function
in case of NULL, in case modifying the behaviour of FACE_FROM_ID is
unwanted. This is inside the attached 003.patch.

Now let me explain how exactly you can reproduce the bug:

* First you will need a linux environment. This bug should be
reproducible on any linux. You could do it on your own linux or you
could get my current setup: VirtualBox and
https://manjaro.org/get-manjaro/ xfce.
* Then you will need emacs and xclip installed. You can install them
from your package manager or from source, I've reproduced the bug with
the following versions: 25.1.1, 25.1.90 and when building master from
source.
* Open a terminal and either make it fullscreen or maximized.
* To install spacemacs you first need to remove ~/.emacs.d and
~/.emacs and then execute the following commands:

git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d
curl -fSLo ~/.spacemacs
https://raw.githubusercontent.com/sdwolf/dotfiles/master/.spacemacs

* Now you must start emacs inside a relatively large git repository. I
have chosen emacs's repo for this.

cd emacs
emacs -nw .

* You now have to wait untill emacs gets all the packages. when this
is done you will have exactly the same setup as I have on all my
machines.
* You have to stop emacs and start it again. You can either do C-x C-c
or :qa! since it used evil-mode (vim style).
* When you have it started again you should see 2 thigs. First on the
left neotree opened with the contents of the current directlry, which
should be the contents of the emacs repo. On the right would be dired
with the same content.
* From this place you need to press <spacebar> p f (that is spacebar
followed by 'p' followed by 'f' on separate key strokes, do not hold
down the keys, just press). This will bring up helm in the lower part
of the screen. The idea is to open a relatively large file so that
emacs has a lot of work to do and potentially trigger the segfault.
The cursor will be on helm's search so you can type "src/term.c"
(without the quotes) then press return (RET). If this does not crash
emacs, you will have to move to a relatively large line number, ex
1800 and close emacs. This means that next time you open this file,
emacs will open it at that line number. To move to that line number
just type ":1800" and pres return (RET). To close emacs from here you
can type ":qa!" and press return (RET).
* You will have to open emacs again and do the above step again. This
manages to trigger the segfault every time in my case. Note that it
should take a relatively long time to open this file (6--10 seconds),
so please wait patiently.

Some things i've observed while digging with gdb:
- Before opening helm in the setup above there are 28 faces in the face_cache.
- After I open helm the cache fills with around 48 faces.
- When i hit return after selecting a file, the cache fills up with
more faces, until it gets to displaying the frame corresponding to the
file (buffer). Then the face_cache drops to 33 (f->used == 33).
- When it gets to the line where it must redisplay helm (vpos == 29 on
dgb frame 2 above), it wants to redisplay the faces for helm but they
are no longer in the cache, so FACE_FROM_ID returns NULL and a crash
happens when the code dereferences the porinter a line below.
- Since helm dissapears a few moments later, it's no problem if you
just skip over this with a return or if you use a default face.
- On emacs 25 with any of my patches applied, for a fraction of a
second after pressing return and helm closing, you can still see the
lower left corner of the screen (where the neotree area resides) still
having the contents of helm. But that part is imediatly redrawn with
the content of neotree. On emacs 26 that part does not get redrawn,
untill you do an action like moving up/down one page or switch to
neotree. This might be an inconvenience but in my opinion it's better
than having a segfault.

Hopefully I've managed to describe the problem (and potentially the
patches I've attached are helpfull). Feel free to ask if you need
further clarifications. Right now I am using my patched version of
emacs to do my work and it would be great if a fix or workaround for
this would be available in the default versions.

For reference, here is an issue on github direclty related to this
problem: https://github.com/syl20bnr/spacemacs/issues/8197

Thank you,
Codrut

Attachment: 001.patch
Description: Text Data

Attachment: 002.patch
Description: Text Data

Attachment: 003.patch
Description: Text Data

Attachment: 004.patch
Description: Text Data


reply via email to

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