Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash updating database from WebDAV source #660

Closed
gward opened this issue Oct 6, 2019 · 4 comments

Comments

@gward
Copy link
Contributor

commented Oct 6, 2019

Bug report

I've configured MPD to use WebDAV for storage using the "curl" plugin:

music_directory     "http://localhost:8080/albums/"

It crashes due to an assertion failure whenever it tries to update the database. Sometimes this happens automatically at startup, and sometimes I have to run mpc update. Either way: assertion fails, crash & coredump.

Here is the complete output of running mpd:

$ ./mpd --no-daemon --stderr /tmp/mpddav/mpd.conf
exception: bind to '0.0.0.0:6601' failed (continuing anyway, because binding to '[::]:6601' succeeded): Failed to bind socket: Address already in use
libsamplerate: libsamplerate converter 'Fastest Sinc Interpolator'
vorbis: Xiph.Org libVorbis 1.3.6
opus: libopus 1.3
sndfile: libsndfile-1.0.28
hybrid_dsd: The Hybrid DSD decoder is disabled because it was not explicitly enabled
exception: Decoder plugin 'wildmidi' is unavailable: configuration file does not exist: /etc/timidity/timidity.cfg
adplug: adplug 2.2.1
exception: Failed to open '/tmp/mpddav/mpddb': No such file or directory
output: No 'audio_output' defined in config file
output: Attempt to detect audio output device
output: Attempting to detect a alsa audio device
output: Successfully detected a alsa audio device
exception: Input plugin 'tidal' is not configured: No Tidal application token configured
exception: Input plugin 'qobuz' is not configured: No Qobuz app_id configured
curl: version 7.64.0
curl: with GnuTLS/3.6.5
avahi: Initializing interface
exception: RTIOThread could not get realtime scheduling, continuing anyway: sched_setscheduler failed: Operation not permitted
avahi: Client changed to state 2
avahi: Client is RUNNING
avahi: Registering service _mpd._tcp/Music Player @ lucifer
avahi: Service group changed to state 0
avahi: Service group is UNCOMMITED
avahi: Failed to add service _mpd._tcp: Local name collision
update: spawned thread for update job id 1
state_file: Loading state file /tmp/mpddav/mpdstate
update: starting
exception: Failed to open '/tmp/mpddav/mpdstate': No such file or directory
mpd: ../src/db/update/Walk.cxx:309: bool UpdateWalk::UpdateDirectory(Directory&, const ExcludeList&, const StorageFileInfo&): Assertion `info.IsDirectory()' failed.
zsh: abort (core dumped)  ./mpd --no-daemon --stderr /tmp/mpddav/mpd.conf

Here is my configuration file:

$ cat /tmp/mpddav/mpd.conf
music_directory     "http://localhost:8080/albums/"
playlist_directory  "/tmp/mpddav/playlists"
db_file             "/tmp/mpddav/mpddb"
log_file            "/tmp/mpddav/mpd.log"
state_file          "/tmp/mpddav/mpdstate"
log_level           "verbose"
port                "6601"

Oh yeah, I'm running from a recent source checkout:

$ git remote -v
origin	https://github.com/MusicPlayerDaemon/MPD.git (fetch)
origin	https://github.com/MusicPlayerDaemon/MPD.git (push)

$ git describe
v0.21.15-627-g2f3e94f8d

FWIW, I get pretty much the same crash with 0.20.18 (Ubuntu source package), 0.21.4 (Ubuntu binary package), and 0.21.15 (source tarball from musicpd.org). So this is not a recent bug.

Here's a gdb session with backtrace:

$ cat .gdbinit
set args --no-daemon --stderr /tmp/mpddav/mpd.conf 

$ gdb ./mpd   
GNU gdb (Ubuntu 8.2.91.20190405-0ubuntu3) 8.2.91.20190405-git
Copyright (C) 2019 Free Software Foundation, Inc.
[...]
(gdb) r
Starting program: /tmp/mpddav/MPD/build/mpd --no-daemon --stderr /tmp/mpddav/mpd.conf 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
exception: bind to '0.0.0.0:6601' failed (continuing anyway, because binding to '[::]:6601' succeeded): Failed to bind socket: Address already in use
libsamplerate: libsamplerate converter 'Fastest Sinc Interpolator'
vorbis: Xiph.Org libVorbis 1.3.6
opus: libopus 1.3
sndfile: libsndfile-1.0.28
hybrid_dsd: The Hybrid DSD decoder is disabled because it was not explicitly enabled
exception: Decoder plugin 'wildmidi' is unavailable: configuration file does not exist: /etc/timidity/timidity.cfg
adplug: adplug 2.2.1
exception: Failed to open '/tmp/mpddav/mpddb': No such file or directory
output: No 'audio_output' defined in config file
output: Attempt to detect audio output device
output: Attempting to detect a alsa audio device
[New Thread 0x7fffe3915700 (LWP 10020)]
[Thread 0x7fffe3915700 (LWP 10020) exited]
output: Successfully detected a alsa audio device
exception: Input plugin 'tidal' is not configured: No Tidal application token configured
exception: Input plugin 'qobuz' is not configured: No Qobuz app_id configured
curl: version 7.64.0
curl: with GnuTLS/3.6.5
[New Thread 0x7fffe3915700 (LWP 10021)]
[New Thread 0x7fffe7915700 (LWP 10022)]
avahi: Initializing interface
exception: RTIOThread could not get realtime scheduling, continuing anyway: sched_setscheduler failed: Operation not permitted
avahi: Client changed to state 2
avahi: Client is RUNNING
avahi: Registering service _mpd._tcp/Music Player @ lucifer
avahi: Service group changed to state 0
avahi: Service group is UNCOMMITED
avahi: Failed to add service _mpd._tcp: Local name collision
[New Thread 0x7fffe7114700 (LWP 10023)]
update: starting
update: spawned thread for update job id 1
state_file: Loading state file /tmp/mpddav/mpdstate
exception: Failed to open '/tmp/mpddav/mpdstate': No such file or directory
[New Thread 0x7fffe6913700 (LWP 10024)]
[Thread 0x7fffe6913700 (LWP 10024) exited]
mpd: ../src/db/update/Walk.cxx:309: bool UpdateWalk::UpdateDirectory(Directory&, const ExcludeList&, const StorageFileInfo&): Assertion `info.IsDirectory()' failed.

Thread 5 "update" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffe7114700 (LWP 10023)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff17f5ed7 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff17d7535 in __GI_abort () at abort.c:79
#2  0x00007ffff17d740f in __assert_fail_base
    (fmt=0x7ffff1965588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x55555576db4d "info.IsDirectory()", file=0x55555576d991 "../src/db/update/Walk.cxx", line=309, function=<optimized out>) at assert.c:92
#3  0x00007ffff17e7012 in __GI___assert_fail
    (assertion=0x55555576db4d "info.IsDirectory()", file=0x55555576d991 "../src/db/update/Walk.cxx", line=309, function=0x55555576daa0 <UpdateWalk::UpdateDirectory(Directory&, ExcludeList const&, StorageFileInfo const&)::__PRETTY_FUNCTION__> "bool UpdateWalk::UpdateDirectory(Directory&, const ExcludeList&, const StorageFileInfo&)") at assert.c:101
#4  0x00005555556d862b in UpdateWalk::UpdateDirectory(Directory&, ExcludeList const&, StorageFileInfo const&)
    (this=0x555555911030, directory=..., exclude_list=..., info=...) at ../src/db/update/Walk.cxx:309
#5  0x00005555556d8c81 in UpdateWalk::Walk(Directory&, char const*, bool)
    (this=0x555555911030, root=..., path=0x5555558d7370 "", discard=true) at ../src/db/update/Walk.cxx:480
#6  0x00005555556d5481 in UpdateService::Task() (this=0x5555558d72c0) at ../src/db/update/Service.cxx:123
#7  0x00005555556d5a2e in BindMethodDetail::BindMethodWrapperGenerator2<UpdateService, true, void (UpdateService::*)() noexcept, &UpdateService::Task, void>::Invoke(void*) (_instance=0x5555558d72c0) at ../src/util/BindMethod.hxx:189
#8  0x00005555556047da in BoundMethod<void () noexcept>::operator()() const (this=0x5555558d7310)
    at ../src/util/BindMethod.hxx:91
#9  0x0000555555608a38 in Thread::Run() (this=0x5555558d7310) at ../src/thread/Thread.cxx:63
#10 0x0000555555608a18 in Thread::ThreadProc(void*) (ctx=0x5555558d7310) at ../src/thread/Thread.cxx:92
#11 0x00007ffff19a6182 in start_thread (arg=<optimized out>) at pthread_create.c:486
#12 0x00007ffff18cfb1f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) 

Something I found curious: if I walk up the stack to UpdateWalk::Walk(), I don't find my music_directory URL anywhere. Both root and path are the empty string:

(gdb) up
#5  0x00005555556d8c81 in UpdateWalk::Walk (this=0x555555911030, root=..., path=0x5555558d7370 "", discard=true)
    at ../src/db/update/Walk.cxx:480
480			UpdateDirectory(root, exclude_list, info);
(gdb) p root.path
$1 = ""
(gdb) p path
$2 = 0x5555558d7370 ""

No idea if that is relevant.

Version

$ ./mpd --version
Music Player Daemon 0.22~git (v0.21.15-627-g2f3e94f8d)
Copyright 2003-2007 Warren Dukes <warren.dukes@gmail.com>
Copyright 2008-2018 Max Kellermann <max.kellermann@gmail.com>
This is free software; see the source for copying conditions.  There is NO
warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Database plugins:
 simple proxy upnp

Storage plugins:
 local smbclient udisks nfs curl

Neighbor plugins:
 smbclient upnp udisks

Decoders plugins:
 [mad] mp3 mp2
 [mpg123] mp3
 [vorbis] ogg oga
 [oggflac] ogg oga
 [flac] flac
 [opus] opus ogg oga
 [sndfile] wav aiff aif au snd paf iff svx sf voc w64 pvf xi htk caf sd2
 [audiofile] wav au aiff aif
 [dsdiff] dff
 [dsf] dsf
 [hybrid_dsd] m4a
 [faad] aac
 [mpcdec] mpc
 [wavpack] wv
 [modplug] 669 amf ams dbm dfm dsm far it med mdl mod mtm mt2 okt s3m stm ult umx xm
 [mikmod] amf dsm far gdm imf it med mod mtm s3m stm stx ult uni xm
 [sidplay] sid mus str prg P00
 [wildmidi] mid
 [fluidsynth] mid
 [adplug] amd d00 hsc laa rad raw sa2
 [ffmpeg] 16sv 3g2 3gp 4xm 8svx aa3 aac ac3 adx afc aif aifc aiff al alaw amr anim apc ape asf atrac au aud avi avm2 avs bap bfi c93 cak cin cmv cpk daud dct divx dts dv dvd dxa eac3 film flac flc fli fll flx flv g726 gsm gxf iss m1v m2v m2t m2ts m4a m4b m4v mad mj2 mjpeg mjpg mka mkv mlp mm mmf mov mp+ mp1 mp2 mp3 mp4 mpc mpeg mpg mpga mpp mpu mve mvi mxf nc nsv nut nuv oga ogm ogv ogx oma ogg omg opus psp pva qcp qt r3d ra ram rl2 rm rmvb roq rpl rvc shn smk snd sol son spx str swf tak tgi tgq tgv thp ts tsp tta xa xvid uv uv2 vb vid vob voc vp6 vmd wav webm wma wmv wsaud wsvga wv wve
 [gme] ay gbs gym hes kss nsf nsfe sap spc vgm vgz
 [pcm]

Filters:
 libsamplerate soxr

Tag plugins:
 id3tag

Output plugins:
 shout null fifo pipe alsa ao openal pulse jack httpd recorder

Encoder plugins:
 null vorbis opus lame wave flac

Archive plugins:
 [bz2] bz2
 [zzip] zip
 [iso] iso

Input plugins:
 file archive alsa tidal qobuz curl ffmpeg smbclient nfs mms cdio_paranoia

Playlist plugins:
 extm3u m3u pls xspf asx rss soundcloud flac cue embcue

Protocols:
 file:// alsa:// cdda:// ftp:// ftps:// gopher:// http:// https:// mms:// mmsh:// mmst:// mmsu:// nfs:// qobuz:// rtmp:// rtmps:// rtmpt:// rtmpts:// rtp:// scp:// sftp:// smb:// srtp:// tidal://

Other features:
 avahi dbus udisks epoll icu inotify ipv6 systemd tcp un
@gward

This comment has been minimized.

Copy link
Contributor Author

commented Oct 6, 2019

Oh yeah: my WebDAV server is Apache 2.4, from the Ubuntu package (2.4.38-2ubuntu2.3). The best evidence that MPD is talking to Apache as a WebDAV server is one line from Apache's access log right before MPD crashes:

lucifer.local:8080 127.0.0.1 - - [06/Oct/2019:18:16:37 -0400] "PROPFIND /albums/ HTTP/1.1" 207 458 "-" "Music Player Daemon 0.22~git"

The best evidence that Apache is providing a working WebDAV server: I can open dav://localhost:8080/albums/ in my file browser, and I see exactly what I expect to see -- a directory full of albums.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Oct 7, 2019

This is a combination of two bugs:

  • the database update crashes if the music_directory is not a directory
  • the WebDAV client requires status=200 OK, but your Apache replies with 207 Multi-Status did not request the resourcetype property
MaxKellermann added a commit that referenced this issue Oct 7, 2019
Without requesting the property, "good" WebDAV servers would not send
it, and so MPD could never recognize a directory, failing the database
update.

Closes #660
@gward

This comment has been minimized.

Copy link
Contributor Author

commented Oct 7, 2019

Confirmed: the commits that @MaxKellermann pushed to branch v0.21.x fix this bug -- MPD no longer crashes as soon as it starts updating from webdav storage. Thank you!

However, it looks like there are still problems updating from WebDAV. I'll open another ticket for the next crash...

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Oct 7, 2019

Yes please go ahead, your bug report was very good and made the fix easy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.