MacOS – mpd stuttering when run under launchd

audiohomebrewlaunchdmacos

Background

As a terminal junkie, I've started messing around with a combination of mpd (Music Player Daemon) and a player, ncmpcpp (NCurses Media Player Client C++).

I installed these via Homebrew – a simple brew install mpd ncmpcpp. A bit of configuration later, and the apps are running quite nicely. The effect is actually rather impressive:
ncmpcpp playing some random things

The problem I run into is when I want to run mpd automatically instead of having it launch in my terminal. It comes with a launchd plist, so I install that, and it appears to work – The problem is that whatever I'm playing, be that an MP3, streaming audio from a server, or whatever, the audio stutters every 5 seconds

This absolutely does not happen when mpd is invoked directly from the command line, only when it's fired off via launchd.

Here's what the plist looks like:

<!--homebrew.mxcl.mpd.plist-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>homebrew.mxcl.mpd</string>
    <key>ProcessType</key>
    <string>Interactive</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/opt/mpd/bin/mpd</string>
        <string>--no-daemon</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/usr/local</string>
</dict>

The ProcessType interactive was added by me in an attempt to force launchd to give the daemon higher priority, to no effect.

Debugging?

If we dtruss the process, there is a huge blast of identical gettimeofday messages correlated with every stutter. It looks like this:

gettimeofday(0x10A03FD40, 0x0, 0x1000)       = 1428698761 0

Things I've already eliminated

  • CPU / Disk IO

The system is relatively quiet – during the stutters, mpd is not even on the top 25 for memory or CPU usage, and load is well below 1.0

  • Incorrect environment causing bad config settings to be loaded

My mpd config is the one being loaded from ~/.mpdconf – same as it is when I run it by hand.

This appears to be a symptom of the way launchd chooses to handle the process.

The ultimate question

Why is the daemon so misbehaved when run under launchd, but not when run via terminal?

Bonus question:

What about the way launchd kicks off processes could be making this behavior manifest?

Best Answer

I had the similar issue and google led me to this thread. Now I have a solution to the problem if someone else find this.

Just remove the --no-daemon line.

This seems to work fine:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>homebrew.mxcl.mpd</string>
    <key>WorkingDirectory</key>
    <string>/usr/local</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/opt/mpd/bin/mpd</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>