LINUX.ORG.RU

Теперь дебажим SDL1; уточнение вопроса поломки работы с фреймбуфером свежих ядер

 , ,


1

3

Итак, теперь более основательно продебажил с другой стороны. Не со стороны ядра, а со стороны самой SDL1. И результат, надо сказать, несколько отличается от того, что предполагалось.

strace показывает, что сегфолт происходит в районе вызова FBIOPUT_VSCREENINFO. Такое в SDL1 есть и при тестировании видеорежимов. Однако, критичным оказался неожиданный кусок video/fbcon/SDL_fbvideo.c.
Находится он в функции FB_SetVideoMode() и в оригинале выглядит так:

                if ( !shadow_fb &&
                                ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
                        vinfo.yres_virtual = height;
                        if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
                                SDL_SetError("Couldn't set console screen info");
                                return(NULL);
                        }
                }
Так вот. Если его привести к виду
                if ( !shadow_fb &&
                                ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
                        vinfo.yres_virtual = height;
                        /*if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
                                SDL_SetError("Couldn't set console screen info");
                                return(NULL);
                        }*/
                }
то всё начинает работать без сегфолтов на ванильных свежих ядрах.

Патч: http://saahriktu.org/downloads/patches/make_sdl1.2.15_works_with_framebuffer_...

★★★★★

Последнее исправление: saahriktu (всего исправлений: 1)

Где-то я читал, что в kdesu времём kde2/kde3 был баг, который не проявлялся. В ядро Linux внесли изменение, из-за которого kdesu перестал логинить. Когда завели баг, то автор изменения сказал «баг не с нашей стороны - надо вносить изменения в kdesu». Линус Торвальдс внёс необходимые изменения в ядро, необходимые для починки kdesu. Когда программист спросил «почему», он ответил «пользователя не волнует», и рассказал простые истины про обратную совместимость и про то, почему она важна

Я так думаю, в данном случае описанный выше пример не применим, потому что kdesu пользовались миллионы людей, а SDL под Framebuffer - единицы. Хотя на днях релизнули PlayStation Classic, и там как раз SDL1 + DirectFB, лол

ZenitharChampion ★★★★★
()
Последнее исправление: ZenitharChampion (всего исправлений: 1)
Ответ на: комментарий от ZenitharChampion

WE DO NOT BREAK USERSPACE!

Seriously. How hard is this rule to understand? We particularly don't break user space with TOTAL CRAP.

(c)

annulen ★★★★★
()

я бы не стал выкидывать этот код, просто обработчик ошибки заменил бы на варнинг.

bass ★★★★★
()

Пока это всё ещё выглядит так, как будто FBIOPUT_VSCREENINFO работал со вчерашней версией ядра, и перестал работать с сегодняшней. То есть это всё ещё баг ядра.

То, что кто-то выше по стеку вызовов не проверят возврат этой функции на NULL и что-то пытается с ним делать, это уже совсем другая проблема.

Тролльвальдс вон как раз в LKML пишет:

We have very clear rules in the kernel: if some change breaks existing
setups, it is ABSOLUTELY NEVER the application that is broken.

It is the kernel.
Seriously, the "we don't break user space" is the #1 rule in the
kernel, and people should _know_ it's the #1 rule.

If somebody ignores that rule, it needs to be escalated to me.
Immediately. Because I need to know.

I need to know so that I can override the bogus NAK, and so that we
can fix the breakage ASAP. The absolute last thing we need is some
other user space then starting to rely on the new behavior, which just
compounds the problem and makes it a *much* bigger problem.

But I also need to know so that I can then make sure I know not to
trust the person who broke rule #1.

This is not some odd corner case for the kernel. This is literally the
rule we have lived with for *decades*.

So please escalate to me whenever you feel a kernel developer doesn't
follow the first rule. Because the code that broke things *will* be
reverted (*).

                    Linus

