commit -m "better"
2.96K subscribers
868 photos
105 videos
3 files
2.07K links
just random thoughts
Download Telegram
Системы по загрузке плагинов делятся на: #plugins

* "Нормальные"

Точка входа в XXX.so имеет вид OBJECT* init_XXX(CTX*). Так устроен, например, python. Версионирование, без излишних вызовов dlsym(), без модификации глобального состояния. В общем, приемлемо, ну, насколько это вообще может быть приемлемо. Статически линкуются только в путь.

* "Ну такое"

Все, то же самое, но точка входа имеет вид init(), без _XXX. Это норм, когда система плагинов не подразумевает никакой возможности статической линковки. В случае статической линковки приходится ходить sed'ом по коду, и сводить все к первому случаю. Ну, например, vulkan loader.

* Всратые

Всратость бывает, конечно, разная. Например, плагины для gio подсистемы из glib:

https://github.com/GNOME/glib-networking/blob/master/tls/gnutls/gtlsbackend-gnutls.c#L278

Казалось бы, первый тип? Нет, 2 строчками ниже опциональная регистрация в каком-то глобальном объекте, если в конструктор не передали место, куда регистрироваться. Опциональная с точки зрения runtime, но не линкера.

Ну, от GNU и #GNOME особо никто ничего и не ждал.

* Всратейшие.

Тут кто во что горазд. Например, FAR Manager - 20 точек входа, 10 из которых - это глобальные объекты в плагине. Все это добро может быть, а может и не быть. Плагин имеет произвольный доступ к состоянию программы, к ее глобальным объектам. Ссылок не дам - это все размазано по всему коду. Ощущение такое, что кто-то порезал монолитную программу на .so произвольным образом, но, вместо того, чтобы динамически с ними слинковаться, сделал из этого плагины.

* Леденящий душу пиздец

Например, загрузка плагинов для загрузки разных форматов изображений в gdk-pixbuf. https://github.com/GNOME/gdk-pixbuf/blob/master/gdk-pixbuf/gdk-pixbuf-io.c

Что бы я тут особо подчеркнул:

- 2 разных системы загрузки плагинов - для встроенных, и для внешних

- Загрузка встроенных плагинов - квадрат от числа плагинов. 1 функция с помощью кучи макросов строит код, который по строке вернет реальный лоадер за линию, и вторая функция - которая в цикле по всем строкам дергает первую функцию. В С хеш-таблицы, как известно, не завезли. AA секцию автор этого кода бы завалил, но ему больше и не надо, код он не пишет, руководит разработкой всего GNOME.

- Самое встратое - вместо того, чтобы полистить содержимое директории с плагинами, это говно ожидает, что установщик очередного плагина добавит метаданные этого плагина в какой-то очень встратый файлик. Повторить это я не смог, и притворился, что svg - это встроенный плагин, но загружаемый через dlopen() https://github.com/pg83/mix/blob/main/pkgs/lib/gdk/pixbuf/00.diff

- Конечно, всё это говно только ради одного единственного настоящего плагина in the wild - загрузчика svg

Точек входа у каждого плагина там 2, это важно. Имена у всех них одинаковые, статическая сборка не предусмотрена.

Отдельной строкой хотел бы упомняуть лоадер из opengl(). Там, конечно, есть GetProcAddr(const char*), чтобы можно было одни драйвера делать послойно над другими, но, несмотря на это, каждый драйвер должен проэкспортировать все 300 функций из opengl() явно. Благо, это просто - все 300 функций описаны в удобном XML файле. Отсюда десятки проектов типа https://github.com/anholt/libepoxy, которые генерят мегабайты кода в виде .so, только чтобы подменить пару функций. Я думаю, программистам на C это очень заходит - мегабайты кода без единой аллокации и возможных проездов.

Я, кстати, прикидывал - средний вызов в opengl/vulkan проходит 3 - 5 уровней косвенности. Так и живем.
🔥8👍1
В одном там рабочем чате с коллегами зашла речь, кто как смотрит порно. Мне пришлось признаться, что я для этого использую рабочий macbook, потому что в моем браузере все еще не работает поддержка видео. Собственно, у меня там 3 заметных проблемы:

