Page MenuHomeFreeBSD

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

Authored by christos on Thu, Sep 5, 8:00 PM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Sep 22, 12:31 PM
Unknown Object (File)
Tue, Sep 17, 3:08 AM
Unknown Object (File)
Wed, Sep 11, 5:50 PM
Unknown Object (File)
Wed, Sep 11, 5:50 PM
Unknown Object (File)
Wed, Sep 11, 11:13 AM
Unknown Object (File)
Tue, Sep 10, 5:46 PM
Unknown Object (File)
Tue, Sep 10, 2:16 PM
Unknown Object (File)
Tue, Sep 10, 1:54 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 59325
Build 56212: 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.Mon, Sep 16, 1:42 AM