(*) Yes, there are exceptions. We have had situations where some
interface was simply just a huge security issue or had some other
fundamental issue. And we've had cases where the breakage was just so
old that it was no longer fixable. So even rule #1 can sometimes have
things that hold it back. But it is *very* rare. Certainly nothing
like this.
Так что, возможно, баг есть и в ядре (сломали существующие приложения в юзерспейсе) и в SDL1 (недостаточно хорошо проверяют возврат из функций, которые могут сфейлиться).

Deleted
()

Мне стало интересно...

saahriktu, а есть какой-нибудь относительно простой способ воспроизвести это в виртуалке под qemu? С инструкцией типа «взять дистрибутив A версии X, установить в нём программу B версии Y и запустить её таким то образом».

Ядра разных версий я собрать могу, а вот все юзерспейсные компоненты, включая SDL1 и тестовые программы со всеми зависимостями - хз.

Deleted
()
Ответ на: Мне стало интересно... от Deleted

Достаточно найти и запустить дистрибутив с ядром одной из следующих версий: 4.14.80-, 4.18.18-, 4.19, 4.20. И войти там в ядерную консоль с DRM'овским фреймбуфером (radeondrmfb, nouveaufb, inteldrmfb,...). Софт на SDL1 там уже будет сегфолтиться. А если пропатчить SDL1 патчем из первого поста этой темы, то перестанет. При этом с ядрами до версий 4.14.79 и 4.18.17 включительно всё будет работать из коробки без всяких патчей. Соответствующий патч внесли именно в ядра версий 4.14.80, 4.18.18 и 4,19. Из 4.19 он перешёл и в 4.20.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Не могу воспроизвести в qemu ситуацию, при которой SDL1 вообще работает. Тестирую на Fedora 29 x86_64 с самосборными ядрами, fbi (фреймбуфферный просмотрщик картинок, не на SDL1) и xblast (какая-то игра на SDL1) из репозиториев федоры. Результат такой:

  • 4.18.0: fbi работает, xblast падает.
  • 4.20.0: fbi работает, xblast падает.

В общем, сама проблема воспроизводится, но факт поломки со стороны ядра - нет.

Может там ещё какие-то условия есть?

upd. Реверт коммита db05c481977599236f12a85e55de9f5ab37b0a2c из предыдущей темы никак не влияет на ситуацию.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от saahriktu

Судя по всему, с тем багом фреймбуфер не работал вообще. А тут он работает, fbi нормально картинки показывает.

Deleted
()
Ответ на: комментарий от saahriktu

Нашёл ещё одну игрушку на SDL1: sopwith.

Если сразу при запуске системы выбрать родное для неё разрешение («video=VGA-1:640x400»), то она работает и под 4.18.0 и под 4.20.0.

Если выбрать меньшее разрешение, то она выдаёт сообщение о том, что не может настроить видеорежим. И на 4.18.0 и на 4.20.0.

Если выбрать большее разрешение, то и там и там происходит какая-то хрень, после которой на экран перестаёт обновляться. И плюс не получается переключиться на другую консоль. Видимо это какой-то другой баг.

Автор, может ты уже поделишься точной инструкцией по воспроизведению того, что ломается именно у тебя?

Deleted
()
Ответ на: комментарий от Deleted

Ну так ядра уже пропатчены или ещё нет?

Если ничего не патчить, то из коробки со свежими ядрами софт на SDL1 (включая fceux, Retro Arch,... и т.д.) на DRM'овских фреймбуферах будет просто сегфолтиться. Однако, можно пропатчить или ядро или библиотеку SDL1.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Ну так ядра уже пропатчены или ещё нет?

Без посторонних патчей.

Если ничего не патчить, то из коробки со свежими ядрами софт на SDL1 (включая fceux, Retro Arch,... и т.д.) на DRM'овских фреймбуферах будет просто сегфолтиться. Однако, можно пропатчить или ядро или библиотеку SDL1.