1) Поддержка видео. Как починю, обязательно напишу про эту эпичную историю.
2) Про кривые иконки из-за старой librsvg я уже писал, надо или как-то затащить Rust, или научить это оффлоадить в inkscape. Я склоняюсь ко второму пути.
3) И сегодняшняя история - поддержка PDF!

Epiphany, как и многие, поддерживает PDF через PDF.JS. Но оно почему-то не работает. Конечно, как обычно, дело в динамическом связывании - код, которому нужен код читалки, не может его найти в runtime. И в данном случае дело не в статической линковке, а в чем-то еще(что-то с ресурсной системой glib, я не разобрался пока).

Чинить это займет время, а pdf-ки читать надо уже сейчас.

Я решил вечерочком собрать себе читалку - Evince. Думал, плевое дело, простая программа, все зависимости уже в репе, 5 минут, не больше. Ага, конечно.

* В программе есть плагины. Читатели у меня уже прошаренные, поэтому я просто скажу, что загрузка плагинов там по второму типу #plugins Плагины много времени не заняли, все же, это основная фишка дистрибутива.

* После загрузки программы я увидел надпись "unsupported mime type application/octet-stream", и тут я понял, что это надолго.

Не буду утомлять скучными подробностями #debug, но:

* glib неявно зависит от базы данных для определения mime types. Неявно - значит, все делает вид, что работает, до поры до времени, примерно как TLS в той же #glib.

* Пути для поиска этих данных вычисляются довольно нетривиальным образом.

* Самое страшное - сборка этих данных зависит от docbook xml, а это моя дикая боль. Я напишу об этом отдельно, но надо понимать, что там очень сложная динамическая линковка данных поверх XML, все это сдобрено perl, с легким налетом GNU. Я это затащить могу, но очень не хочу, и пока просто обходил стороной. А тут жесткая зависимость сборки.

Короче, я решил, что вместо всей этой херни я вкорячу старую-добрую libmagic, из пакета file https://www.darwinsys.com/file/. Хороший, древний, проверенный код, без изъебов.

revision 1.1
date: 1987/08/23 19:51:05; author: ian; state: Exp;
Initial revision


Код чуть младше меня.

Замечания по ходу процесса:

* Пришлось сделать thread-safe обертку над api libmagic: https://github.com/pg83/mix/blob/main/pkgs/lib/mimetype/mix.sh

* Как оно используется: https://github.com/pg83/mix/blob/main/pkgs/lib/glib/01.diff (блин, а код без аллокаций на C писать вполне норм!) Я бы хотел тут остановиться, и сказать, что оно заработало like a charm, но нет

* glib сначала пытается определить тип по расширению, в #libmagic этого нет. Я это обошел тем, что всегда определяю по данным. NVMe все стерпит.

* Без нужных ему данных glib определяет длину буфера для autodetect в 0. Ну, починил.

* Названия mime types в библиотеках немного расходятся. К счастью, авторы Evince это предусмотрели, и добавить нужный mime type было несложно.

Короче, все заработало, а бонусом я выяснил, что в диалоге открытия файлов в GTK не работали иконки, потому что им нужен mimetype. А я и не замечал.

Почему freedesktop не взяли эту либу за основу, я не понимаю. Ведь в OSS так много свободных рук.
6👍3🔥1
История одного бутстрапа.

Решил я себе собрать какой-нить не-tiling wm. Выбор пал на wayfire, потому что картинки в интернете красивые. Похоже на compiz, если вы понимаете, о чем я.

https://github.com/WayfireWM/wayfire/blob/master/src/api/wayfire/plugin.hpp#L187 #plugins - первая проблема. Все плагины имеют одинаковую точку входа. И, к сожалению, в данном конкретном случае не получается модифицировать определение этого макроса, потому что его могут вызывать так - https://github.com/WayfireWM/wayfire/blob/master/plugins/single_plugins/autostart.cpp#L55 (нет законченного С токена, к которому можно привязаться).

