- 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>
16 KiB
Troubleshooting
Реальные грабли которые мы прошли при первой production deployment'е cuframes (Frigate + custom C++ processor + custom Python). Документировано чтобы вы их не повторяли.
Содержание
- Runtime / CUDA IPC
- Frigate-specific
- Build / FFmpeg patch
- Docker / IPC
- Networking / RTSP
- Gitea Actions / CI
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 без других ошибок.
Причины (в порядке вероятности):
/run/cuframes/<key>.sockне виден consumer'у — забыли volume-mount/run/cuframesсмонтирован, но publisher ещё не успел создать socket — увеличитьconnect_timeout_ms- 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 installmissing 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.
Причины:
-
CMake install rules отсутствовали в libcuframes (early commits до
601806a).cmake --installсоздавал пустой prefix. Fix: обновить cuframes до ≥601806a. -
Wrong HINTS в find_library: твой проект ищет в
${CUFRAMES_ROOT}/build/...но install layout кладёт в${CUFRAMES_ROOT}/lib. Добавь оба пути в HINTS. -
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:
- Build на newer base (Ubuntu 24.04+). Но runtime target (Frigate Debian 12) не запустит binary с glibc-2.38 symbols (backwards-incompatible).
- Убрать
--enable-cuda-llvm. Потеря: CUDA filters (scale_cuda,overlay_cuda,hwupload_cuda). Decode/encode через NVDEC/NVENC всё равно работают. - Дождаться когда 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 автоматически.