Opened 10 years ago

Last modified 10 years ago

#1584 new defect

No sound after mplayer restart (AO_ALSA)

Reported by: spinal.by@… Owned by: reimar
Priority: normal Component: ao
Version: 1.0rc2 Severity: normal
Keywords: Cc:
Blocked By: Blocking:
Reproduced by developer: Analyzed by developer:

Description

I'm using mplayer version 1.0_rc2_p20090731 which is current Gentoo stable.
I have mplayer and xscreensaver installed.
To disable xscreensaver I added this line to mplayer.conf:
heartbeat-cmd="/usr/bin/xscreensaver-command -deactivate &> /dev/null &"

There's several ways to reproduce the bug. The most reliable is this:
1) Run mplayer:
mplayer <PATH_TO_SOME_MOVIE_WITH_SOUND>
2) Exit mplayer immediately after it's started (press q)
3) Now restart mplayer as soon as possible:
mplayer <PATH_TO_SOME_MOVIE_WITH_SOUND>

You will not get the sound. And you will get the error similar to this:
[AO_ALSA] alsa-lib: pcm_dmix.c:1008:(snd_pcm_dmix_open) unable to open slave

When the line "heartbeat-cmd=..." is removed from mplayer.conf, this error disappears.

To debug I run this command after quitting mplayer:

~ $ fuser -v /dev/snd/*

USER PID ACCESS COMMAND

/dev/snd/controlC0: spinal 30849 F.... xfce4-mixer-plu
/dev/snd/pcmC0D0p: spinal 6617 F.... xscreensaver-co
/dev/snd/timer: spinal 6617 f.... xscreensaver-co

PID 6617 - is out heartbeat-cmd obviously.

P.S. Some other ways to reproduce the bug:

  • Rapidly changing currently playing movie in smplayer
  • Sometimes it's enough just to quit mplayer and start it again in some "unlucky" period of time.

Regardz.

Attachments (1)

alsa_cloexec.diff (900 bytes) - added by reimar 10 years ago.
Try to set CLOEXEC on ALSA fds

Download all attachments as: .zip

Change History (7)

comment:1 Changed 10 years ago by reimar

This looks like an issue in ALSA to me.
While I can't say what the exact issue with dmix is, I am quite certain that ALSA should set O_CLOEXEC for all the /dev/snd stuff it opens.
It has been discussed here: http://mailman.alsa-project.org/pipermail/alsa-devel/2009-May/017784.html but no idea if anything came of it.
In another thread they say that it is supposed to be fixed from MPlayer side, however nobody was able to name a way how to do it:
http://www.mail-archive.com/alsa-devel@lists.sourceforge.net/msg06390.html
Not to mention that many of the API suggestions can't be used with system() but would require fork() and exec().
If you can get some information on how this is supposed to work it is easily implemented - until then I can only recommend to use something else like -ao oss (certain to not have _this specific_ issue), or -ao openal or -ao sdl (and hope they figured how to avoid this problem).
Of course, another "issue"/question is why the heartbeat command takes long enough to execute for this to matter.

Changed 10 years ago by reimar

Try to set CLOEXEC on ALSA fds

comment:2 Changed 10 years ago by reimar

This is ugly and possibly incomplete, but maybe you could test it anyway, maybe it is good enough.

comment:3 Changed 10 years ago by spinal.by@…

(In reply to comment #2)

Created an attachment (id=593) [details]
Try to set CLOEXEC on ALSA fds

This is ugly and possibly incomplete, but maybe you could test it anyway, maybe
it is good enough.

Hello, Reimar.
Thanks for your quick response.
I tested the patch.

Here's the output you will probably be interested in:
====
While mplayer's running:
$ fuser -v /dev/snd/*

USER PID ACCESS COMMAND

/dev/snd/controlC0: spinal 3150 F.... xfce4-mixer-plu
/dev/snd/pcmC0D0p: spinal 3312 F...m mplayer

spinal 3314 F.... xscreensaver-co

/dev/snd/timer: spinal 3312 f.... mplayer
===
After mplayer terminated:
$ fuser -v /dev/snd/*

USER PID ACCESS COMMAND

/dev/snd/controlC0: spinal 3150 F.... xfce4-mixer-plu
/dev/snd/pcmC0D0p: spinal 3314 F.... xscreensaver-co

The difference is that /dev/snd/timer is not locked by heartbeat-cmd anymore, but /dev/snd/pcmC0D0p still remains.

P.S. Having such a rapid response on bugs is such a rare case...
Thanks!

comment:4 Changed 10 years ago by reimar

Ok, I unfortunately see no way of getting the file descriptor for the /dev/snd/pcmC0D0p which for what I can tell leaves only two options:
1) going through all possible file descriptor values, setting CLOEXEC on all fds
2) replacing system() by fork() and exec() and closing all file descriptors in-between
3) maximum uglyiness: do an open in ao_alsa, check which fd you got, close it again, at the end after all ALSA initialization is done, set CLOEXEC on about the next 100 fds from that one. Very brittle, not going to work if ALSA opens more files during playback, relies on very strict POSIX semantics, making it even more impossible to ever use ALSA e.g. on WinCE etc., might set CLOEXEC on things we actually didn't want to set e.g. if MPlayer ever becomes multi-threaded - a complete maintenance nightmare.

Issues for 1) and 2):
going through all file descriptors (necessary for both) is not only ugly and a waste of time, but also would be OS-specific, since WinCE can e.g. have negative values for file descriptors, and it doesn't pick the lowest free one in general. This violates POSIX, but that still doesn't change the fact. Which would mean calling close/fcntl almost 4 billion times before each execution unless as said the code is made OS-specific (making it even uglier).
Setting CLOEXEC on all in general may have undesired behaviour in the future, e.g. there were patches implementing Windows 32 bit codec support via a 32 bit binary stub.
Replacing system() by fork() and exec() would be a portability issue, system() is more widely supported than fork().
Given these I only see two reasonable ways of "fixing" this
1) change ALSA - either so you can get a full list of the fds it has open or that you can make it set CLOEXEC on them
2) fix xscreensaver-command. IMO it really should not take more than about a millisecond to run, so it should be basically impossible to perceive this issue.

Well, and of course: just don't use ALSA, at least not directly. Not that I can actually recommend any _good_ alternative.

comment:5 Changed 10 years ago by spinal.by@…

Hm, as I understand you, there's a missing feature in ALSA API.
I gonna contact ALSA team with their bugzilla. The problem is I don't understand clearly what's wrong with ALSA.
Could you please particularly explain, what should be done on ALSA side to make this bug resolved right?

P.S. I contacted xscreensaver maintainer at the same time I created this bug report, but didn't get any answer yet.

comment:6 Changed 10 years ago by spinal.by@…

Hi, Reimar.
Maybe you have a patch for alsa that could help you to fix the issue ?

Regardz.

Note: See TracTickets for help on using tickets.