Поэтому я испробовал новую для себя технику - переименование символов в готовых артефактах. В объектных файлах. https://github.com/pg83/mix/blob/main/pkgs/bin/wayfire/mix.sh#L51 В этом цикле мы пользуемся тем, что имя плагина совпадает с именем .cpp файла.

Потом по получившимся .o файлам строим структуры данных для моего "динамического" загрузчика - https://github.com/pg83/mix/blob/main/pkgs/bin/wayfire/mix.sh#L62

Ну и перелинковываем программу вместе с плагинами - https://github.com/pg83/mix/blob/main/pkgs/bin/wayfire/mix.sh#L71 Тут можно отметить вызов cc без -I/-L/-l, потому что моя система готовит враппер для компилятора со всеми нужными агрументами.

Казалось бы, все?

Нет, при старте программа начала кидаться исключением из какого-то глобального конструктора: https://github.com/WayfireWM/wayfire/blob/master/plugins/wobbly/wobbly.cpp#L152 У чувака таким странным образом сделан разбор аргументов командной строки. Плагин загружается уже после обработки конфига, и это как-то работает.

Ну, если уж начинать жестить - то зачем останаливаться? Я написал ленивый класс для обработки параметров конфига - https://github.com/pg83/mix/blob/main/pkgs/bin/wayfire/opts.h

Все тут же заработало? Какое там.

В логах и в strace это выглядит так - мы читаем конфиг, а дальше ничего не происходит. Потратил на это пару часов, чтобы выяснить, что автор этого кода конкретно сошел с ума - он пересекает множество запрошенных плагинов с множеством реальных файлов в папке с плагинами, чтобы отфильтровать несуществующие. Без записи об этом в лог, просто кидая на пол. https://github.com/WayfireWM/wayfire/blob/master/src/output/plugin-loader.cpp#L200 - в транке логгирование уже есть. Нормальные люди просто пытаются открыть файл по запросу, и пишут ошибку, если не получилось.

После фикса все завелось и заработало. Если найду, в комментариях будет скриншот, все же любят скриншоты! Заодно доказываю сомневающимся, что у меня есть работающая телега!

just random thoughts:

* Сначала мне показалось, что проект хорошо написан, но после всего этого вылизывания и глубокого знакомства с кодом стало понятно, что просто показалось. Наличие комментариев к интерфейсам - еще не показатель.

* У автора плагиноз головного мозга. Все сделано через плагин. Даже загрузка конфига через плагин. Кольцевая зависимость? Ничего страшного - передадим имя плагина для загрузки конфига через command line!

* Примерно половина кода проекта - поддержка перечитывания конфигурации при изменении файла с конфигом. Ну, ладно, треть. Хотя умные люди давно все придумали - общение с dbus в основном event loop.

* Для wayfire нужно было собрать https://github.com/g-truc/glm Эти упыри не только не стали делать install таргет для своей либы, но и убрали .pc файл для discover этой библиотеки, репозитариям приходится это делать вручную - https://github.com/archlinux/svntogit-community/tree/packages/glm/trunk https://github.com/archlinux/svntogit-community/blob/packages/glm/trunk/PKGBUILD#L30 Надо бы ворваться к ним в тикет, но пока нет. UPD: вломиться не получится, тикет отменили - https://github.com/g-truc/glm/issues/947
👍6
#gstreamer #plugins #gold

OSS, построенный на консалтинге - зло, так же как и OSS, основанный на продаже вендорам закрытых версий своего же OSS кода.

Пока за фичу кто-то не заплатит, хрен она появится в публичной репе, даже если будут желающие ее запилить просто так.

Вот, например, авторы gstreamer последние 15 лет всем рассказывают, как же динамически загружаемые плагины - это круто.

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

https://www.collabora.com/news-and-blog/news-and-events/generate-mininal-gstreamer-build-tailored-to-your-needs.html

