[GH-ISSUE #148] [BUG] AbsChunkedInputStream's wait_lock releases before chunk is ready #19

Closed
opened 2026-02-27 08:11:28 +03:00 by kerem · 1 comment
Owner

Originally created by @yeralin on GitHub (Aug 18, 2022).
Original GitHub issue: https://github.com/kokarare1212/librespot-python/issues/148

Describe the bug
From time to time, librespot-python library would fail to play audio in the middle of the stream. After debugging the problem (hard to reproduce), I noticed that AbsChunkedInputStream.read(__size: int = 0) method returns an empty buffer. After debugging it further, I tracked the problem down to AbsChunkedInputStream.wait_lock which is prematurely released under the AbsChunkedInputStream.check_availability method.

So, I put a few debugging statements around the wait() call:

def check_availability(self, chunk: int, wait: bool, halted: bool) -> None:
    ...
    with self.wait_lock:
            if not halted:
                self.stream_read_halted(chunk, int(time.time() * 1000))
            self.chunk_exception = None
            self.wait_for_chunk = chunk
            print("block")
            self.wait_lock.wait()
            print("unblock")
            if self.closed:
                return
    ...

And received the following logs:

block
DEBUG:Librespot:Session:Chunk 25/55 completed, cached: False, stream: 131072
unblock

block
DEBUG:Librespot:Session:Chunk 26/55 completed, cached: False, stream: 131072
unblock

block
DEBUG:Librespot:Session:Chunk 27/55 completed, cached: False, stream: 131072
unblock

block
DEBUG:Librespot:Session:Chunk 28/55 completed, cached: False, stream: 131072
unblock

block
unblock

As you can see for chunk #29, self.wait_lock.wait() returns before the chunk is downloaded; thus, the buffer returned empty.
You can also verify that by checking self.wait_for_chunk which is not -1. Although, it must be set to -1 right before self.wait_lock.notify_all() calls.

To Reproduce
As I mentioned reproducing this bug is difficult since it happens haphazardly.

Not entirely sure why this happens. I did some googling, but I haven't found anyone else encountering this problem before. I've been trying streaming songs >6 mins long, and in 1 out of 5 times this issue occurs.

Expected behavior
self.wait_lock.wait() call under AbsChunkedInputStream.check_availability method should return after the chunk is ready to be consumed.

Client Information (please complete the following information):

  • OS: Ubuntu 21.10
  • Python Version: Python 3.9.7
  • Library Version: git+https://github.com/kokarare1212/librespot-python (master)

Additional context
One potential resolution that has worked for me was to change the call from self.wait_lock.wait() to self.wait_lock.wait_for(lambda: self.available_chunks()[chunk]).

Effectively, the result would be the same as we are blocking and waiting for the chunk to become available.

Originally created by @yeralin on GitHub (Aug 18, 2022). Original GitHub issue: https://github.com/kokarare1212/librespot-python/issues/148 **Describe the bug** From time to time, `librespot-python` library would fail to play audio in the middle of the stream. After debugging the problem (hard to reproduce), I noticed that `AbsChunkedInputStream.read(__size: int = 0)` method returns an empty buffer. After debugging it further, I tracked the problem down to `AbsChunkedInputStream.wait_lock` which is prematurely released under the `AbsChunkedInputStream.check_availability` method. So, I put a few debugging statements around the `wait()` call: ```python def check_availability(self, chunk: int, wait: bool, halted: bool) -> None: ... with self.wait_lock: if not halted: self.stream_read_halted(chunk, int(time.time() * 1000)) self.chunk_exception = None self.wait_for_chunk = chunk print("block") self.wait_lock.wait() print("unblock") if self.closed: return ... ``` And received the following logs: ``` block DEBUG:Librespot:Session:Chunk 25/55 completed, cached: False, stream: 131072 unblock block DEBUG:Librespot:Session:Chunk 26/55 completed, cached: False, stream: 131072 unblock block DEBUG:Librespot:Session:Chunk 27/55 completed, cached: False, stream: 131072 unblock block DEBUG:Librespot:Session:Chunk 28/55 completed, cached: False, stream: 131072 unblock block unblock ``` As you can see for chunk `#29`, `self.wait_lock.wait()` returns **before** the chunk is downloaded; thus, the buffer returned empty. You can also verify that by checking `self.wait_for_chunk` which is not `-1`. Although, it must be set to `-1` right before `self.wait_lock.notify_all()` calls. **To Reproduce** As I mentioned reproducing this bug is difficult since it happens haphazardly. Not entirely sure why this happens. I did some googling, but I haven't found anyone else encountering this problem before. I've been trying streaming songs >6 mins long, and in 1 out of 5 times this issue occurs. **Expected behavior** `self.wait_lock.wait()` call under `AbsChunkedInputStream.check_availability` method should return **after** the chunk is ready to be consumed. **Client Information (please complete the following information):** - OS: Ubuntu 21.10 - Python Version: Python 3.9.7 - Library Version: `git+https://github.com/kokarare1212/librespot-python` (master) **Additional context** One potential resolution that has worked for me was to change the call from `self.wait_lock.wait()` to `self.wait_lock.wait_for(lambda: self.available_chunks()[chunk])`. Effectively, the result would be the same as we are blocking and waiting for the chunk to become available.
kerem 2026-02-27 08:11:28 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@kokarare1212 commented on GitHub (Aug 19, 2022):

Thank you for reporting the bug.
I have made the change.

<!-- gh-comment-id:1220091746 --> @kokarare1212 commented on GitHub (Aug 19, 2022): Thank you for reporting the bug. I have made the change.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot-python-kokarare1212#19
No description provided.