diff --git a/src/decoder_control.c b/src/decoder_control.c
index b934d516f6409c558bf3b0b77fb415fff567d7ea..6d2efd0d7c1c047c2b59579c3b57c075fc42ccc9 100644
--- a/src/decoder_control.c
+++ b/src/decoder_control.c
@@ -102,8 +102,13 @@ dc_seek(struct notify *notify, double where)
 }
 
 void
-dc_quit(struct notify *notify)
+dc_quit(void)
 {
+	assert(dc.thread != NULL);
+
 	dc.quit = true;
-	dc_command(notify, DECODE_COMMAND_STOP);
+	dc_command_async(DECODE_COMMAND_STOP);
+
+	g_thread_join(dc.thread);
+	dc.thread = NULL;
 }
diff --git a/src/decoder_control.h b/src/decoder_control.h
index 4fd0f9edc091ba57a85d0072f141053b92cc608c..542cfe78a5378be4433fccee716e64928a0bb353 100644
--- a/src/decoder_control.h
+++ b/src/decoder_control.h
@@ -45,6 +45,10 @@ enum decoder_state {
 };
 
 struct decoder_control {
+	/** the handle of the decoder thread, or NULL if the decoder
+	    thread isn't running */
+	GThread *thread;
+
 	struct notify notify;
 
 	volatile enum decoder_state state;
@@ -124,6 +128,6 @@ bool
 dc_seek(struct notify *notify, double where);
 
 void
-dc_quit(struct notify *notify);
+dc_quit(void);
 
 #endif
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index 12449237fd47dfc6665293553712127e30d75496..97555f44d524a04b03490e754b1e3107286daa88 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -258,8 +258,10 @@ static gpointer decoder_task(G_GNUC_UNUSED gpointer arg)
 void decoder_thread_start(void)
 {
 	GError *e = NULL;
-	GThread *t;
 
-	if (!(t = g_thread_create(decoder_task, NULL, FALSE, &e)))
+	assert(dc.thread == NULL);
+
+	dc.thread = g_thread_create(decoder_task, NULL, true, &e);
+	if (dc.thread == NULL)
 		FATAL("Failed to spawn decoder task: %s\n", e->message);
 }
diff --git a/src/player_thread.c b/src/player_thread.c
index c5060fcb498068fccdc959c149f88c5b5fe2d399..dc263b6adaaf6c6820fa37d8c01d6bb9eeda3507 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -526,7 +526,7 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
 			break;
 
 		case PLAYER_COMMAND_EXIT:
-			dc_quit(&pc.notify);
+			dc_quit();
 			closeAudioDevice();
 			player_command_finished();
 			g_thread_exit(NULL);