Конечно, все это сделано максимально говенным способом, накрутили каких-то скриптов поверх meson https://github.com/GStreamer/gst-build/blob/master/scripts/generate_init_static_plugins.py, накостылили прокидывание настроек из основного meson файла в вспомогательные, и, самая мякотка - сказали, "а мы будем собирать все, что найдем, как обычно, а вы потом в отдельном файлике имплементируйте функцию, которая зарегистрирует все нужные вам плагины".

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

Написал однажды, и напишу еще раз.

Самый лучший опенсорс - это опенсорс от больших компаний, который:

* решает побочную для этих компаний задачу, поэтому им нет смысла вот так вот мелко гадить, типа chromium, protobuf, tensorflow, llvm, catboost, etc

* который делается по нормальным корпоративным лекалам, с тестами и KPI
🔥7👍3👎1🤔1
#plugins

У меня сейчас не собрано ни одного KDE-шного приложения(за исключением пары библиотек, ранее нужных телеге), потому что я очень не хочу иметь дело с их KParts и KIO Slaves. Про KIO Slaves(кстати, их еще не переименовали? последний раз я в их исходник заглядывал лет 15 назад) в другой раз, сегодна про #KParts.

Что такое KParts?

https://api.kde.org/frameworks/kparts/html/index.html

Если совсем просто, то каждый виджет, отнаследованный от QWidget, имеет конструктор KWidget(QWidget* parent).

* Тут возникает соблазн сделать фабрику этих виджетов, по имени. Дело полезное, скажем, для прокидывания кода в скриптуху, в построитель интерфейсов, и так далее.

* А дальше у всех разработчиков происходит какое-то умопомрачение. Как только у разработчика появляется сколько-нибудь полезная фабрика, он обязательно хочет ее сделать подгружаемой с диска, через dlopen.

Я не понимаю причины этого умопомрачения, возможно, это как-то связано с укоренившимся мифом, что "модульность" == "плагины".

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

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

Если говорить конкретно про KParts, как вот про такую плагинную фабрику по загрузке виджетов, то:

* Я не понимаю, чем для среднего приложения KParts::load("terminal", parent) лучше, чем new KonsoleWidget(parent). Нет, никто, в своем уме, не будет реализовывать другую консоль для KDE, в том числе, потому что у виджетов QT есть интроспекция в сигналах и в слотах, и хрен ты узнаешь, к каким из них подсоединился тот или иной пользователь KParts::load("terminal"). Чем хуже - понимаю, это неявная зависимость, ее надо прописывать в пакетном менеджере, вместо сборочного скрипта.

* Есть point про всякого рода просмотрщики файлов, которые из себя представляют shell для KParts. Я на это отвечу, что:

1) Просмотр jpeg и просмотр pdf сильно отличаются, и тем более, сильно отличаются от просмотра там 3ds. Обвязка/GUI в этом shell должна быть сильно разной для разных типов файлов, а если shell предназначем для каких-то конкретных типов файлов, то тогда уже нет смысла в KParts, надо просто слинковаться с нужными библиотеками для просмотра pdf/djvu/svg.

2) Загружать и выполнять произвольный код в свою программу - ну такое. У тебя какой-то third party KPart будет ездить по памяти, а ты этим shell, после просмотра файла и проезда по памяти, пойдешь браузить WEB, как это было в Konqueror(глюкалово страшное, после просмотра samba share его лучше было перезагрузить). Лучше я открою отдельное приложение через dbus/xdg-open, которое спокойно унесет проехавшуюся память за собой в могилу.

3) Если уж так хочется shell, то сделай из своего процесса wayland compositor, и открывай себе просмотрщики в отдельных процессах, показывая их GUI у себя в shell.

А для меня KParts бы означало следующее - сборку всего KDE в первый раз, для коллекционирования плагинов, а потом сборку во второй раз, с подготовленной фабрикой из этих плагинов. Признаться, мне это не очень интересно, да и полезность не очень понятна.
👍8
Я тут какое-то время обдумывал мысль, не стоит ли мне как-то расслабить булки свою позицию про плагины #plugins, и про код, загружаемый в адресное пространство процесса.

