Системы по загрузке плагинов делятся на: #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 уровней косвенности. Так и живем.
* "Нормальные"
Точка входа в 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 уровней косвенности. Так и живем.
GitHub
glib-networking/tls/gnutls/gtlsbackend-gnutls.c at master · GNOME/glib-networking
Read-only mirror of https://gitlab.gnome.org/GNOME/glib-networking - GNOME/glib-networking
🔥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/. Хороший, древний, проверенный код, без изъебов.
Код чуть младше меня.
Замечания по ходу процесса:
* Пришлось сделать 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 так много свободных рук.
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
Решил я себе собрать какой-нить не-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
GitHub
wayfire/src/api/wayfire/plugin.hpp at master · WayfireWM/wayfire
A modular and extensible wayland compositor. Contribute to WayfireWM/wayfire development by creating an account on GitHub.
👍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
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
Collabora | Open Source Consulting
Generate a minimal GStreamer build, tailored to your needs
Thanks to a partnership with Huawei, you can now use gst-build to generate a minimal GStreamer build, tailored to a specific application, or set of applications. Here's how.
🔥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 в первый раз, для коллекционирования плагинов, а потом сборку во второй раз, с подготовленной фабрикой из этих плагинов. Признаться, мне это не очень интересно, да и полезность не очень понятна.
У меня сейчас не собрано ни одного 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 в первый раз, для коллекционирования плагинов, а потом сборку во второй раз, с подготовленной фабрикой из этих плагинов. Признаться, мне это не очень интересно, да и полезность не очень понятна.
api.kde.org
KParts - Main Page
KDE products API documentation
👍8
Я тут какое-то время обдумывал мысль, не стоит ли мне как-то расслабить булки свою позицию про плагины #plugins, и про код, загружаемый в адресное пространство процесса.
Например, разрешив писать плагины для какого-то безопасного представления, типа #wasm.
В целом, идея звучит здраво, скажем, более здраво, чем загрузить случайную .so в себя, но, как мне кажется, пока недостаточно здраво:
* Если ты влинковываешь JIT в себя, то у тебя, скорее всего, поверхность взаимодействия с внешним кодом увеличивается, а не уменьшается. А в то, что этот jit будет без багов, я не очень верю.
* wasm пока довольно lightweight, но почему он через 5 лет не станет очередной JVM, не очень понятно. Стали ли бы вы к себе влинковывать JVM, чтобы безопасно исполнять плагины?
* Даже если предположить, что JIT будет не влинкован в каждое приложение, а будет общесистемный демон, который по bytecode будет возвращать объектный код, то, все равно, такой объектный код все равно опаснее, чем интерпретация, или запуск в отельном процессе.
Короче, хорошо, но, КМК, недостаточно хорошо.
Какой-нибудь очень простой wasm-интерпретатор, для не критичных к CPU блоков кода, мне кажется более интересным.
Ну и, если вы браузер, и уже притащили к себе wasm jit, то почему бы вам не скомпилировать просмотрщик PDF в WASM? Вот в этом не вижу ничего плохого, только хорошее. Или, если пофантазировать, то отказаться от текущей модели браузеров(процесс на страницу), и просто весь браузер собрать в безопасный wasm.
А лично я пока продолжаю считать, что отдельный процесс на плагин - наше все.
Например, разрешив писать плагины для какого-то безопасного представления, типа #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. Или через переменные среды. Но уж точно не так.
Вот тут вот автор 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) не получается, потому что, как выше написал, некоторые символы таки общие.
Подобрать подходящий режим сборки пока не вышло. Печаль, беда.
https://github.com/stal-ix/ix/blob/main/pkgs/bin/gthumb/unwrap/ix.sh#L9 - пример достаточно редкой неудачи, когда я пока так и не смог побороть родную сборку, и получить из нее статически слинкованный артефакт.
Я даже не знаю, как прокомментировать тот бред, который я написал в сборке, могу только высокоуровнево объяснить проблему.
Там используется очень встратый способ загрузки плагинов, когда символы из плагинов становятся доступны следующим загружаемым плагинам, я такого еще не встречал. Это, реально, не разложенная на .so фабрика, а вот так вот, по рабоче-крестьянски распиханное единое приложение по нескольким .so.
А сами зависимые плагины содержат пересекающиеся друг с другом по именам символы, которые надо как-то скрыть, или переименовать, чтобы можно было слинковать в одной единице трансляции. А использовать уже существующие механизмы(например, добавить префикс ко всем именам в .so) не получается, потому что, как выше написал, некоторые символы таки общие.
Подобрать подходящий режим сборки пока не вышло. Печаль, беда.
GitHub
ix/pkgs/bin/gthumb/unwrap/ix.sh at main · stal-ix/ix
ix package manager. Contribute to stal-ix/ix development by creating an account on GitHub.
😱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()"
Динамическая загрузка исполняемого кода - это слишком сложный и хрупкий механизм, чтобы его можно было использовать корректно.
Не используйте.
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()"
Динамическая загрузка исполняемого кода - это слишком сложный и хрупкий механизм, чтобы его можно было использовать корректно.
Не используйте.
www.opennet.ru
Удалённо эксплуатируемая уязвимость в OpenSSH ssh-agent
Компания Qualys выявила удалённо эксплуатируемую уязвимость (CVE-2023-38408) в реализации ssh-agent из состава OpenSSH, позволяющую выполнить код в системе, предоставившей доступ к ssh-agent для хоста на другом конце ssh-соединения. Совершение атаки возможно…
👍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
Мне кажется, вот этот вот способ описания каждой следующей версии продукта как маленькое инкрементальное изменение сборки предыдущей версии - это очень удобно, изящно, и отражает ход мыслей. О как.
Каждая мажорная версия питона ломает сборку статически слинкованных в интерпретатор модулей, каким-нибудь новым и интересным способом.
Вот, и 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/pg83/ix/blob/main/pkgs/lib/python/3/12/ix.sh
Мне кажется, вот этот вот способ описания каждой следующей версии продукта как маленькое инкрементальное изменение сборки предыдущей версии - это очень удобно, изящно, и отражает ход мыслей. О как.
GitHub
cpython/Modules/Setup at main · python/cpython
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.
🔥12❤7👍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, хотя собрать его получилось вполне.
Ждем, надеемся.
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, хотя собрать его получилось вполне.
Ждем, надеемся.
www.opennet.ru
Второй альфа-выпуск среды рабочего стола COSMIC
Компания System76, разрабатывающая Linux-дистрибутив Pop!_OS, начала тестирование второй альфа-версии среды рабочего стола COSMIC, написанной на языке Rust (не путать со старым COSMIC, который был основан на GNOME Shell). Для тестирования предложены iso-образы…
👍20❤6🔥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), чтобы все работало "как раньше", и чтобы можно было связать драйвер с приложением только в момент линковки этого приложения!
В 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), чтобы все работало "как раньше", и чтобы можно было связать драйвер с приложением только в момент линковки этого приложения!
Telegram
commit -m "better"
Снова про #mesa
В цитируемом посте я писал, как ловко запилил процедуры "вычитания" одной статической библиотеки из другой, и почему мне пришлось так делать для сборки mesa.
К сожалению, эта процедура оказалась не очень "робастной" (то есть, апдейт на новую…
В цитируемом посте я писал, как ловко запилил процедуры "вычитания" одной статической библиотеки из другой, и почему мне пришлось так делать для сборки mesa.
К сожалению, эта процедура оказалась не очень "робастной" (то есть, апдейт на новую…
😁13👍7🤡6🐳3🔥2
https://www.opennet.ru/opennews/art.shtml?num=62624
https://www.reddit.com/r/linux/comments/1iayzwm/orbitiny_desktop_environment_released_originally/
Гля какая красота!
Чувак, в одно рыло, запилил целое DE, да еще и на QT!
Осталось понять, есть ли там #plugins, и можно в прод!
https://www.reddit.com/r/linux/comments/1iayzwm/orbitiny_desktop_environment_released_originally/
Гля какая красота!
Чувак, в одно рыло, запилил целое DE, да еще и на QT!
Осталось понять, есть ли там #plugins, и можно в прод!
www.opennet.ru
Опубликована среда рабочего стола Orbitiny, использующая Qt
Представлена среда рабочего стола Orbitiny Desktop, написанная с нуля с использованием фреймворка Qt. Проект преподносится как попытка совместить некоторые инновационные идеи, которые раньше не встречались в пользовательских окружениях, с традиционными элементами…
😁18👍11🤔4
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, и делать зависимость на конкретную реализацию только в конечных приложениях.
Поэтому я сегодня грустный панда, #mesa стала пересобираться существенно чаще.
Задумался про то, чтобы запилить кастомный opengl loader, по типу https://github.com/anholt/libepoxy, или https://github.com/NVIDIA/libglvnd, только попроще, чтобы продолжать собирать код с таким вот loader, и делать зависимость на конкретную реализацию только в конечных приложениях.
GitHub
GitHub - anholt/libepoxy: Epoxy is a library for handling OpenGL function pointer management for you
Epoxy is a library for handling OpenGL function pointer management for you - anholt/libepoxy
👍5❤4🤔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) это понимают.
> Одмен, а в чем прикол делать дистр с фулл статик линковкой? У тебя пост на канальчике про это есть какой-нить?
У меня про это много чего написано, достаточно погрепать канал по "статическая".
В целом, аргументация такая:
* динлинковка - это вынужденная мера, появившаяся, когда у компухтеров было мало памяти
* динамическая линковка - сложнее, тулинг хуже (
* динамическая линковка - сложнее, например, во взаимодействии с другими системами (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) это понимают.
GitHub
GitHub - libriscv/libriscv: The fastest RISC-V sandbox
The fastest RISC-V sandbox. Contribute to libriscv/libriscv development by creating an account on GitHub.
👍60❤6🤡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!
"Подход к обработке ошибок в Nimony претерпел значительные изменения. Автор Nim выражает неудовлетворённость традиционными механизмами исключений и их эмуляцией через алгебраические типы данных (sum types). Вместо этого предлагается концепция интеграции состояния ошибки непосредственно в сам объект данных. В качестве примеров приводятся: представление ошибки в потоках ввода-вывода через специальное состояние, использование NaN для чисел с плавающей запятой, или low(int) для невалидных целочисленных значений. В случаях, когда объект не может инкапсулировать состояние ошибки, предлагается использовать потоко-локальную (thread-local) переменную для сигнализации"
Эх, забавный был язык, я даже хотел написать на нем пару программок для #stal/IX, но его автор, очевидным образом, сошел с ума - говорит, в каждом типе данных должен быть особый sentinel.
Это уже не говоря про то, что он хочет уметь расширять синтаксис загружаемыми #plugins!
www.opennet.ru
Представлены принципы дизайна компилятора Nimony для будущего Nim 3.0
В процессе разработки языка программирования Nim 3.0 развивается новый компилятор Nimony, основополагающим принципом проектирования которого является достижение предсказуемости времени выполнения в худшем случае (Worst Case Execution Time, WCET). Это требование…
🤡10❤7😁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 == бабах!
"Проблема вызвана тем, что при применении опции "-R" ("--chroot") для запуска команд в chroot-окружении с выбранным пользователем корневым каталогом, файл /etc/nsswitch.conf загружался в контексте нового корневого каталога, а не системного каталога. Так как пользователь может использовать в качестве корневого каталога для chroot собственный каталог, он может разместить в нём файл конфигурации nsswitch.conf. Контролируя загружаемый подсистемой NSS (Name Service Switch) файл /etc/nsswitch.conf, пользователь может добавить в него настройки, приводящие к вызову дополнительных обработчиков. Подобные обработчики загружаются NSS в форме разделяемых библиотек, которые также можно разместить в подконтрольном пользователю каталоге. Подставив свою библиотеку пользователь может добиться выполнения из неё кода с правами root, так как обработка NSS производится до сброса привилегий"
Все, как я люблю - #plugins + #suid == бабах!
www.opennet.ru
Уязвимости в утилите sudo, позволяющие получить права root в системе
В пакете sudo, применяемом для организации выполнения команд от имени других пользователей, выявлена уязвимость (CVE-2025-32463), позволяющая любому непривилегированному пользователю выполнить код с правами root, даже если пользователь не упомянут в конфигурации…
❤25🔥4🆒2👍1