Ну вот не воспроизводится это с любым софтом на SDL1. sopwith - работает.

Deleted
()
Ответ на: комментарий от Deleted

Если выбрать большее разрешение, то и там и там происходит какая-то хрень, после которой на экран перестаёт обновляться. И плюс не получается переключиться на другую консоль. Видимо это какой-то другой баг.

Это похоже не баг, а ожидаемое поведение фреймбуфера, когда его забывают переключить обратно из графического режима в текстовый. Сама прога в этом случае выдаёт на stderr нормальное сообщение об ошибке («init screen: failed»), без сегфолта.

Deleted
()
Ответ на: комментарий от saahriktu

Пересобрал fceux, чтобы отвязать его от GTK. Если разрешение фреймбуфера сразу стоит то же самое, которое пытается запросить fceux, то всё работает. Если другое, то fceux выдаёт «Couldn't set console screen info», что логично. Поведение не отличается между 4.18.0 и 4.20.0.

Версия SDL: 1.2.15. С патчами от мейнтейнеров федоры, но там вроде ничего связанного с фреймбуфером нет.

Deleted
()
Ответ на: комментарий от saahriktu

А у тебя, кстати, какой драйвер используется?

И пробовал ли ты воспроизвести проблему со своим юзерспейсным окружением, но в qemu?

Deleted
()
Ответ на: комментарий от Deleted

Если разрешение фреймбуфера сразу стоит то же самое, которое пытается запросить fceux, то всё работает. Если другое, то fceux выдаёт «Couldn't set console screen info»

При чём тут разрешение? Это «Couldn't set console screen info» появляется как раз как следствие того, что теперь из за того патча от американского товарища DRM'овский фреймбуфер теперь стал по дефолту «Reject all pixel format changing requests» с возвращением -EINVAL. Именно «pixel format changing requests». А SDL'овская функция FB_SetVideoMode() в дефолтном виде при возвращении этого -EINVAL считает, что всё пропало, и возвращает NULL. Это «Couldn't set console screen info» как раз сообщение самой библиотеки SDL. И именно из тех 4-х строчек, которые я вырезал (про что и написано в первом посте темы). После чего у меня всё заработало и с ванильными свежими ядрами.

А у тебя, кстати, какой драйвер используется?

radeondrmfb.

И пробовал ли ты воспроизвести проблему со своим юзерспейсным окружением, но в qemu?

Нет. Живое железо же лучше. Мало ли какие грабли связаны именно с реализацией виртуальных машин.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

При чём тут разрешение?

Вооот... а оно, кстати, при чём! Я кажется понял в чём проблема с SDL1 и фреймбуфером конкретно у меня. ИМХО это ещё один небольшой баг.

Нет. Живое железо же лучше. Мало ли какие грабли связаны именно с реализацией виртуальных машин.

Лучше пробовать воспроизводить баги в разных средах. Так обычно проще понять что именно и где сломалось. Ну и позволяет найти ещё больше багов 8).

А воспроизведение в qemu бонусом даёт гарантию того, что другие люди тоже смогут воспроизвести проблему и поковырять её.

Кстати, у тебя на сайте из профиля актуальный email? Как тебя в Cc: указывать? А то я хочу попробовать описать все находки на тему SDL1+новые_ядра и закинуть в LKML. И посмотреть что из этого выйдет.

Deleted
()
Ответ на: комментарий от Deleted

у тебя на сайте из профиля актуальный email?

Да.

Как тебя в Cc: указывать?

Можно и этот email с сайта указать, да.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Последние (надеюсь) вопросы:

  • Какое у тебя разрешение во фреймбуфере?
  • С какими опциями и каким ромом ты запускаешь fceux?
Deleted
()
Ответ на: комментарий от Deleted

Какое у тебя разрешение во фреймбуфере?

1920x1080 конечно же.

С какими опциями и каким ромом ты запускаешь fceux?