Например, разрешив писать плагины для какого-то безопасного представления, типа #wasm.

В целом, идея звучит здраво, скажем, более здраво, чем загрузить случайную .so в себя, но, как мне кажется, пока недостаточно здраво:

* Если ты влинковываешь JIT в себя, то у тебя, скорее всего, поверхность взаимодействия с внешним кодом увеличивается, а не уменьшается. А в то, что этот jit будет без багов, я не очень верю.

* wasm пока довольно lightweight, но почему он через 5 лет не станет очередной JVM, не очень понятно. Стали ли бы вы к себе влинковывать JVM, чтобы безопасно исполнять плагины?

* Даже если предположить, что JIT будет не влинкован в каждое приложение, а будет общесистемный демон, который по bytecode будет возвращать объектный код, то, все равно, такой объектный код все равно опаснее, чем интерпретация, или запуск в отельном процессе.

Короче, хорошо, но, КМК, недостаточно хорошо.

Какой-нибудь очень простой wasm-интерпретатор, для не критичных к CPU блоков кода, мне кажется более интересным.

Ну и, если вы браузер, и уже притащили к себе wasm jit, то почему бы вам не скомпилировать просмотрщик PDF в WASM? Вот в этом не вижу ничего плохого, только хорошее. Или, если пофантазировать, то отказаться от текущей модели браузеров(процесс на страницу), и просто весь браузер собрать в безопасный wasm.

А лично я пока продолжаю считать, что отдельный процесс на плагин - наше все.
🔥8👍1
https://daniel.haxx.se/blog/2022/08/12/the-dream-of-auto-detecting-proxies/

Вот тут вот автор curl расписал, почему он не хочет к себе тащить зависимость от libproxy. Давно про нее хотел написать, вот, появился повод.

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

Потому что, в попытке решить простую проблему, добавляет в код кучу новых:

* #plugins Плагинная архитектура - куча загружаемых модулей, каждый под свой DE. Заменяем проблему поиска прокси в DE на поиск плагина для этого DE. Чем это плохо, много раз писал.

* Удивительный факт - плагины используются не по месту! По месу было бы, если бы плагины линковались с библиотеками этого DE, и тогда, действительно, имело бы смысл не загружать в себя чужеродный event loop. Проблема в том, что плагины не линкуются с кодом, а дергают subprocess - https://github.com/libproxy/libproxy/blob/master/libproxy/modules/config_kde.cpp#L47 Собственно, это вторая проблема - плагин дергает fork(), чего нельз делать в библиотеке общего назначения.

* Просто код всратого качество - какие-то плагины ловят исключения - https://github.com/libproxy/libproxy/blob/master/libproxy/modules/config_kde.cpp#L56, какие-то - нет. https://github.com/libproxy/libproxy/blob/master/libproxy/modules/config_gnome3.cpp#L130

* Велосипедизм. https://github.com/libproxy/libproxy/blob/master/libproxy/modules/config_gnome3.cpp#L61 - реализация popen2, плохого качества.

Короче, всячески НЕ рекомендую.

Как надо? Надо, конечно, узнавать это через dbus, через xdg portal. Или через переменные среды. Но уж точно не так.
🔥6👍4🤔1😱1
#plugins

https://github.com/stal-ix/ix/blob/main/pkgs/bin/gthumb/unwrap/ix.sh#L9 - пример достаточно редкой неудачи, когда я пока так и не смог побороть родную сборку, и получить из нее статически слинкованный артефакт.

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

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

А сами зависимые плагины содержат пересекающиеся друг с другом по именам символы, которые надо как-то скрыть, или переименовать, чтобы можно было слинковать в одной единице трансляции. А использовать уже существующие механизмы(например, добавить префикс ко всем именам в .so) не получается, потому что, как выше написал, некоторые символы таки общие.

