beetbox / beetbox/audioread

audioread race condition freezes when cleaning up

Open
#57 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
538
Forks
112
PR merge metrics
No merged PRs in 30d

Description

I have a flac file that causes acoustid to freeze when doing:
```
import acoustid
acoustid.fingerprint_file('01.flac')
```
If I press Ctrl-C, I get the following backtrace:
```
Traceback (most recent call last):
File "/usr/lib64/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/lib/python3.6/site-packages/audioread/gstdec.py", line 149, in run
self.loop.run()
File "/usr/lib64/python3.6/site-packages/gi/overrides/GLib.py", line 588, in run
raise KeyboardInterrupt
```
Btw, the file plays perfectly fine with ffplay, mpv, mplayer... Also, I tried reading the audio blocks with simple audioread code like:
```
with audioread.audio_open(path) as f:
for x in f:
print(x)
```
and that seems to work fine.

What makes me think that it's an audioread issue and not an acoustid issue is that in audioread's gstdec.py, if I put `return None` as the first line of get_loop_thread, it doesn't freeze (works normally).

I've tried to debug a bit the problem and noticed that acoustid has a _fingerprint_file_audioread function defined as:
```
def _fingerprint_file_audioread(path, maxlength):
"""Fingerprint a file by using audioread and chromaprint."""
try:
with audioread.audio_open(path) as f:
duration = f.duration
fp = fingerprint(f.samplerate, f.channels, iter(f), maxlength)
except audioread.DecodeError:
raise FingerprintGenerationError("audio could not be decoded")
return duration, fp
```
If I add `time.sleep(0.00000000000001)` at the end of the `with` block (just after the fingerprint call), sometimes it works as expected, and if I use `time.sleep(0.1)` instead, it seems to "fix it" and doesn't freeze anymore, so it seems to be some kind of race condition.

After some more debugging I found out that the exact line where it's freezing is in the call to `self.pipeline.set_state(Gst.State.NULL)` inside `GstAudioFile.close` but I'm not sure how to continue from there since I don't have much experience with gstreamer.

I'm using audioread 2.1.5, gstreamer 1.12.3 and pyacoustid 1.1.5 with chromaprint 1.4.2 . I also tried with gstreamer 1.12.2 and audioread 2.1.4.

Btw, another solution I found was to do `ffmpeg -i 01.flac output.flac`. The resulting file is processed correctly and never freezes.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the FLAC case through acoustid.fingerprint_file and the audioread loop in audioread/gstdec.py. Inspect get_loop_thread and GstAudioFile.close, especially the pipeline.set_state(Gst.State.NULL) call, using the reported backtrace and timing behavior. Done means cleanup completes without freezing while processing the problematic file.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
audio-video-rtc
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.