Сегфолты происходят независимо от рома. Дополнительных опций не указываю. Заглянув в конфиг обнаружил там эти актуальные настройки:

SDL.AutoScale = 1
SDL.BitsPerPixel = 32
...
SDL.Fullscreen = 0
...
SDL.KeepRatio = 1
SDL.LastXRes = 1920
SDL.LastYRes = 1080
...
SDL.OpenGL = 0
SDL.OpenGLip = 0
...
SDL.XScale = 4.000000
SDL.YScale = 4.000000

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от saahriktu

Можешь потестить вот эти два патча: 1, 2? Если всё будет ок, допишу к ним сопроводительное письмо и отправлю.

Deleted
()

В общем, вот: https://lkml.org/lkml/2018/12/26/107. Надеюсь, понятно написал на своём корявом инглише. Посмотрим ответят ли...

Deleted
()

Касательно возможности исправления этого со стороны SDL...

Фикс из первого поста некорректен. Вот этот код -

		if ( !shadow_fb &&
				ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
			vinfo.yres_virtual = height;
			if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
				SDL_SetError("Couldn't set console screen info");
				return(NULL);
			}
		}
- имеет следующий смысл: сначала пробуем FBIOPUT_VSCREENINFO с обычным vinfo, а если не срабатывает, то меняем vinfo.yres_virtual, пробуем ещё раз и ещё раз проверяем на ошибки. Соответственно, если просто закомментить второй вызов ioctl(), то ошибка первого ioctl() будет просто проигнорирована. Вряд ли это именно та логика, которая должна тут быть.

Вообще, в SDL какой-то жуткий говнокод вот в этой части, которая выбирает правильные параметры для передачи в FBIOPUT_VSCREENINFO. Иногда он берёт захардкоженные значения, иногда читает /etc/fb.modes и как-то хитро перерабатывает(???). Если SDL считает, что текущий режим уже правильный, то FBIOPUT_VSCREENINFO похоже просто не вызывается.

Я, честно говоря, не понял до конца как это работает. И не могу посоветовать как это исправить со стороны SDL 1.2 так, чтобы гарантированно не сломалось что-то другое.

Касательно сегфолов: если код, вызывающий функции SDL не проверяет возвращаемые значения и из-за этого сегфолтится, то чинить надо и его тоже.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Вряд ли это именно та логика, которая должна тут быть.

Да. Однако, как ни странно, практически это почему-то работает.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Была возможность потестить патчи на ядро без патчей на SDL? Это важно.

Да. Однако, как ни странно, практически это почему-то работает.

Практически это работает потому что ты 1) удалил проверку на ошибки, которые возвращает ядро и 2) требуемый SDLем pixel format в твоём случае и так совпадает с тем, который фактически настроен на fbdev. В каких-то других ситуациях удаление этого кода скорее всего наоборот всё сломает и на экран будет выводиться мусор вместо нормальной картинки.

Deleted
()
Ответ на: комментарий от Deleted

Была возможность потестить патчи на ядро без патчей на SDL? Это важно.

Так в первой теме я же патчил конкретно ядро. До библиотеки SDL я добрался только в этой теме.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Мои патчи слегка отличаются. И я их отправил в LKML. Хочется, чтобы именно их потестировал кто-то кроме меня и на железе, отличном от моего.

Deleted
()
Ответ на: комментарий от saahriktu

Я выше кинул две ссылки.

Рибейз на самое свежее ядро из гита (там пришли другие изменения в той же функции) тоже есть:

Deleted
()
Ответ на: комментарий от Deleted

Что-то они на ядро 4.20 не наложились. Пришлось переносить руками. В итоге всё заработало, но немного кривовато (картинка не по центру экрана; а с моими патчами по центру). Никакой отладочной информации ни в каких выхлопах не наблюдается.

Там в багзилле SDL мне ещё порекомендовали в этой SDL1 закомментировать строчку

