Files
cuframes/docs/troubleshooting.md
gx fbe1d18c39 docs: troubleshooting guide + production notes
- docs/troubleshooting.md — 13 секций с реальными grабельками которые мы
  прошли: cudaIpcOpenEventHandle invalid device context (pid namespace),
  s6-overlay vs pid share, scale_cuda missing (cuda-llvm + stdbit.h glibc 2.36),
  libcuframes not found install paths, ffbuild/ missing source, GMP no working
  compiler (long-long reliability), zlib.net deprecated URL, RTSP/RTP UDP
  docker NAT, gitea actions Node version
- docs/architecture.md — Appendix A "Production deployment notes" с реальными
  observations после 24h+ run: что подтвердилось, что доработали, что не учли
- docs/requirements.md — production deployment matrix + Docker namespace
  requirements таблица (cross-container CUDA IPC требует 5 условий)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 00:37:13 +01:00

16 KiB
Raw Permalink Blame History

Troubleshooting

Реальные грабли которые мы прошли при первой production deployment'е cuframes (Frigate + custom C++ processor + custom Python). Документировано чтобы вы их не повторяли.

Содержание


Runtime / CUDA IPC

cudaIpcOpenEventHandle: invalid device context

Симптом: subscriber сразу после cuframes_subscriber_create падает с этой ошибкой.

Причина: CUDA driver проверяет IPC peer через /proc/<pid>/.... Если процесс publisher'а не виден в PID namespace consumer'а — context считается невалидным.

Fix: shared PID namespace.

Docker:

consumer:
  ipc: "container:<publisher>"   # shared /dev/shm
  pid: "container:<publisher>"   # ← вот это критично, без него fail

Host process: запуск consumer'а на host'е (либо publisher'а на host'е тоже) — same default namespace.

Caveat: если consumer image использует s6-overlay (Frigate, linuxserver.io images) — pid: container: несовместим (см. соответствующую секцию).

Subscriber timeout

Симптом: cuframes_subscriber_create: timeout без других ошибок.

Причины (в порядке вероятности):

  1. /run/cuframes/<key>.sock не виден consumer'у — забыли volume-mount
  2. /run/cuframes смонтирован, но publisher ещё не успел создать socket — увеличить connect_timeout_ms
  3. Publisher запущен, socket есть, но permission denied — см. ниже

Permission denied на socket

Симптом: socket виден через ls -la /run/cuframes/, owner root. Consumer process — non-root user → не может connect().

Fix:

  • Запустить consumer как root: user: root в compose
  • Либо изменить permissions socket после создания (publisher delegation) — TBD в v0.2

Frigate-specific

s6-overlay-suexec: fatal: can only run as pid 1

Симптом: container Frigate'а в restart loop, в logs только эта ошибка.

Причина: pid: container:<publisher> сделал Frigate not-PID-1 в shared namespace. s6-overlay v3 strictly требует PID 1 для proper signal handling/zombie reaping.

Fix: убрать pid: container: для Frigate. Только ipc: container: shared.

Trade-off: без shared pid некоторые edge cases CUDA IPC ломаются (см. соответствующую секцию). Frigate на практике работает потому что подключается до того как CUDA driver проверяет peer (race window race), но если publisher restart'нётся посередине — Frigate'у не удастся пере-подключиться без перезапуска.

Real fix (planned v0.2): encoded packet sharing — Frigate detect получает кадры через decoded path (work-around), record получает encoded через socket-based protocol который не требует cudaIpcOpenEventHandle.

No such filter: 'scale_cuda'

Симптом: Frigate ffmpeg subprocess падает с этой ошибкой в AVFilterGraph.

Причина: наш patched FFmpeg собран без --enable-cuda-llvm (см. stdbit.h grабля). Без cuda-llvm в FFmpeg нет CUDA filters (scale_cuda, overlay_cuda).

Fix: в Frigate config.yml явно отключи hwaccel cuda:

ffmpeg:
  hwaccel_args: []   # CPU scale вместо scale_cuda

Cost: 5-10% CPU per FHD25 камера. Real fix (v0.2): publisher-side resize в cuframes сам.

Missing dynamic .so после ffmpeg replace

Симптом: после docker cp patched ffmpeg в Frigate container — ldd ffmpeg показывает libharfbuzz.so.0 => not found, libfribidi.so.0 => not found, … ~20 missing .so.

