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

327 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Troubleshooting
Реальные грабли которые мы прошли при первой production deployment'е cuframes
(Frigate + custom C++ processor + custom Python). Документировано чтобы вы их
не повторяли.
## Содержание
- [Runtime / CUDA IPC](#runtime--cuda-ipc)
- [`cudaIpcOpenEventHandle: invalid device context`](#cudaipcopeneventhandle-invalid-device-context)
- [Subscriber timeout (`cuframes_subscriber_create: timeout`)](#subscriber-timeout)
- [Permission denied на socket](#permission-denied-на-socket)
- [Frigate-specific](#frigate-specific)
- [`s6-overlay-suexec: fatal: can only run as pid 1`](#s6-overlay-suexec-fatal-can-only-run-as-pid-1)
- [`No such filter: 'scale_cuda'`](#no-such-filter-scale_cuda)
- [Missing dynamic .so после ffmpeg replace](#missing-dynamic-so-после-ffmpeg-replace)
- [Build / FFmpeg patch](#build--ffmpeg-patch)
- [`libcuframes not found` при configure](#libcuframes-not-found-при-configure)
- [`ffbuild/library.mak: No such file`](#ffbuildlibrarymak-no-such-file)
- [`could not find a working compiler` (GMP)](#could-not-find-a-working-compiler-gmp)
- [`zlib: download failed` в crosstool-NG](#zlib-download-failed-в-crosstool-ng)
- [`stdbit.h: No such file` при `--enable-cuda-llvm`](#stdbith-no-such-file-при---enable-cuda-llvm)
- [Docker / IPC](#docker--ipc)
- [Cross-container CUDA IPC: ipc + pid namespace share](#cross-container-cuda-ipc-ipc--pid-namespace-share)
- [Buildx container driver не видит host images](#buildx-container-driver-не-видит-host-images)
- [Networking / RTSP](#networking--rtsp)
- [RTSP/RTP UDP не доходит до клиента (docker NAT)](#rtsprtp-udp-не-доходит-до-клиента-docker-nat)
- [`Nonmatching transport in server reply`](#nonmatching-transport-in-server-reply)
- [Gitea Actions / CI](#gitea-actions--ci)
- [`node: executable file not found`](#node-executable-file-not-found)
- [`SyntaxError: Unexpected token '{'` (Node 12)](#syntaxerror-unexpected-token--node-12)
---
## 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:
```yaml
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:` несовместим (см. [соответствующую секцию](#s6-overlay-suexec-fatal-can-only-run-as-pid-1)).
### 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 ломаются (см. [соответствующую секцию](#cudaipcopeneventhandle-invalid-device-context)). 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абля](#stdbith-no-such-file-при---enable-cuda-llvm)). Без cuda-llvm в FFmpeg нет CUDA filters (scale_cuda, overlay_cuda).
**Fix**: в Frigate config.yml явно отключи hwaccel cuda:
```yaml
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):
```bash
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 граблю](#zlib-download-failed-в-crosstool-ng))
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:
```bash
wget https://zlib.net/fossils/zlib-1.2.12.tar.gz -O preload/zlib-1.2.12.tar.gz
```
В Dockerfile перед `ct-ng build`:
```dockerfile
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 секцию](#no-such-filter-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):
```yaml
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:
```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
```
В Ubuntu 24.04 apt уже даёт Node 20 — там goes автоматически.