vinfo.bits_per_pixel = bpp;
Это я сейчас тоже протестировал, но это не работает совсем. Сейчас пойду отписываться туда.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

а с моими патчами по центру

С твоими патчами на ядро или с твоими патчами на SDL?

И какое поведение было до поломки с стороны ядра?

Deleted
()
Ответ на: комментарий от Deleted

В обоих случаях (и когда ядро пропатчено, а SDL1 нет, и когда ядро непропатчено, а SDL1 пропатчена). До картинка тоже была по центру.

Пока ещё никуда не отписывался, решил ещё немного поковырять. И нашёл, что у меня это как-то связано именно с double buffering и, по ходу, виртуальным разрешением фреймбуфера.

Если просто отключить double buffering в софте, то сегфолт исчезает, но картинка превращается в кашу.

В общем, конкретно у меня это никак не связано ни с vinfo.bits_per_pixel, ни с vinfo.xres, ни с vinfo.yres. Они сразу запрашиваются соответствующими параметрам фреймбуфера.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от saahriktu

А, ну да, видимо, из за этого флага SDL_DOUBLEBUF оно вообще начинает переопределять настройки фреймбуфера.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

В обоих случаях (и когда ядро пропатчено, а SDL1 нет, и когда ядро непропатчено, а SDL1 пропатчена). До картинка тоже была по центру.

Хм. У меня тоже не по центру. Но варианта «до» у меня нет, так как без патчей на ядро SDL1 на фреймбуфере вообще никак не работает. Потому я не знаю как это должно выглядеть правильно.

Может ты попробуешь как-то упаковать свой юзерспейс в образ или тарболл, чтобы я попробовал воспроизвести у себя этот баг точно так же?

Deleted
()
Ответ на: комментарий от Deleted

А собрать или найти ядро версии этак 4.18.17 не вариант? С этим ядром всё ещё работало без патчей. На нём и можно посмотреть как всё работало до внесения того патча из за которого всё началось.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

А собрать или найти ядро версии этак 4.18.17 не вариант? С этим ядром всё ещё работало без патчей. На нём и можно посмотреть как всё работало до внесения того патча из за которого всё началось.

Ну я же писал, что со старыми ядрами у меня НЕ РАБОТАЕТ точно так же, как с новыми без патча.

И вообще воспроизводимость вот этой поломанной логики в SDL зависит от кучи факторов.

Deleted
()
Ответ на: комментарий от saahriktu

Ну так особенности моего окружения тогда ничем тут не помогут.

Вот как раз они и помогут, потому что со стороны ядра разницы нет: эмуляция fbdev поверх DRM-драйверов работает одинаково на всех видеокартах.

Deleted
()
Ответ на: комментарий от saahriktu

Вот мой вариант этого ядра, но оно заработает далеко не везде: http://saahriktu.org/linux-4.18.17

Да, оно собрано монолитом. С поддержкой radeondrmfb и inteldrmfb.

Если ты не пересоберёшь его так, чтобы оно работало в qemu к каким-нибудь нормальным конфигом железа, то толку от этого ядра в данном контексте ровно ноль.

Сейчас оно просто виснет на «Booting the kernel».

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Ну так само окружение у меня в целом вполне ванильное. Тут больше суть в конкретном железе и в конкретном ядре.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от Deleted

И я даже не знаю о каких опциях речь. Никогда ничего не собирал под виртуальные машины. Только под реальное железо.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Ну так само окружение у меня в целом вполне ванильное.

Тогда выкладывай его целиком. Ну или хотя бы расскажи как его воссоздать с точностью до версий всех библиотек и программ, а тк же всех настроек. Настройки - это важно.

Тут больше суть в конкретном железе и в конкретном ядре.

Нет. Ещё раз: эмуляция fbdev поверх DRM работает одинаково на разных устройствах. Как минимум та часть, в которой участвует проблемный код со стороны ядра.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.