pyglet
pyglet copied to clipboard
Pulse Audio Exception - Hard to Reproduce
Describe the bug
I'm using Python Arcade 3.0.0.dev25 and Pyglet 2.0.0.9. Randomly (usually when I pause a lot when debugging, but also when I've been running the game for a while) I get the following exception thrown:
Assertion 'q->front' failed at pulsecore/queue.c:81, function pa_queue_push(). Aborting.
The bug is clearly in pulse audio. It was listed as a "closed issue": https://github.com/mackron/miniaudio/issues/235 And fixed here: https://github.com/mackron/miniaudio/commit/50c9081b19fe4e25c781c78b6b7acfbc5ffdef58
System Information:
pyglet.version: 2.0.9
pyglet.compat_platform: linux
pyglet.__file__: /home/david/.virtualenvs/venv_arcade/lib/python3.10/site-packages/pyglet/__init__.py
pyglet.options['audio'] = ('xaudio2', 'directsound', 'openal', 'pulse', 'silent')
pyglet.options['debug_font'] = False
pyglet.options['debug_gl'] = True
pyglet.options['debug_gl_trace'] = False
pyglet.options['debug_gl_trace_args'] = False
pyglet.options['debug_gl_shaders'] = False
pyglet.options['debug_graphics_batch'] = False
pyglet.options['debug_lib'] = False
pyglet.options['debug_media'] = False
pyglet.options['debug_texture'] = False
pyglet.options['debug_trace'] = False
pyglet.options['debug_trace_args'] = False
pyglet.options['debug_trace_depth'] = 1
pyglet.options['debug_trace_flush'] = True
pyglet.options['debug_win32'] = False
pyglet.options['debug_input'] = False
pyglet.options['debug_x11'] = False
pyglet.options['shadow_window'] = True
pyglet.options['vsync'] = None
pyglet.options['xsync'] = True
pyglet.options['xlib_fullscreen_override_redirect'] = False
pyglet.options['search_local_libs'] = True
pyglet.options['win32_gdi_font'] = False
pyglet.options['headless'] = False
pyglet.options['headless_device'] = 0
pyglet.options['win32_disable_shaping'] = False
pyglet.options['dw_legacy_naming'] = False
pyglet.options['win32_disable_xinput'] = False
pyglet.options['com_mta'] = False
pyglet.options['osx_alt_loop'] = False
pyglet.window
------------------------------------------------------------------------------
display: <pyglet.canvas.xlib.XlibDisplay object at 0x7f8a319e2d10>
screens[0]: XlibScreen(display=<pyglet.canvas.xlib.XlibDisplay object at 0x7f8a319e2d10>, x=0, y=0, width=1920, height=1080, xinerama=False)
config['double_buffer'] = 1
config['stereo'] = 0
config['buffer_size'] = 24
config['aux_buffers'] = 0
config['sample_buffers'] = 0
config['samples'] = 0
config['red_size'] = 8
config['green_size'] = 8
config['blue_size'] = 8
config['alpha_size'] = 0
config['depth_size'] = 24
config['stencil_size'] = 0
config['accum_red_size'] = 0
config['accum_green_size'] = 0
config['accum_blue_size'] = 0
config['accum_alpha_size'] = 0
config['major_version'] = 3
config['minor_version'] = 3
config['forward_compatible'] = None
config['opengl_api'] = 'gl'
config['debug'] = None
context: XlibContext(id=140231516124640, share=XlibContext(id=140231514667616, share=None))
window.context._info
------------------------------------------------------------------------------
gl_info.get_version(): (4, 6)
gl_info.get_vendor(): Intel
gl_info.get_renderer(): Mesa Intel(R) UHD Graphics 630 (CFL GT2)
pyglet.gl.glx_info
------------------------------------------------------------------------------
context.is_direct(): 1
glx_info.get_server_vendor(): SGI
glx_info.get_server_version(): 1.4
glx_info.get_server_extensions():
GLX_ARB_create_context
GLX_ARB_create_context_no_error
GLX_ARB_create_context_profile
GLX_ARB_create_context_robustness
GLX_ARB_fbconfig_float
GLX_ARB_framebuffer_sRGB
GLX_ARB_multisample
GLX_EXT_create_context_es_profile
GLX_EXT_create_context_es2_profile
GLX_EXT_fbconfig_packed_float
GLX_EXT_framebuffer_sRGB
GLX_EXT_import_context
GLX_EXT_libglvnd
GLX_EXT_no_config_context
GLX_EXT_texture_from_pixmap
GLX_EXT_visual_info
GLX_EXT_visual_rating
GLX_MESA_copy_sub_buffer
GLX_OML_swap_method
GLX_SGI_make_current_read
GLX_SGI_swap_control
GLX_SGIS_multisample
GLX_SGIX_fbconfig
GLX_SGIX_pbuffer
GLX_SGIX_visual_select_group
GLX_INTEL_swap_event
glx_info.get_client_vendor(): Mesa Project and SGI
glx_info.get_client_version(): 1.4
glx_info.get_client_extensions():
GLX_ARB_context_flush_control
GLX_ARB_create_context
GLX_ARB_create_context_no_error
GLX_ARB_create_context_profile
GLX_ARB_create_context_robustness
GLX_ARB_fbconfig_float
GLX_ARB_framebuffer_sRGB
GLX_ARB_get_proc_address
GLX_ARB_multisample
GLX_EXT_buffer_age
GLX_EXT_create_context_es2_profile
GLX_EXT_create_context_es_profile
GLX_EXT_fbconfig_packed_float
GLX_EXT_framebuffer_sRGB
GLX_EXT_import_context
GLX_EXT_no_config_context
GLX_EXT_swap_control
GLX_EXT_swap_control_tear
GLX_EXT_texture_from_pixmap
GLX_EXT_visual_info
GLX_EXT_visual_rating
GLX_ATI_pixel_format_float
GLX_INTEL_swap_event
GLX_MESA_copy_sub_buffer
GLX_MESA_multithread_makecurrent
GLX_MESA_query_renderer
GLX_MESA_swap_control
GLX_NV_float_buffer
GLX_OML_swap_method
GLX_OML_sync_control
GLX_SGIS_multisample
GLX_SGIX_fbconfig
GLX_SGIX_pbuffer
GLX_SGIX_visual_select_group
GLX_SGI_make_current_read
GLX_SGI_swap_control
GLX_SGI_video_sync
glx_info.get_extensions():
GLX_ARB_create_context
GLX_ARB_create_context_no_error
GLX_ARB_create_context_profile
GLX_ARB_create_context_robustness
GLX_ARB_fbconfig_float
GLX_ARB_framebuffer_sRGB
GLX_ARB_get_proc_address
GLX_ARB_multisample
GLX_EXT_buffer_age
GLX_EXT_create_context_es2_profile
GLX_EXT_create_context_es_profile
GLX_EXT_fbconfig_packed_float
GLX_EXT_framebuffer_sRGB
GLX_EXT_import_context
GLX_EXT_no_config_context
GLX_EXT_swap_control
GLX_EXT_swap_control_tear
GLX_EXT_texture_from_pixmap
GLX_EXT_visual_info
GLX_EXT_visual_rating
GLX_INTEL_swap_event
GLX_MESA_copy_sub_buffer
GLX_MESA_query_renderer
GLX_MESA_swap_control
GLX_OML_swap_method
GLX_OML_sync_control
GLX_SGIS_multisample
GLX_SGIX_fbconfig
GLX_SGIX_pbuffer
GLX_SGIX_visual_select_group
GLX_SGI_make_current_read
GLX_SGI_swap_control
GLX_SGI_video_sync
pyglet.media
------------------------------------------------------------------------------
audio driver: <pyglet.media.drivers.pulse.adaptation.PulseAudioDriver object at 0x7f8a319e3eb0>
pyglet.media.ffmpeg
------------------------------------------------------------------------------
FFmpeg version: 4.2.7-0ubuntu0.1
pyglet.media.drivers.openal
------------------------------------------------------------------------------
OpenAL not available.
pyglet.input.wintab
------------------------------------------------------------------------------
WinTab not available.
How To Reproduce This is the code I've written to start the sound most of the time. When a sprite triggers an action (i.e. starts walking) if the player sprite is close enough, the sound turns on. This code snippet is typical of when I load or turn on sound. Typically there are two sounds playing when the exception happens.
def start(self, player_character: arcade.Sprite, source_sprite: arcade.Sprite, eos=None):
self.player_character = player_character
self.sound_source = source_sprite
self.eos = eos
self.sound = arcade.Sound(self.file_name, streaming=False)
if self.min_range <= 0: # Start playing right away
self.media_player = self.sound.play(volume=self.max_volume, loop=self.loop)
# Todo: Add EOS logic
After looking at the system info, I realized I didn't have OpenAL installed - so I did. Obviously, this is a work around, but I did notice everything sounded better (the distance from player seemed to work better).
The bug is clearly in pulse audio. It was listed as a "closed issue":
Could you please you post the following?
- The version of AVbin pyglet is using
- The miniaudio version that AVbin is using
- Your Ubuntu version
Although the issue you linked was closed in 2020, the fix might not be shipped on older LTS versions.
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.6 LTS
Release: 20.04
Codename: focal
Please forgive my ignorance on AVbin ... can you tell me how to check ?
My apologies, I think there was a misunderstanding:
- The current version of
pyglet.media.drivers
seem to bind PulseAudio and OpenAL directly via ctypes instead of using miniaudio or AVbin - Based on the miniaudio issue, PR, and commit, it looks like it's race condition from how access is handed off rather than a bug in PulseAudio itself
The contradictory docstring at the top of the PulseAudio binding is also concerning. Combined with the issues you linked, it's probably good starting point for investigating this further:
https://github.com/pyglet/pyglet/blob/66466f80cb9b2437971851bbaf0a997faf7343bb/pyglet/media/drivers/pulse/lib_pulseaudio.py#L1-L10
I'm not familiar with audio and am unsure if I'll be able to fix this.
Obviously, this is a work around
A workaround may be better than nothing, especially if the required packages are widely available. Documenting them and the setup steps would be a decent short-term solution.
Could you please re-run the pyglet system info command and confirm the following?
- You no longer get the exception when using OpenAL
- The
pyglet.media.drivers.openal
section no longer readsOpenAL not available.
- The
pyglet.media
section'saudio driver
entry now starts with variation ofaudio driver: <pyglet.media.drivers.openal.adaptation.OpenALDriver
Randomly (usually when I pause a lot when debugging, but also when I've been running the game for a while) I get the following exception thrown:
On further thought, this behavior seems understandable in the context of debugging and other reports of the same error. It may be an underflow caused by debugging or loss of sync:
- There's a
get_timing_info
method that the OOP abstraction uses
https://github.com/pyglet/pyglet/blob/66466f80cb9b2437971851bbaf0a997faf7343bb/pyglet/media/drivers/pulse/interface.py#L502-L509 2. Debugging can do odd things to programs that aren't built to account for odd jumps in time 3. On resuming or loss of sync, pyglet's abstraction could try to fetch nonexistent data due to the time data being stale
I think you've also revealed why I've never run into this issue despite contributing to arcade for years on Linux: I've been using OpenAL the whole time.
pyglet.media
------------------------------------------------------------------------------
audio driver: <pyglet.media.drivers.openal.adaptation.OpenALDriver object at 0x7f8929cdb430>
Interestingly, this user reported that installing PipeWire with a PulseAudio adapter layer also fixed the problem. To me, this reads as one of the following:
- PulseAudio is indeed buggy
- The design of PulseAudio may be flawed since this issue comes up surprisingly frequently in search results
I could try to install or switch to a PulseAudio adapter layer to replicate this issue, but it might be pointless.
- I have not had the exception since I installed OpenAL, it was happening once or twice a day before and has not happened since.
- Confirmed
pyglet.media.drivers.openal
------------------------------------------------------------------------------
Library: <CDLL 'libopenal.so.1', handle 3359e30 at 0x7f7bf4159960>
Version: 1.1
Extensions:
ALC_ENUMERATE_ALL_EXT
ALC_ENUMERATION_EXT
ALC_EXT_CAPTURE
ALC_EXT_DEDICATED
ALC_EXT_disconnect
ALC_EXT_EFX
ALC_EXT_thread_local_context
ALC_SOFT_device_clock
ALC_SOFT_HRTF
ALC_SOFT_loopback
ALC_SOFT_output_limiter
ALC_SOFT_pause_device
- Confirmed
pyglet.media
------------------------------------------------------------------------------
audio driver: <pyglet.media.drivers.openal.adaptation.OpenALDriver object at 0x7f7bf40bfd60>
@pushfoo - Indeed! I wasn't particularly interested in Pulse, I just didn't have OpenAL on this box. Just for the sake of anybody who finds this later... I ran this command to install OpenAL
sudo apt-get install libopenal-dev
The bug is clearly in pulse audio. It was listed as a "closed issue":
Could you please you post the following?
- The version of AVbin pyglet is using
- The miniaudio version that AVbin is using
- Your Ubuntu version
Although the issue you linked was closed in 2020, the fix might not be shipped on older LTS versions.
AVbin hasn't been part of pyglet for a while.
I personally haven't had experience with PulseAudio, just OpenAL, Xaudio2, and DirectSound. I do know PulseAudio is probably one of the oldest drivers.
AVbin hasn't been part of pyglet for a while.
This was already corrected in this comment, my apologies.
sudo apt-get install libopenal-dev
Are you sure you need need the -dev
version rather than just libopenal
? I see the following on my system:
$ dpkg -l | grep openal
ii libopenal-data 1:1.19.1-2 all Software implementation of the OpenAL audio API (data files)
ii libopenal1:amd64 1:1.19.1-2 amd64 Software implementation of the OpenAL audio API (shared library)
Either way, I think the doc solution is the best short-term option for arcade, if not pyglet. Thank you for reporting this and continuing to help with investigating it.
Even though it looks like one of the lead pyglet maintainers is already aware, the PulseAudio issues could still take a while to get resolved. Race condition bugs aren't really fun to deal with, especially when the easy workaround is to use an audio backend already present on many distros.
@pushfoo I tend to install the -dev version of stuff by default old habit - you just never know when you want to tweak something.
tend to install the -dev version of stuff by default old habit - you just never know when you want to tweak something.
I think it would make sense for anyone looking to develop pyglet with a focus on audio. Have you worked with Sphinx before?
@pushfoo no, I haven't. I'm old though ;). I had a few games published for the Playstation 1 in the late 1990s. These days I usually have guys working for me. I'm writing a zombie game for a five-year-old child of a good friend I know that loves Zombies. :)
Ah, it's a documentation library!
One thing you can do as well, is enable media debugging via pyglet.options["debug_media"] = True
. This will produce a lot of debug messages, but may provide more information when the crash occurs.
I'm old though ;).
Your experience with tech hype cycles means you'll be ready ~~when~~ if another AI winter hits.
Arcade's recent git history demonstrates the downside of Sphinx: it's powerful, yet unintuitive at best and painful at worst. However, it's probably nothing compared to the PS1 optimization and disc layout stories I've heard. :P
I'd welcome your input on either of the referencing issues linked above, or any other arcade issues. Knowledge of OOP and abstraction pitfalls from the past would be helpful to avoid repeating them.
One thing you can do as well, is enable media debugging
Thank you for pointing that out. I'll include this in the arcade doc as well. As to pyglet, what's your recommendation for how to proceed? Doc for now, full fix later?
Highlights from a brief Discord discussion with Square789:
-
At least some of the problems involved are well-understood
i've only read the linked miniaudio fix which involved additional mainloop locks; so that may be it really i do definitely know there is at least one missing lock in the PA adaptation, i just don't remember where
-
Temporary doc fixes are still a good idea
That sounds good; openal is a lot more friendly to use anyways
I would go ahead and give the latest version a try as there has been a big rework in the audio engine (2.0.14b). Hopefully that clears up the issue, if not let us know. If we haven't heard back we will assume this is stale and close this issue.
No further update from user on whether this is resolved with latest audio engine rework. Feel free to open a new request if problem persists.