Skip to content

fix(core): bound pending thread-pool jobs and tighten measured lint debt - #1422

Closed
lusoris wants to merge 3 commits into
masterfrom
fix/thread-pool-queue-bound
Closed

lusoris wants to merge 3 commits into
masterfrom
fix/thread-pool-queue-bound

Conversation

@lusoris

@lusoris lusoris commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Bound pending thread-pool jobs by the number of successfully created workers so input faster than scoring cannot grow the pending picture queue without limit. Adapt Netflix/vmaf commit 8fc71e3006f0b21e8e31d6e5d1b904332149ad9e to preserve VMAFx inline/heap job recycling, per-worker data and batch error accumulation; keep registered capacity waiters alive during coordinated shutdown.

Add a guarded scoped lint-baseline writer under ADR-1243. Its actual LLVM 22.1.8 measurement tightens thread_pool.c from 15 warnings to zero (CPU total 1472 → 1457), preserves every unmeasured source/header allowance and retains the original 292-TU full-report metadata with explicit scoped provenance.

Type

  • fix — bug fix
  • build / ci — tooling / infra
  • port — adapted upstream Netflix/vmaf fix with fork-specific lifetime/test changes

Validation

On head bbf349e04, based on master 78c9d2bfc:

  • Dedicated CPU-only container compiled this checkout: both Meson thread-pool executables passed; four deterministic backpressure/failure tests passed under ASan+UBSan and under TSan. No installed libvmaf binary or shared GPU/device instance was used.
  • Original fork source fails the saturation regression. Removing only the producer-lifetime wait from the fix reproduces ASan heap-use-after-free in the coordinated shutdown case.
  • 32 ratchet/parser/filesystem tests pass, including missing/unreadable inputs, compiler/tool/parse failures, debt increases, output aliases, atomic replacement failures, two actual competing writer processes and baseline drift. Strict mypy and normal commit hooks pass.
  • Actual scoped clang-tidy measurement of both changed translation units: zero warnings, zero uncited NOLINTs; repeating the write after rebase leaves the baseline byte-identical. Scoped tests do not replace the full required CI lane.

Checklist

  • Commits follow Conventional Commits.
  • Full make lint and make test green locally: not yet established; keep draft and held.
  • Full meson test -C build: not run; the two relevant executables passed.
  • New C test carries the fork license header; upstream source header retained.
  • ADR-1243 was atomically reserved and committed before tooling; index and changelog rendered from fragments.
  • No Netflix assertAlmostEqual(...) score was modified.

Bug-status hygiene

  • docs/state.md records T-THREAD-POOL-UNBOUNDED-QUEUE-2026-09-08 with the bounded validation scope.

Deep-dive deliverables

  • Research digest — docs/research/2041-thread-pool-backpressure.md links upstream evidence, fork couplings and the reproduced shutdown race.
  • Decision matrix — ADR-1243 compares full measurements, partial replacement, hand edits and guarded scoped tightening.
  • AGENTS.md invariant note — core/AGENTS.md and scripts/ci/AGENTS.md preserve lifetime, ownership and ratchet contracts.
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragment — changelog.d/fixed/thread-pool-bounded-queue.md and changelog.d/added/tidy-scoped-baseline-tightening.md.
  • Rebase note — separate queue/lifetime and scoped-writer entries in docs/rebase-notes.md.

Reproducer

meson test -C build test_thread_pool test_thread_pool_backpressure --print-errorlogs
python3 -m unittest discover -s scripts/ci/tests -p 'test_tidy_*.py'

The test build injects pthread failures and scheduling barriers in its own executable. It verifies actual-worker queue capacity, dequeue wakeups, coordinated capacity-waiter cancellation, concurrent inline/heap payload recycling, error reset and initialization unwind.

Known follow-ups and limits

  • Keep this PR draft and on the merge-train hold list until full lint/test and hosted required gates are green. Full golden-data scoring, Windows/macOS builds and the upstream reporter's VideoToolbox workload remain unverified here.
  • Destruction must be externally serialized against API entry, including callers waiting to acquire the queue mutex. The supported cancellation case requires a producer proven registered in the capacity wait; arbitrary enqueue/destroy races are not supported. Same-pool recursive enqueue can deadlock and is documented as unsupported.
  • Baseline writers use POSIX advisory locking and reject detected content drift. Arbitrary Git/editor mutations do not honor that lock; keep the checkout stable while measuring.
  • Master’s pre-existing ADR by-tag generation drift is covered by the separate RC1 hygiene work. This PR preserves its canonical ADR/index changes without importing hundreds of unrelated generated files; regenerate after the documentation base fix lands.
  • No SIMD/GPU feature extractor, public C API or FFmpeg-facing surface changed.

Adapt upstream queue admission to preserve recycled inline/heap jobs, worker data and batch errors. Wait for blocked producers during shutdown so their synchronization objects remain alive.

(cherry picked from commit 8fc71e3006f0b21e8e31d6e5d1b904332149ad9e)
Preserve full-report metadata and unmeasured debt during guarded scoped writes. Reject incomplete coverage, failed measurements, regressions and output aliases; serialize full and scoped writers and replace validated output atomically. Lower the measured thread-pool allowance from 15 warnings to zero.
@lusoris

lusoris commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by the pre-rc.1 fixing train in #1425, which carries this work.

Closing rather than leaving it open, because the ADR Collision Guard — a required check — fails #1425 while two open PRs claim the same ADR number. The guard is right that they collide; it cannot tell that one of them contains the other.

Verified before closing, not assumed: every ADR file this branch adds is byte-identical in #1425 (sha256 compared), and the branch's commits were replayed onto the train individually, with each conflict resolved by hand and recorded in the commit messages.

The branch is untouched, so this is reversible — reopen if #1425 is abandoned.

@lusoris lusoris closed this Sep 15, 2026
@lusoris
lusoris deleted the fix/thread-pool-queue-bound branch September 18, 2026 07:57
lusoris added a commit that referenced this pull request Oct 8, 2026
…9cb9479f2

The fork's records of its Netflix/vmaf pull requests and of the upstream
defects it tracks were last checked on 2026-10-01. Upstream master has
moved to 9cb9479f2 since, with the MSVC series, the arm64 ADM kernels,
the fused SpEED filter and a rewrite of integer_compute_adm(). This
brings the records up to date. No fork code and no score changes.

- known-upstream-bugs.md: 42 open pull requests instead of 15, which of
  them needed a rebase or a rework against 9cb9479f2, the #1494 and
  best15 status, the integer AIM change upstream (cffd5b77d), the arm64
  gap in #1602, and what is new upstream since the parity pin. The pin
  heading is unchanged.
- state.md: dated updates on the rows for #1422, #1551 (both halves),
  #1602, #1605, #1635, #1636 and #955.
- upstream_parity.d: the APSNR zero-error row also names #1618, which
  changes the same cap upstream; the allowlist page is regenerated.
- rebase-notes.d: what a port of upstream's arm64 ADM code (8bc5a5c6a,
  b41d2340a) must not copy, and the closed state of #1551.

Signed-off-by: Lusoris <lusoris@proton.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant