From ca450663d09b0e467292aaa17f636db71b95d574 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Tue, 20 Aug 2019 20:01:53 +0200
Subject: [PATCH] decoder/Control: work around crash after SEEK was too late

See code comment.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/629
---
 NEWS                    |  2 ++
 src/decoder/Control.cxx | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/NEWS b/NEWS
index acc735d2e..56ce212c9 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ ver 0.21.14 (not yet released)
   - sidplay: show track durations in database
   - sidplay: convert tag values from Windows-1252 charset
   - sidplay: strip text from "Date" tag
+* player
+  - fix crash after song change
 
 ver 0.21.13 (2019/08/06)
 * input
diff --git a/src/decoder/Control.cxx b/src/decoder/Control.cxx
index 5faa23fe5..cf8a74385 100644
--- a/src/decoder/Control.cxx
+++ b/src/decoder/Control.cxx
@@ -147,6 +147,18 @@ DecoderControl::Seek(SongTime t)
 	seek_error = false;
 	SynchronousCommandLocked(DecoderCommand::SEEK);
 
+	while (state == DecoderState::START)
+		/* If the decoder falls back to DecoderState::START,
+		   this means that our SEEK command arrived too late,
+		   and the decoder had meanwhile finished decoding and
+		   went idle.  Our SEEK command is finished, but that
+		   means only that the decoder thread has launched the
+		   decoder.  To work around illegal states, we wait
+		   until the decoder plugin has become ready.  This is
+		   a kludge, built on top of the "late seek" kludge.
+		   Not exactly elegant, sorry. */
+		WaitForDecoder();
+
 	if (seek_error)
 		throw std::runtime_error("Decoder failed to seek");
 }