Skip to content

Lock the OBR mutex in head-tracking and limiter setters - #23

Closed
trsonic wants to merge 10 commits into
mainfrom
fix/obr-head-rotation-data-race
Closed

Lock the OBR mutex in head-tracking and limiter setters#23
trsonic wants to merge 10 commits into
mainfrom
fix/obr-head-rotation-data-race

Conversation

@trsonic

@trsonic trsonic commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

SetHeadRotation(), EnableHeadTracking() and EnableLimiter() wrote world_rotation_, head_tracking_enabled_ and limiter_enabled_ without acquiring mutex_, while Process() reads all three under the lock for the duration of each rendered block. Head rotation in particular is typically updated from a sensor thread while the audio thread renders, so the unsynchronized 4-float quaternion write could be observed torn mid-block — and all three writes are data races regardless.

Every other ObrImpl mutator already takes the mutex; this makes the remaining three do the same. The setters are only called from the C API wrappers (obr_capi.cpp), so no caller holds the lock and there is no deadlock path.

No functional change on a single thread; existing tests pass unchanged.

trsonic and others added 10 commits July 30, 2026 19:00
Ports the fork's MODULE.bazel, BUILD.bazel, extensions.bzl and
third_party/pffft.BUILD onto the public repo layout (code at the
repository root instead of liboar/).
Bazel globs do not cross package or module boundaries; the vendored OBR
subtree's BUILD and MODULE.bazel files would stop the top-level targets
from picking up its sources.
Azimuths outside (-180, 180] (e.g. +270 for -90) skipped the front-back
fold and hit the closest-speaker fallback, whose linear angle difference
picks the wrong speaker whenever the true separation crosses the +/-180
seam. Normalize azimuths once at metadata ingestion so every downstream
consumer sees canonical angles, and make the fallback distance circular.
Renders aliased azimuth pairs (+270 vs -90 etc.) to stereo and requires
bit-identical output, and checks lateral sources collapse onto opposite
speakers. Before the fix a source at +270 landed on the left speaker.
enable_testing() at the top level puts the obr unit tests and the liboar
examples in one ctest registry; the examples are registered under an
"oar" label (mirroring the obr subtree's "obr" label) derived from the
directory's target list so new examples cannot be silently left out. The
CI workflow's hardcoded example list and separate obr ctest invocation
collapse into a single label-filtered ctest run.
_open stored the address of the stack-local pout in
ear_renderer->out_sp_layout, which lives for the renderer's lifetime.
The pointer is only dereferenced during _open itself (matrix lookups),
so the bug is latent, but any future reader of
out_sp_layout.sp_layout.predefined_sp after _open returns would hit a
dangling stack pointer. Null it before returning, matching how the
input-layout paths already reset pin/cin.
The ARM NEON matrix-render, OBR resampler/sh_hrir DSP, and LFE filter
sample-rate fixes were merged upstream (AOMediaCodec/oar #14, #15 and
the matrix_render include commit), so they drop off the pending list.
The OLR azimuth wrapping, ctest registration, and EAR dangling-pointer
fixes take their place.
SetHeadRotation(), EnableHeadTracking() and EnableLimiter() wrote
world_rotation_, head_tracking_enabled_ and limiter_enabled_ without
acquiring mutex_, while Process() reads all three under the lock for
the duration of each rendered block. Head rotation in particular is
typically updated from a sensor thread while audio renders, so the
unsynchronized quaternion write could be observed torn mid-block, and
all three are data races regardless. Every other ObrImpl mutator
already takes the mutex; make these three do the same.
@trsonic

trsonic commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Withdrawing for now; will resubmit later.

@trsonic trsonic closed this Jul 30, 2026
@trsonic
trsonic deleted the fix/obr-head-rotation-data-race branch July 30, 2026 20:40
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