]> git.ktnx.net Git - mpd-feeder.git/commitdiff
rework idling again, walking around Net::Async::MPD interface
authorDamyan Ivanov <dmn@debian.org>
Sun, 21 Nov 2021 08:44:35 +0000 (08:44 +0000)
committerDamyan Ivanov <dmn@debian.org>
Sun, 21 Nov 2021 08:44:35 +0000 (08:44 +0000)
thing is, that the ->noidle() call places readers on the mpd handle,
because it uses ->send(). this interferes with the expected protocol
flow like this:

idle() is called, a reader/parser is queued by ->send()
when noidle is called, it calls send(), which queues another reader/parser
MPD sees the 'noidle' command and responds with plain 'OK', which is
consumed by the readers queued by idle(). this by itself causes a crash
because the is no "result" and ->{changes} is invoked on undefined value

it the undef deref is fixed, the protocol still hangs, because of the
extra readers queued, which consumes the reply of the next command
issued (e.g. 'playlist')

the other thing that doesn't work is the link check in mpd-feeder. on
timer, it wants to break out of 'idle' waiting just to be sure that the
connection is alive. this also causes dereferencing of an undefined
value and protocol lock up.

so, instead, the idle/noidle is implemented half under-the-table.
idle is implemented via ordinary send(), and broken by a crude call to
mpd->{mpd_handle}->write(), breaking API. this serves two purposes.
first, the readers queued by send() see toe 'OK' resulting from noidle
and return empty result, which is handled by Feeder without crashing.
second, sending a low-level 'noidle' command via the connection handle
avoids queuing extra reader which would cause protocol hang.

the result is that periodic connection checks (leaving and re-entering
idle) work, idle events (which put MPD out of idle mode) are handled
outside of 'idleness' as they should be, asynchronous signals
(TERM, INT, etc.) work as expected outside of 'idleness'. happy camping
all around!


No differences found