cheofusi / just_playback

A small library for playing audio files in python, with essential playback functionality.
MIT License
63 stars 7 forks source link

Leaking file descriptors on Linux #39

Closed adamf closed 2 weeks ago

adamf commented 1 month ago

HI! After running https://github.com/adamf/piplayer/blob/main/piplayer.py for a while, the file descriptor counts keeps increasing, gradually exceeding ulimit and crashing the program.

All the open file descriptors are memfd:pulseaudio owned by the python process using just_playback:

python     9452 16296 python                root  DEL       REG                0,1                6570 /memfd:pulseaudio
python     9452 16296 python                root  134u      REG                0,1 67108864       7479 /memfd:pulseaudio (deleted)
...
# lsof -nP | grep "memfd:pulseaudio" | wc -l
23496

I don't think this is a pulseaudio issue, and it could be my issue (I wrote the referenced code very quickly), but I wonder if this is the intersection of how I'm using just_playback with threads and how just_playback and miniaudio are interacting. Would love some thoughts.

adamf commented 1 month ago

I wonder if my code is skipping to the next file before https://github.com/cheofusi/just_playback/blob/main/just_playback/ma_playback.c#L128 gets handled by a naturally ended audio stream. That said, what happens in https://github.com/cheofusi/just_playback/blob/main/just_playback/ma_playback.c#L128 when the playback object calls load_file again before the audio has finished playing? Does this callback keep getting triggered?

adamf commented 1 month ago

calling load_file() / play() / sleep(1) in a loop reproduces this leak.

cheofusi commented 3 weeks ago

Hi @adamf,

Sorry for the late response. I've been away for while.

I'm unable to reproduce this issue. On running the following script and noting the PID,

from just_playback import Playback
from time import sleep

p = Playback()
while True:
    p.load_file("test.mp3")
    p.play()
    sleep(1)

watch -n 1 'sudo ls /proc/$pid/fd/ | wc -l' stays constant.

Every time you call load_file(), terminate_audio_stream() at https://github.com/cheofusi/just_playback/blob/main/just_playback/ma_playback.c#L112 is called and that cleans up any existing file handles, including stopping the audio device.

adamf commented 2 weeks ago

Thanks for looking into this! I'll see if I can get a better reproducer and re-open if I can. Thanks!