Skip to content
Tech News
← Back to articles

Fixing a 20-year-old bug in Enlightenment E16

read original get Enlightenment E16 Legacy Support Kit → more articles
Why This Matters

This article highlights the significance of maintaining and updating legacy software in the tech industry, as it demonstrates how long-standing bugs can persist and impact user experience even decades after their inception. Fixing a 20-year-old bug in Enlightenment E16 underscores the importance of community-driven development and the ongoing effort to preserve and improve niche, yet influential, open-source projects for dedicated users and enthusiasts.

Key Takeaways

The editor in chief of this blog was born in 2004. She uses the 1997 window manager, Enlightenment E16, daily. In this article, I describe the process of fixing a show-stopping, rare bug that dates back to 2006 in the codebase. Surprisingly, the issue has roots in a faulty implementation of Newton’s algorithm.

Some may find it weird, but I actually greatly enjoy using Enlightenment E16 as my window manager. It’s themable, hackable, lightweight (24MB peak RSS!), amenable to heavy keyboard users like myself, and most importantly - it looks goregous:

E16 first came to be in 1997, thanks to Carsten Haitzler, and it has been in development ever since. Most have moved to E17 and other newer versions; a community of hardcore enthusiasts still uses E16, and I am one of them. The codebase is quite old, and it has accumulated a lot of technical debt over the years.

Bugs always come out of the woodworks in a time scramble and this one likely sensed a prime opportunity: I was doing a lot of last-minute work on a couple of slides for a course that I will be teaching. I had a couple of PDFs with lecture slides and an exercise sheet typeset in LaTeX. At some point, I opened one of them in Atril, and the entire desktop froze.

The bug⌗

I killed the X11 session from a TTY. Sadly, the hang was deterministic: every time I opened that specific PDF.

Attaching gdb to the live process showed every sample parked in imlib2’s font cache, under the same e16 caller:

#0 __strcmp_evex () #1 __imlib_hash_find (hash=0x55bc9c111420, key="\001\001\001\001\001") object.c:172 #2 __imlib_font_cache_glyph_get (fn=..., index=0) font_draw.c:30 #3 __imlib_font_get_next_glyph (... utf8="Kickoff.pdf — Introduction...") font_main.c:218 #4 __imlib_font_query_advance (...) font_query.c:89 #5 imlib_get_text_advance (...) api_text.c:231 #6 Efont_extents (...) text_ift.c:87 #7 _ift_TextSize (...) text_ift.c:156 #8 TextstateTextFitMB (ts=..., textwidth_limit=291) text.c:350 #9 TextstateTextFit (...) text.c:559 #10 TextstateTextDraw (... text="Kickoff.pdf — Introduction...") text.c:638 #11 ITApply (...) iclass.c:930 #12 ITApply (...) iclass.c:884 #13 _BorderWinpartITclassApply (ewin=..., i=2, force=1) borders.c:179 #14 EwinBorderUpdateInfo (ewin=...) borders.c:300 #15 EwinChangesProcess (...) ewins.c:2141 #16 EwinEventPropertyNotify (ewin=..., ev=...) ewins.c:1438 ... #21 main (...) main.c:320

Re-attaching repeatedly showed the program was not deadlocked. __imlib_font_cache_glyph_get was being called with different glyph indices (0, 20, 73, 81, 82, 87, 88, …) each time. So the inner font-measurement was making progress; the loop was somewhere outside it.

After some fudging, I found out that Frame 8 ( TextstateTextFitMB at text.c:350 ) was the constant. That’s a ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent); call inside the middle-ellipsis truncation loop that tries to fit a string into textwidth_limit = 291 pixels by nuking characters out of the middle - used when rendering the title of the PDF, that happened to also be the title of the window, too long for the decoration to contain.

... continue reading