Page MenuHomeFreeBSD

sound: Simplify pcm_chnalloc() and fix infinite loop bug
ClosedPublic

Authored by christos on Sep 5 2024, 8:00 PM.
Tags
None
Referenced Files
F102912631: D46548.diff
Mon, Nov 18, 4:19 PM
Unknown Object (File)
Mon, Nov 11, 3:59 AM
Unknown Object (File)
Sat, Nov 9, 1:36 PM
Unknown Object (File)
Oct 18 2024, 3:41 PM
Unknown Object (File)
Oct 15 2024, 8:18 PM
Unknown Object (File)
Oct 15 2024, 8:17 PM
Unknown Object (File)
Oct 15 2024, 8:17 PM
Unknown Object (File)
Oct 15 2024, 8:17 PM
Subscribers

Details

Summary

Simplify logic to execute the following algorithm:

  1. Search for a free (i.e not busy) channel and return successfully.
  2. If no channel was found, either return an ENOTSUP if no VCHAN can be created (disabled or we reached the limit), or create one more VCHAN and scan for it again.
  3. If the second scan failed again, return EBUSY.

This patch also solves a bug where we'd end up in an infinite loop,
calling vchan_setnew() with the same newcnt value indefinitely, after
the following scenario:

  1. Plug device.
  2. Spawn X channels.
  3. Kill all channels except _last_ opened.
  4. Clean up all unused VCHANs.
  5. Spawn X+1 channels.
  6. Infinite loop in pcm_chnalloc().

I am not exactly sure which part of pcm_chnalloc() caused this bug, but
the patch fixes it at least...

Sponsored by: The FreeBSD Foundation
MFC after: 2 days

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 59322
Build 56209: arc lint + arc unit

Event Timeline

Handle vchan_setnew() error case.

I think the endless loop was caused by goto vchan_alloc;: It skips the retry check, successfully calls vchan_setnew() with unchanged values, and then loops back through goto retry_chnalloc;. There's nothing else in there that would change and break the loop.

That endless loop would be triggered when the vchan_num < c->unit condition is met. I'd expect that to happen before spawning vchan X + 1 though.

I think the endless loop was caused by goto vchan_alloc;: It skips the retry check, successfully calls vchan_setnew() with unchanged values, and then loops back through goto retry_chnalloc;. There's nothing else in there that would change and break the loop.

That endless loop would be triggered when the vchan_num < c->unit condition is met. I'd expect that to happen before spawning vchan X + 1 though.

Good analysis. I did some testing to confirm this a few days ago and I think this is what's happening indeed. Are you okay with the patch?

This revision is now accepted and ready to land.Sep 16 2024, 1:42 AM