Подобрать подходящий режим сборки пока не вышло. Печаль, беда.
😱6👍3👎1😁1👌1😨1
commit -m "better"
В батле "статическая vs. динамическая линковка" есть один фактор, про который особо никто не рассказывает, ну или мне просто не встречалось раньше. Это эстетика! Причем не простая эстетика, что, дескать, в случае статической линковки по всей fs не валяются…
https://www.opennet.ru/opennews/art.shtml?num=59469

TL;DR - эксплуатируется дыра в ssh-agent, позволяющая получить доступ к вашей системе, если вы куда-то прокинули свой ssh agent.

Дыра, конечно, попадает в мой золотой список историй, про "почему же не надо в динамическую линковку", потому что способ эксплуатации - триггерить загрузку плагинов #plugins этим самым ssh-agent в нужном порядке:

"Изначально возможность загрузки разделяемых библиотек не рассматривалась как угроза безопасности, так как загрузка возможна только из системных каталогов /usr/lib*, в которых находятся официально поставляемые дистрибутивом библиотеки, а операции с данными библиотеками ограничены вызовом функций dlopen() и dlclose(), без обращения к функциям библиотек. Тем не менее, было упущено из виду, что некоторые библиотеки имеют функции-конструкторы и деструкторы, автоматически вызываемые при выполнении операций dlopen() и dlclose(). Этого может быть достаточно, чтобы подобрать нужные библиотеки и организовать удалённое выполнение кода"

Ну и самая мякотка:

"Всего в поставке Ubuntu выявлено 58 библиотек, делающих стек исполняемым при вызове dlopen() и оставляющих его в таком состоянии после вызова dlclose(); ...; 9 библиотек регистрируют обработчик SIGSEGV при вызове dlopen() и оставляют его после вызова dlclose(); 2 библиотеки регистрируют обработчик SIGABRT при вызове dlopen()"

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

Не используйте.
👍16🔥8🤡4🤔3😱1
commit -m "better"
Вышел python 3.12 Думаю, самая крутая его фишка - это https://docs.python.org/3.12/howto/perf_profiling.html#perf-profiling Одной строкой - интеграция с perf record/report. Да, да, в python появился нормальный профайлер! Тут, конечно, можно устроить срач…
#rant

Каждая мажорная версия питона ломает сборку статически слинкованных в интерпретатор модулей, каким-нибудь новым и интересным способом.

Вот, и 3.12 версия - не исключение.

Система сборки стала игнорировать *disabled* модули в Setup.* - https://github.com/python/cpython/blob/main/Modules/Setup#L19-L21

Теперь, вместо того, чтобы отменить сборку этого модуля, как работало "всегда", принудительно собирается динамически слинкованный модуль.

Как я когда-то уже шутил, мне кажется, что авторы некоторых OSS проектов зарабатывают деньги на том, что готовят желающим сборки без всех этих извращений с динамическими #plugins.

Иначе я это объяснить не могу.

Ладно, конечно могу - всем просто похер на этот механизм, вот он и ломается, почем зря.

К счастью, мой враппер над компилятором давно, и с легкостью, справляется с такой засадой (он просто собирает .a из тех же .o, вместо .so) - https://github.com/pg83/ix/blob/main/pkgs/lib/python/3/12/ix.sh#L19