Причина: Frigate's bundled ffmpeg статически слинкован (NickM-27/FFmpeg-Builds делает full static build). Все 30+ deps встроены в один binary. Frigate runtime image не имеет этих .so packages installed (ему не надо — bundled ffmpeg self-contained).

Наш custom ffmpeg — dynamic linked (apt deps). Нужны .so на target.

Fix: либо

  • apt install missing libs в Frigate (additive image modification):
    apt install libharfbuzz0b libfribidi0 librist4 libsrt1.5-openssl libssh-4 \
                libvpx7 libwebpmux3 libwebp7 libdav1d6 libaom3 libmp3lame0 \
                libsvtav1enc1 libtheora0 libvorbis0a libvorbisenc2 \
                libx264-164 libx265-199 libopus0
    
  • Либо строить наш ffmpeg static (sources from NickM-27 pipeline) — complex (см. zlib download / GMP compiler граблю)

Best practice: создать Dockerfile.frigate overlay поверх Frigate image, который добавляет deps и копирует ffmpeg. Запечь в image, не in-place patch.


Build / FFmpeg patch

libcuframes not found при configure

Симптом: FFmpeg configure (с --enable-libcuframes) fails с этой ошибкой из enabled libcuframes && require libcuframes .... config.log показывает fatal error: cuframes/cuframes.h: No such file or directory.

Причины:

  1. CMake install rules отсутствовали в libcuframes (early commits до 601806a). cmake --install создавал пустой prefix. Fix: обновить cuframes до ≥ 601806a.

  2. Wrong HINTS в find_library: твой проект ищет в ${CUFRAMES_ROOT}/build/... но install layout кладёт в ${CUFRAMES_ROOT}/lib. Добавь оба пути в HINTS.

  3. rm -f libcuframes.so* удалил .so но .a file называется libcuframes_static.a (не libcuframes.a) → linker не находит -lcuframes. Fix: либо не удаляй .so, либо переименуй .a при install.

ffbuild/library.mak: No such file

Симптом: configure FFmpeg success, но make падает сразу: Makefile:123: ffbuild/library.mak: No such file or directory.

Причина: вы сделали ваш fork FFmpeg через snapshot (не git clone), и случайно исключили ffbuild/ в rsync. Это source files FFmpeg, не build artifacts.

Fix: убедись что ffbuild/ есть в твоём FFmpeg checkout (ls ffbuild/library.mak). Если делаешь snapshot через rsync — не используй --exclude=ffbuild.

could not find a working compiler (GMP)

Симптом: crosstool-NG build падает на Installing GMP for host с configure: error: could not find a working compiler. config.log показывает no, long long reliability test 1.

Причина: GMP 6.2.1 имеет known issue с GCC 11+ (Ubuntu 22.04 default). Проверка long-long reliability fail'ит false-positive.

Fix: pin GMP к 6.3.0 в ct-ng-config:

CT_GMP_V_6_3=y
# CT_GMP_V_6_2 is not set
CT_GMP_VERSION="6.3.0"

И убедись что crosstool-NG version (commit) поддерживает 6.3.0 (≥ master 2024-09).

zlib: download failed в crosstool-NG

Симптом: crosstool-NG step Retrieving 'zlib-1.2.12' fail'ит.

Причина: zlib.net убрали старые versions с дефолтного location — теперь они только в /fossils/ subdirectory. Crosstool-NG hardcoded URL не работает.

Fix: pre-fetch tarball + положить в local cache:

wget https://zlib.net/fossils/zlib-1.2.12.tar.gz -O preload/zlib-1.2.12.tar.gz

В Dockerfile перед ct-ng build:

COPY preload/*.tar.gz /root/src/

CT_LOCAL_TARBALLS_DIR=${HOME}/src — crosstool-NG найдёт в cache и не пойдёт download.

stdbit.h: No such file при --enable-cuda-llvm

Симптом: FFmpeg configure с --enable-cuda-llvm fail'ит: fatal error: stdbit.h: No such file or directory. ERROR: cuda_llvm requested but not found.

Причина: stdbit.h — C23 standard header. Доступен в glibc ≥ 2.38.

  • Ubuntu 22.04 = glibc 2.35 — нет
  • Debian 12 = glibc 2.36 — нет
  • Ubuntu 24.04 = glibc 2.39 — есть
  • Debian 13 (trixie) = glibc 2.38+ — есть

Fix options:

  1. Build на newer base (Ubuntu 24.04+). Но runtime target (Frigate Debian 12) не запустит binary с glibc-2.38 symbols (backwards-incompatible).
  2. Убрать --enable-cuda-llvm. Потеря: CUDA filters (scale_cuda, overlay_cuda, hwupload_cuda). Decode/encode через NVDEC/NVENC всё равно работают.
  3. Дождаться когда Frigate base обновится до newer Debian — вне твоего контроля.

На практике: убираем cuda-llvm, в Frigate config hwaccel_args: []. См. scale_cuda секцию.


Docker / IPC

Cross-container CUDA IPC: ipc + pid namespace share

Что нужно Compose option
/dev/shm shared (для cuframes header + SHM ring) ipc: container:<publisher> (либо ipc: shareable у publisher + same у consumer)
/proc visibility (для CUDA IPC peer validation) pid: container:<publisher>
/run/cuframes/*.sock доступен volume mount: cuframes_sock:/run/cuframes:ro
GPU access runtime: nvidia
Socket permissions user: root (либо chmod socket в publisher)

Все 5 должны быть выполнены. Один пропуск — fail при subscriber_create или cudaIpcOpenEventHandle.

Buildx container driver не видит host images

Симптом: при использовании custom buildx builder (docker buildx create --driver docker-container ...) с FROM local-image:tag — error failed to authorize: 403 Forbidden (buildkit пытается pull с registry).

Причина: container driver buildx изолирован, не имеет доступа к host's local docker daemon images. Pull через registry.

Fix: либо

  • Не использовать custom builder — docker buildx use default (использует host daemon). Минус: теряем --cache-to/--cache-from type=local.
  • Либо push local image в registry (local или gitea), и buildx pull'ит оттуда.

Networking / RTSP

RTSP/RTP UDP не доходит до клиента (docker NAT)

Симптом: RTSP server в docker контейнере с ports: "554:8555". Клиент (TV, VLC) делает RTSP SETUP successfully (TCP control работает), но video frames не приходят.

Причина: RTP идёт UDP, sourced из docker network namespace. SNAT MASQUERADE для outbound работает, но RTP destination port (которое клиент опубликовал в SETUP) не маппится обратно через docker bridge — клиент видит UDP packets от чужого source IP (docker network 172.x), не от 192.168.88.23 как expected.

Fix: network_mode: host для RTSP-server контейнера. Тогда server listens напрямую на host interfaces, RTP packets идут без NAT.

Trade-offs:

  • Все ports app'а listen на host network (нет port mapping). Проверь port collisions.
  • DB env vars (postgres:5432 в docker network DNS) надо менять на host paths (localhost:5433 если postgres exposed на host port 5433).

Nonmatching transport in server reply

Симптом: ffprobe -rtsp_transport tcp -i rtsp://... falls с этим сообщением.

Причина: RTSP server возвращает SDP с UDP-only transport. Client ожидает TCP interleaved.

Fix: использовать UDP transport: -rtsp_transport udp (либо default behavior). Если TV не поддерживает UDP — нужен RTSP server который умеет RTP-over-TCP interleaved (cctv-processor v0.1 не умеет).


Gitea Actions / CI

node: executable file not found

Симптом: первый JS action (например actions/checkout@v4) fail'ит: OCI runtime exec failed: exec: "node": executable file not found in $PATH.

Причина: гитея act_runner запускает JS actions через node, но твой custom container (например nvidia/cuda:...) не имеет node installed.

Fix: pre-install node в первом run: step (до actions/checkout):

steps:
  - name: Bootstrap node
    run: apt-get update && apt-get install -y nodejs git ca-certificates
  - name: Checkout
    uses: actions/checkout@v4

Либо использовать container с node pre-installed (docker.gitea.com/runner-images:ubuntu-22.04).

SyntaxError: Unexpected token '{' (Node 12)

Симптом: после apt install nodejs в Ubuntu 22.04 — actions/checkout@v4 fail'ит: SyntaxError: Unexpected token '{' at static {...}.

Причина: Ubuntu 22.04 apt'овский nodejs = Node 12. actions/checkout@v4 скомпилирован для Node 20+ (static class blocks — ES2022).

Fix: install Node 20 from NodeSource:

curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs

В Ubuntu 24.04 apt уже даёт Node 20 — там goes автоматически.