[Errno 24] after opening and closing videos constantly
Issue Report
Description
Alternating between two player instances to put a video display on a tour. This eventually produces a [Errno 24] Too many open files after about an hour.
Problem reproduction
this is the current test code
# Project: Chart Compatible Impath Decoder Emulator for Raspberry pi
# Python 3
#Test for video switching for monitors on tour
import time
import socket
import sys
from _thread import *
import os
import subprocess
import re
import logging
from omxplayer.player import OMXPlayer
from datetime import datetime
def LoadStream(val):
#Val = 0 'tmpSDP.sdp dbus "omxplayer.player0'
#Val = 1 'tmpSDP.sdp dbus "omxplayer.player1'
#Val = 2 'cnv.sdp' dbus "omxplayer.player1
omx_arg = ['--timeout', '6000', '--live', '--blank', '--refresh', '--no-keys']
if (val == 0):
return OMXPlayer('tmpSDP1.sdp', args=omx_arg, dbus_name="omxplayer.player0")
elif (val == 1):
return OMXPlayer('tmpSDP2.sdp', args=omx_arg, dbus_name="omxplayer.player1")
else:
return OMXPlayer('cnv.sdp', args=omx_arg, dbus_name="omxplayer.player1")
log_name = datetime.now().strftime('decoder_%H_%M_%d_%m_%Y.log')
logging.basicConfig(filename= log_name, level=logging.WARNING, format='%(asctime)s %(message)s') #change to 'WARNING' when in production 'DEBUG' and 'INFO' are valid choices
player_turn = True #true = Player1 will hide and player0 will play
omx_test = True #The decoder is not in an error recovery state
player1 = LoadStream(1)
player1.play()
#code will load a new player instance, kill the old instance to give the illusion of a seamless transfer then repeat.
while True:
time.sleep(3)
try:
if player_turn:
player0 = LoadStream(0)
time.sleep(2)
player1.hide_video()
player1.stop()
player1.quit()
time.sleep(1)
player0.play()
time.sleep(1)
if player0.is_playing():
pass
omx_test = True
player_turn = False
logging.info('Playing on Player0')
else:
player1 = LoadStream(1)
time.sleep(2)
player0.hide_video()
player0.stop()
player0.quit()
time.sleep(1)
player1.play()
time.sleep(1)
if player1.is_playing():
pass
omx_test = True
player_turn = True
logging.info('Playing on Player1')
except Exception as e:
error_check = True
logging.warning('failure to load')
logging.warning('failure to load error: %s', e)
while error_check:
player1.quit()
time.sleep(2)
player0.quit()
time.sleep(2)
try:
player1 = LoadStream(2)
player1.play()
time.sleep(2)
if player1.is_playing():
player_turn = True
omx_test = False
error_check = False
except Exception as e:
logging.error('CNV display error: %s', e)
player1.quit()
pass
pass
Please let me know if you need more details, amateur here and first time posting.
SImilar problem here! Looking for a fix
Same problem here. Fixing #78 would make this a lot easier to avoid, I would think.
I've been trying to debug this problem, and I think I've found the issue - but not a fix. Each time the player gets loaded with a source, I see an entry in lsof of type STREAM for the main python process. When player.stop() or .quit() is called, that entry does not go away. For example, after playing a sound effect 7 times, here's an excerpt of lsof | grep 'python':
python 12611 pi 0u CHR 136,2 0t0 5 /dev/pts/2
python 12611 pi 1u CHR 136,2 0t0 5 /dev/pts/2
python 12611 pi 2u CHR 136,2 0t0 5 /dev/pts/2
python 12611 pi 3u unix 0x9be72d00 0t0 219115 type=STREAM
python 12611 pi 4u unix 0x9be74c00 0t0 219245 type=STREAM
python 12611 pi 5u unix 0x9be71b00 0t0 218986 type=STREAM
python 12611 pi 6u unix 0x9be71800 0t0 219102 type=STREAM
python 12611 pi 7u unix 0x9be70000 0t0 219122 type=STREAM
python 12611 pi 8u unix 0x9be76a00 0t0 219986 type=STREAM
python 12611 pi 9u unix 0x9be76700 0t0 220066 type=STREAM
So far I haven't figured out a way to kill those open streams without killing the main python process, but I'll report back if I do.
I ran into the same problem and solved it for me with the following workaround:
You should not create new instances of OMXPlayer, only create them once (player0 and player1 for you).
Instead call load() with the new video to play.
With this approach the number of open streams does not increase anymore.
@michaelnimbs
You are my savior, everything works. You just need to use the method load()
Looking at the lsof output, the open fds are UNIX sockets, so I suspect this is the connection to the dbus daemon. Looking at the source, I indeed see that OMXPlayer._connection is created, but it is never actually closed.
I suspect that it would be solved by disconnecting dbus on quit, e.g. by adding this to the end of the quit() method (alternatively, you can call this after you call quit from your program as well so you do not need to modify the library, then replace self with your player instance):
self._connection._bus.close()
self._connection = None
Anyone care to test this?
Hi, using a single instance and only calling load does not seem like it will help because the DBus connection is opened every time a new process is spawned. (see https://github.com/willprice/python-omxplayer-wrapper/blob/master/omxplayer/player.py#L163)
It may be that in most cases the garbage collector closes the connections but I encountered resource exhaustion at least once with 140 DBus sockets open in a long running Python process which used omxplayer-wrapper.
I'll monkey-patch the quit method to call self._connection._bus.close() and see if this resolves the problem.
In case it helps someone, a quick patch looks like this:
def patch_OMXPLayer_quit():
old_quit = OMXPlayer.quit
def new_quit(self):
self._connection._bus.close()
old_quit(self)
OMXPlayer.quit = new_quit
patch_OMXPLayer_quit()
I'll let you know if it solved the problem definitely.
Ok, I've tested this for quite a long time now and the change I posted definitively fixed the problem with leaking bus connections.
Thanks @jpc for looking into this, would you be able to open a PR with this change and i'll merge it in!
I add @matthijskooijman suggestion in player.py at function quit() and it's work.(Tested 72 hours none stop playing 9 mp4 files, until now pi still playing without [Errno 24])
def quit():
if self._connection._bus is not None:
self._connection._bus.close()
logger.debug('[Errno 24][patch]BusConnection closed')
"""
Quit the player, blocking until the process has died
"""
......
Thanks for the confirmation @bonnyone. I'll make the change and make a new release later today.
@willprice U r welcome.
This is my code for test
def threadingPlayer():
while True:
try:
movie = movies[movie_index]
print('********************************')
print(movie)
print('********************************')
player = OMXPlayer(Path(movie),
args=['--no-osd', '--no-keys', '-o', 'hdmi'],
dbus_name='org.mpris.MediaPlayer2.omxplayer1')
player.set_volume(player_volume)
sleep(2.5)
player.play_sync()
player.quit()
player = None
print('Play Next')
movie_index = movie_index + 1
if movie_index == len(movies):
movie_index = 0
except OSError as e:
logger.error(e)
except Exception as e:
logger.error(e)
threading.Thread(target=threadingPlayer).start()