Всё не получается найти время написать про все выходы после возврата с Киргизии: то времени нет, то “вдохновения”, то ещё чего. Хотя иногда интересные моменты проглядывают. Поэтому решил описать всё одной заметкой, кратенько.
Итак…
Пролог
Киригизия началась для меня относительно спонтанно. Это если смотреть на то, как готовились к другим походам, когда билеты покупались уже в январе, а вся основная канва была ясна и понятна к концу осени предыдущего года.
Тут же март месяц, в группе «ПВД анонсы» сообщение от Вовы с которым единожды ходил на г.Мечта под руководством Зелёного осенью прошлого (2024) года… Мысли начали делать жуууууу в голове. Робко уточняю количество мест (планируется передвижение на авто, поэтому число участников ограничено 4 персонами), но оказывается, что желающих пока только два: собственно Вова и Даша. С Дашей тоже ходили только Мечту и (склероз хорошая болезнь: каждый день новости), как оказалось позже, встречали вместе 2024 НГ на Фалазе с GT.
Но желание куда-то, особенно в новый район, выбраться на фоне тотального оскуднения собственной фантазии, всё же взяло верх. Решаюсь и вписываюсь.
Просто заметка, что бы самому потом не потерять.
Руководство для отладки потоков в RTOS NuttX:
Отмечу, что последние версии GDB и OpenOCD включают весь необходимый софт для работы. А если грузить ELF как-то так:
arm-none-eabi-gdb main.elf \
-ex "target extended-remote | openocd -f interface/stlink.cfg -f ${OPENOCD_CFG} -c 'gdb_port pipe' -c '\$_CHIPNAME.cpu0 configure -rtos nuttx'" -x openocd_nuttx_gdb.rc
То содержимое openocd_nuttx_gdb.rc стоит сделать таким:
define hookpost-file
eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid
eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs
eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
end
eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid
eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs
eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
т.е. что бы и хуком на команду file сработало и сразу же отработало. Как будет более красивое решение - подправлю.
Ещё остался не опробованным вариант отладки с включенной PROCFS и скриптом nuttx/tools/pynuttx/gdbinit.py из поставки NuttX.
Две очень хорошие статьи, что бы расставить точки над i:
Тезисно:
- Все спутники передают два типа данных: альманах и эфемерис.
- Альманах содержит данные всех спутников. Каждый спутник передаёт альманах для всех спутников. Но точность низкая. Действителен до нескольких месяцев.
- Эфемерис содержит точные корректировки орбиты и часов конкретного спутника. Каждый спутник передаёт только свои данные. Данные действительны около 30 минут, передаются каждые 30 сек.
- Эфемериды - содержимое эфемериса и альманаха. Т.е. это те самые параметры орбиты и ухода часов конкретного спутника, позволяющие определить его местоположение в зависимости от времени.
- Горячий старт: когда выключили и включили устройство в пределах 30 минут, когда эфемерисы ещё не протухли.
- Тёплый старт: когда устройство было выключено более 30 минут, эфемерисы успели протухнуть, навигатор ищет спутники по альманаху.
- Холодный старт: сбой часов, оооочень долгое отключение или перемещение навигатора на большое расстояние в выключенном состоянии. Альманах протух, идёт “поиск неба” (переинициализация).
Дополнительно:
Проблема: после вывода ноутбука в сон и последующего пробуждения FFmpeg выдаёт примерно следующее:
[AVHWDeviceContext @ 0x55ec837f1800] cu->cuInit(0) failed -> CUDA_ERROR_UNKNOWN: unknown error Device creation failed: -1313558101.
Команда у меня такая:
ffmpeg -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i INPUT.mkv -c:a mp3 -c:v h264_nvenc -profile baseline -y OUTPUT.mkv
С аналогичной ошибкой отваливается и Kdenlive при попытке использовать аппаратный кодек.
Как оказалось,
ошибка известная (
и на форуме nVidia), там же можно найти WA:
This bug disappears after running nvidia-bug-report.sh for some reason, CUDA works again after running nvidia-bug-report.sh.
Edit: After more research I found out that running nvidia-settings as root somehow fixes the problem.
Edit 2: Loading the nvidia-uvm module though modprobe nvidia-uvm fixes this issue
Схожая проблема.
WA:
sudo modprobe -r nvidia_uvm
sudo modprobe nvidia_uvm
Я засунул эти команды в suspend-hook Systemd:
sudo systemctl edit --force --full nvidia-uvm-wa-sleep.service
Содержимое:
[Unit]
Description=nVidia UVM suspend bug WA
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart= modprobe -r nvidia_uvm
ExecStop= modprobe nvidia_uvm
[Install]
WantedBy=sleep.target
Включить:
sudo systemctl enable nvidia-uvm-wa-sleep.service
Содержимое юнита по мотивам:
Самостоятельное осмысление навеянное
https://t.me/grokaemcpp/627.
Не задумывался над сценариями использования, хотя они есть с C++11.
Раньше была возможность использовать квалификатор const:
struct Foo {
void method(); // (1)
void method() const; // (2)
};
Тут вроде логично, когда какой метод будет вызван.
C++11 добавил возможность пометить метод квалификатором ссылочности: ref-qualified:
&
const&
&&
const&& - хотят это сценарий очень странный.
Первое, что нужно отметить, что если хотя бы один из них определён, то он кофликтует с (1) и (2). Т.е. у вас или ref-qualified или non-ref-qualified:
struct Foo {
#if 0
void method(); // (1)
void method() const; // (2)
#else
void method() &; // (3)
void method() const&; // (4)
void method() &&; // (5)
void method() const&&; // (6)
#endif
};
Второе: что и когда вызывается (или - ниже обозначает, два случая, для сравнения: когда использует и когда не используется ref-квалификация ):
Foo foo;
foo.method(); // (а) вызовется или (1) или (3), либо ОШИБКА, если перегрузка не указана
const Foo const_foo;
const_foo.method() // (б) вызовется или (2) или (4), либо ОШИБКА, если перегрузка не указана
Foo{}.method(); // (в) вызовется или (1) или (5), либо (4), если перегрузка не указана
(const Foo){}.method(); // (г) вызовется или (2) или (6), либо (4), если перегрузка не указана
Тут логика такая: есть имя - вызовется &, нет имени - вызовется &&. И стоит внимательно посмотреть кейсы (в) и (г) для “старого” поведения и нового, но когда перегрузка по && не указана.
Третье: перегрузки могут быть помечены delete: удалённые функции тоже используются в поиске перегрузок и, если наиболее подходящая перегрузка удалена - будет ошибка компиляции.
Ну и для чего может быть нужно: оптимизации и защита. К примеру, если мы вызвали && метод, то мы точно знаем, что мы - временный объект. поэтому, мы можем сделать не просто возврат чего-то, а сделать этому std::move(), пометить метод delete и запретить вызваться или вернуть копию, а не ссылку или указатель.
Другой пример: висячие ссылки или другие отсылки к уничтоженным ресурсам.
struct Bar {
std::string _val;
#if 0
std::string_view get() const { return _val; } // (7)
#else
std::string_view get() const& { return _val; } // (8)
std::string get() && { return _val; } // (9) - можно и std::move(_val), но зависит от
endif
};
Тут вместо std::string_view может быть const std::string&, но со string_view можно проще отловить ситуацию с доступом к уничтоженному объекту:
// как помощиник
Bar request() {
return Bar{};
}
...
auto sv = request().get(); // (д)
some_function(sv); // (е)
Здесь без ref-qualified методов в (д) будет вызван (7), что приведёт в (е) и дальше по коду к обращению к уничтоженному объекту Bar::_val.
При использовании перегрузок по ref-qualified, будет вызван (9) и мы вернём копию строки (или более оптимально, если через std::move(_val)).
Отсюда, имхо, основное применение: если возвращаем некий референс (ссылку, view/span) на внутреннюю структуру класса, то имеет смысл использовать указание ссылочных квалификаторов, причём обоих: & и && - второй будет уточнять поведение для временного объекта. Если уточнения по поведение не нужно, то использование ссылочных квалификаторов избыточно (но смотреть кейсы кейсы (в) и (г)) .
На правах мемориза.
LocalSend (
официальный сайт) - удобный инструмент для обмена файлами между устройствами в локальной сети без подготовленной инфраструктуры. Что примечательно - open source.
Мне потребовалось что бы быстро перекидывать файлы между несколькими андроидами и ноутбуком на Linux. Для своих персональных устройств я использую давно
KDE Connect, но привязывать “левые” устройства и потом каждый раз отвязывать - не добно. А вот LocalSend решает.
Для полноты картины, обсуждение на 4PDA:
На андроид можно поставить их Google Play, F-Droid и ручками APK. На Manjaro - есть в AUR.
Просто заметка по версиям.
В AnyDesk есть возможность туннелирования TCP. Да, вот прям как в SSH. Очень удобно для использования в “чужом” или неподготовленном окружении. Использовал, например, для удалённой отладки кода на устройствах очень сильно далеко от меня (вплоть до другого континента)
Доступна в бесплатной версии, но с нюансом:
- до версии 6.2.1 включительно оно доступно из коробки
- после, доступно только после регистрации аккаунта (?)
При этом версия 6.2.1 пока работает. FYI.
Ну и сразу. Есть
RustDesk. Возможности форвардинга есть. Плюс можно свой сервер разворачивать. В реальных условиях пока не проверял.
Не стартует удалённая отладка. Причём без какого-то фидбека.
Если включить логи:
export QT_LOGGING_RULES='*=true;qt.*=false;qtc.*=true;qtc.clang*=true'
и запустить сессию QtC, то при запуске отладки можно увидеть что-то вроде:
qtc.utils.process: Process 162 starting (non blocking, main thread): --multi :10000
qtc.utils.process: Process 162 finished: result=3, ex=255, 0 bytes stdout: "", 0 bytes stderr: "", 0 ms elapsed
Суть проблемы в том, что на удалённой стороне просто не установлен gdbserver. Соответственно нужно его установить и всё починится.
Как минимум на версии 16.x проблема присутствует. Как и на 17.0.0-beta1 (16.0.82). Проблема определена в переписке.
Веб-сервисы вещь хорошая и удобная… Пока их не блокируют. Поэтому предпочитаю для своих домашний поделок использовать KiCAD. Естественно, что не всегда хватает какого-то символа, посадочного места или 3D вида компонента. При этом в той же EasyEDA есть куча оных уже в готовом виде. Если не вдаваться в подробности соответствия каким-то стандартам, то было бы неплохо, стащить оную и использовать у себя.
Первым тулом, которым я пользовался был (да и останется на всякий случай) -
lc2kicad поставить, пока, можно из AUR:
но репозиторий уже в архиве, а автор отписался, что проект всё.
И вот сегодня открыл для себя новый проект:
easyeda2kicad.
И основная его фишка в том, что по указанному ID он может скачать сразу символ, посадочное место и 3D модель. Положить это в единое место к которому можно настроить пути и потом пользоваться централизованно.
Столкнулся с проблемой: при печати из Inkscape изображения получаются очень мелкими.
Гуглинг
навёл на то, что это проблема с xdg-desktop-portal-kde. Парень из форма создал
Bug Report в котором есть возможный WA. И там же есть отсылка на
репорт в самом проекте Inkscape.
Если коротко: xdg-desktop-portal это некая сущность (или сучность?) которая позволяет приложениям на различных тулкитах более бесшовно интегрироваться в “неродные” окружения рабочего стола: Gtk в окружение KDE и Qt в окружения на базе Gtk (Gnome, Cinnamon, Mate & etc). Интеграция по большей части затрагивает только переиспользование стандартных системных диалогов, типа диалогов открытия файлов, сохранения, вывода окон предупреждений, диалогов печати (тут отдельный акцент). В общем, все те вещи, которые вроде более приятны глазу, но жить без них можно (“вам шашечки или ехать?”). Но и дополнительный слой абстракции, который сам по себе может нести баги.
Собственно проблема как раз и заключается в стыке разных сред при использовании диалога печати. Причём
сначала поддержку Desktop Portal реализовали в Inkscape и сразу же это вызвало
проблемы.
Ладно, теперь к сути. Мне ехать нужно. Решение в лоб это общесистемно заявить:
Собственно после чего все приложения Gtk в окружении KDE станут использовать Gtk диалоги. Как оказалось, если использовать в массе, так себе. К визуалу тоже быстро привыкаешь :)
Поэтому достаточно сделать следующее:
- Меню
- Находим Inkscape
- ПКМ → Изменить приложение…
- Вкладка Приложение
- В поле “Переменные окружения” вставляем
GTK_USE_PORTAL=0
- OK
Теперь:
- если открыть Inkscape через меню или быстрый запуск, он запустится с этим значением
- если открыть SVG файл через Dolphin, то он тоже откроется с этим флагом
Если открывать через терминал ручками: inkscape file.svg, то имеет смысл завести alias с установкой переменной окружения в нужное значение. Если в скриптах (хммм), то указать явно в скрипте.
Когда ходили
нонстоп после нефтебазы немного не туда сунулись по пути на Капитанский мостик, но возникло жаление по осени прогуляться тут с сыном, просто посмотреть, куда идут дороги. Сентябрь пришёл, время реализовывать планы. Что бы долго не тянуть выбрали 7 сентября.

Внезапный поход на вершину, которую ещё не доводилось сходить. Сходили 17-18 августа, но руки написать дошли только сейчас.

С праздником всех причастных!
Век живи, век учись, а дураком помрёшь.
Открыл для себя чудную утилиту timeout из состава coreutils.
Делает ровно то, что описывает её название: запускает команду, переданную как аргумент, на заданное время в секундах (s), минутах (m), часах (h) или днях (d):
timeout 10s ping ya.ru
sudo timeout 10s tcpdump -i wlan0 -Q in -A udp
Обратите внимание: если команда должна быть выполнена под sudo, то sudo должно стоять перед timeout.
По истечении таймаута передаётся сигнал TERM в дочерний процесс. Если нужен другой, то укажите его через аргумент -s SIGNAL. Утилита дополнительно может послать сигнал KILL, если команда не отреагировала на сигнал TERM по истечении таймаута, указанного через параметр -k TIMEOUT. Прочие вкусности смотреть через --help, хотя их там, по большей части, и нет.