Tag Archives: Mimbolovekonsole

Баг Konsole повержен !

Written by elwood

Вчера ночью я наконец добил этот баг, а сегодня вечером патч уже был закоммичен в master git-репозитория konsole. Для того, чтобы разобраться в сути проблемы, понадобилось несколько вечеров, пара виртуалок с линуксами OpenSuse (здесь, собственно, баг был обнаружен) и Debian (на ней я работал с KDevelop, потому что мне показалось, что gdb будет работать лучше в стабильной версии KDevelop – на самом деле всё было так же как и в OpenSuse) и исходники konsole и xterm.

Поиск точки сбоя

Как известно, чтобы поправить что-то, нужно сначала разобраться, что именно работает не так, локализовать проблему. Предстояло определить, что служит причиной неверного вывода на экран. Исходники konsole написаны хорошо, с большим количеством комментариев и удачными названиями классов, поэтому кандидаты на пристальный осмотр были определены сразу: классы TerminalDisplay, Emulation, Vt102Emulation, Pty и Screen. Идея была следующая: написать дампер текущего состояния визуализации и вызывать его при каждом обновлении. Обновление производил TerminalDisplay в функции updateImage(), и я добавил в него дамп матрицы символов и атрибутов, которые должны быть выведены на экран. После испытаний выяснилось, что в этом месте ошибочные атрибуты последних символов уже сформированы, и, значит, надо искать проблему не в выводе на экран, а в коде, который формирует эту матрицу буфера вывода.

Если мы с вами посмотрим на то, что такое эмуляторы терминала, то увидим, что они работают следующим образом. На входе эти программы получают последовательность байт (в которых кодируются как символы для вывода, так и различные управляющие коды), внутри себя они интерпретируют её как последовательность команд вида “добавь символ X”, “установи курсор в (1;3)”, “поменяй текущий цвет на Green” и на выходе выдают ту самую матрицу символов и атрибутов, которая выводится на экран.

Чтобы быстро понять, какие команды генерирует тестовая программа на ncurses, я расставил брейкпоинты на большинство методов класса Screen. И после некоторых мучений обнаружил, что при ширине экрана > 80 ncurses генерирует не те команды, что приходят, когда ширина экрана меньше 80 ! Выяснилось, что ncurses внутри оптимизирует свой вывод, и в проблемном случае для строки возвращает последовательность управляющих кодов, которая делает только удаление одного символа! А в конец строки после этого уже ничего не дописывается, и там появляется пустота.

Исцеление

Встал вопрос – почему эта штука работает в других эмуляторах терминалов ? За ответом было решено лезть в исходники gnome-terminal (точнее, vte – библиотеки, которую gnome-terminal использует для эмуляции), но они оказались намного менее читаемы по сравнению с konsole. И я попробовал вместо гномовских посмотреть исходники xterm, благо они оказались более понятны. И нашёл код функции удаления символа, из которого стало понятно, что после удаления символов будут дописаны пробелы справа, но не с пустыми атрибутами, а с теми, которые установлены сейчас в консоли.

Собственно, после этого уже не составляло труда дописать пару строк, исправляющих проблему. Протестировал на тестовом приложении, запустил и console framework, проверил работоспособность нескольких других консольных программ (mc, vim), всё было ок, оставалось предложить патч для исправления бага. Для этого оказалось достаточным написать комментарий с детальным описанием сути проблемы и приложить патч. В течение следующего дня патч был проверен и закоммичен в master.

Успех.jpg:

На этом подвожу итог с разборками в Konsole, рад как слон, что не придётся писать обходные пути в console framework для рендеринга в konsole-based эмуляторах терминала. Интересно, сколько времени пройдёт до тех пор, пока фикс не будет втянут в пакеты популярных дистрибутивов ? Прямо реально интересно, готов даже не лениться и периодически проверять самые ходовые дистрибутивы (Fedora, CentOS, OpenSuse, Debian, Ubuntu, Arch, Gentoo). Только не знаю, как.

Лёд тронулся!

Written by elwood

Недавно я наткнулся на проблему с рендерингом console framework в стандартном эмуляторе терминала для KDE – Konsole. Проблема заключалась в том, что при перемещении окошек влево в терминале с шириной, равной или меньше ширины буфера экрана, справа от окна появлялись артефакты:

До этого я тестировал в других эмуляторах терминала (gnome-terminal, xterm, putty), и таких проблем не возникало никогда. После некоторых исследований стало ясно, что это бага в самом Konsole. Я был очень удивлён и не питал особых надежд на то, что такой баг можно легко воспроизвести, а тем более убедить мейнтейнеров проекта. Во всяком случае прикладывать к багрепорту аттач с программой на моно, которая внутри неочевидно (для мейнтейнеров) работает, имело бы мало смысла. Поэтому я решил попробовать сделать тестовую программу на чистом Си, минимального размера, но чтобы проблема была наглядно продемонстрирована. И это получилось ! Текст программы можно посмотреть в описании бага. Демонстрация проблемы была наглядна:

После этого я попросил в конференции гентоводов проверить, воспроизводится ли проблема у них. Пользователи Gentoo устанавливают одни из самых последних билдов программ, поэтому проверка у них – это важно. Оказалось, что баг действительно воспроизводится. Прошла неделя, я потихоньку уже сам стал разбираться в исходниках Konsole, научился собирать из исходников, логировать данные в момент обновления экрана, и вот сегодня – баг получил статус CONFIRMED, а значит, и некоторый шанс на то, что им кроме меня кто-то займётся.