Еще они украли к себе в исходники какую-то более хорошую модную автоматически верифицируемую реализацию хеш-функций (https://github.com/python/cpython/tree/main/Modules/_hacl), а вот addincl не сделали, пришлось сделать самому - https://github.com/pg83/ix/blob/main/pkgs/lib/python/3/12/ix.sh#L14

Снова похвастаюсь своими сборочными файлами - https://github.com/pg83/ix/blob/main/pkgs/lib/python/3/12/ix.sh

Мне кажется, вот этот вот способ описания каждой следующей версии продукта как маленькое инкрементальное изменение сборки предыдущей версии - это очень удобно, изящно, и отражает ход мыслей. О как.
🔥127👍4👌2🐳2
commit -m "better"
#rant #cosmic Сподобился собрать https://lapce.dev/, просто чтобы позырить на GUI в Rust. Вот, оно падает, с очень похожей диагностикой на cosmic-term, не совсем в том же месте, но по коду где-то рядом, не может найти шрифт: https://gist.github.com/pg8…
#rant, #plugins

https://www.opennet.ru/opennews/art.shtml?num=61948

Я, знаете ли, иногда поругиваюсь на #cosmic, и на то, что его пишут пионеры, но, на самом деле, очень пристально слежу за проектом, постепенно собираю его запчасти, и пробую использовать IRL.

Почему?

Потому что:

* Не на С. Будет падать не так часто.

* Без legacy GUI (GTK/QT - и то, и то, - говно лютое)

* И, самое важное, без всратых плагинов. Так уж получилось, что, в среде golang/rust, принято расширять программы не через dlopen(), а через что-то типа embedded scripting lang (e.g lua), или через subprocess + lightweight rpc (e.g \n-delimited json). Мне это безумно нравится, потому что это вполне aligned с тем, как я считаю "хорошо" и "правильно" (оценочное суждение, да).

К сожалению, несмотря на заявления, оно довольно жестко гвоздями прибито к PopOS, и у меня, например, пока не получилось заставить работать их wayland compositor, хотя собрать его получилось вполне.

Ждем, надеемся.
👍206🔥2🆒1
commit -m "better"
Снова про #mesa В цитируемом посте я писал, как ловко запилил процедуры "вычитания" одной статической библиотеки из другой, и почему мне пришлось так делать для сборки mesa. К сожалению, эта процедура оказалась не очень "робастной" (то есть, апдейт на новую…
Будни #bootstrap, #mesa, #opengl

В https://t.iss.one/itpgchannel/1350 писал про то, как ловко я обошелся с плагинной системой Mesa.

Все шло хорошо, пока разработчики mesa не решили перестать жить во грехе (это когда они делали вид, что отдельные их драйвера - это #plugins, которые как бы не зависят от ядра, и могут быть загружены в runtime), и начали жить как все нормальные люди.

В релизе 24.2.X, они, тихо и незаметно (ну или я не нашел в changelog), стали линковаться с libgallium.so, вместо того, чтобы загружать ее, как драйвер.

Кажется, я должен был быть очень доволен, всратых плагинов стало меньше?

С одной стороны, да, а с другой - я уже привык к тому, что сборка mesa в два этапа (отдельно ядро, и отдельно драйвера) позволяет мне делать зависимость от драйверов только у конечных программ, а не у всего кода, которому зачем-то нужно скомпилироваться с заголовками от opengl, но в runtime opengl не используется. Ну и cache hit так при сборке больше.

Поэтому я взял да и плагинифицировал эту часть mesa взад.

Собственно, это было очень просто, ядро mesa зависит от от libgallium.so всего по одной функции - https://github.com/pg83/ix/commit/04c0c3c9d6392089f2ea452d70c354cf22ae1c0f#diff-028186b4b1abb1353b6639ea94857e1aa9c5a91debd070b864799052bb502644R5 Раньше она загружалась через dlopen, а сейчас связывается во время линковки.

Ну так я и запилил stub, который вызывает dlopen (который, напомню, у меня не настоящий dlopen, а статически слинкованная фабрика - https://t.iss.one/itpgchannel/1230), чтобы все работало "как раньше", и чтобы можно было связать драйвер с приложением только в момент линковки этого приложения!
😁13👍7🤡6🐳3🔥2
commit -m "better"
В релизе 24.2.X, они, тихо и незаметно (ну или я не нашел в changelog), стали линковаться с libgallium.so, вместо того, чтобы загружать ее, как драйвер.
В 24.3.X основной код и libgallium.so проникли друг в друга еще больше, и разделить loader и driver больше не получается. Что самое интересное, несмотря на это, mesa продолжает подгружать какие-то запчасти через dlopen #plugins. Надеюсь, они понимают, что делают, потому что, со стороны, это выглядит как перекладывание из пустого в порожнее.

Поэтому я сегодня грустный панда, #mesa стала пересобираться существенно чаще.

Задумался про то, чтобы запилить кастомный opengl loader, по типу https://github.com/anholt/libepoxy, или https://github.com/NVIDIA/libglvnd, только попроще, чтобы продолжать собирать код с таким вот loader, и делать зависимость на конкретную реализацию только в конечных приложениях.
👍54🤔4😢2
#gold

> Одмен, а в чем прикол делать дистр с фулл статик линковкой? У тебя пост на канальчике про это есть какой-нить?

У меня про это много чего написано, достаточно погрепать канал по "статическая".

В целом, аргументация такая:

* динлинковка - это вынужденная мера, появившаяся, когда у компухтеров было мало памяти
* динамическая линковка - сложнее, тулинг хуже (санитайзеры требуют, чтобы почти весь код (кроме того, что перехватывается), был собран статически использовать msan с кучей .so - заградительно сложно, отладчик работает хуже, код ходит через GOT/plt, а не напрямую).
* динамическая линковка - сложнее, например, во взаимодействии с другими системами (fork(), threads, tls, etc)
* динамический загрузчик - сложный, а еще он #suid, есть известные проблемы с безопасностью
* плагины лежат хз где, и часто их не хватает, потому что приложения не могут сказать, чтобы в gstreamer был такой-то #plugins
* в целом, загружать в runtime сторонний код в свое приложение (не в песочнице) - очень странная идея, потому что CI с ним, у вас, скорее всего, не было, и как он будет ездить по вашим данным - неизвестно. Для плагинов сейчас норм решение - #WebAssembly в песочнице, или там https://github.com/libriscv/libriscv
* code bloat, больше поверхность для rop
* #ABI - это бич C/C++
* #perf - 5 - 10% CPU на дороге не валяются
* динамически слинкованные бинари дольше запускаются

В общем, я не за статлинковку, я против динамической.

Статлинковка простая, как 5 копеек, и современные окружения (go, rust) это понимают.
👍606🤡6🔥4🤔3🗿2
https://www.opennet.ru/opennews/art.shtml?num=63182

"Подход к обработке ошибок в Nimony претерпел значительные изменения. Автор Nim выражает неудовлетворённость традиционными механизмами исключений и их эмуляцией через алгебраические типы данных (sum types). Вместо этого предлагается концепция интеграции состояния ошибки непосредственно в сам объект данных. В качестве примеров приводятся: представление ошибки в потоках ввода-вывода через специальное состояние, использование NaN для чисел с плавающей запятой, или low(int) для невалидных целочисленных значений. В случаях, когда объект не может инкапсулировать состояние ошибки, предлагается использовать потоко-локальную (thread-local) переменную для сигнализации"

Эх, забавный был язык, я даже хотел написать на нем пару программок для #stal/IX, но его автор, очевидным образом, сошел с ума - говорит, в каждом типе данных должен быть особый sentinel.

Это уже не говоря про то, что он хочет уметь расширять синтаксис загружаемыми #plugins!
🤡107😁5🤔3🆒2
https://www.opennet.ru/opennews/art.shtml?num=63505

"Проблема вызвана тем, что при применении опции "-R" ("--chroot") для запуска команд в chroot-окружении с выбранным пользователем корневым каталогом, файл /etc/nsswitch.conf загружался в контексте нового корневого каталога, а не системного каталога. Так как пользователь может использовать в качестве корневого каталога для chroot собственный каталог, он может разместить в нём файл конфигурации nsswitch.conf. Контролируя загружаемый подсистемой NSS (Name Service Switch) файл /etc/nsswitch.conf, пользователь может добавить в него настройки, приводящие к вызову дополнительных обработчиков. Подобные обработчики загружаются NSS в форме разделяемых библиотек, которые также можно разместить в подконтрольном пользователю каталоге. Подставив свою библиотеку пользователь может добиться выполнения из неё кода с правами root, так как обработка NSS производится до сброса привилегий"

Все, как я люблю - #plugins + #suid == бабах!
25🔥4🆒2👍1