aboutsummaryrefslogtreecommitdiff
path: root/audio/audio.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2016-08-01 15:23:43 +0400
committerMarkus Armbruster <armbru@redhat.com>2016-08-08 14:17:00 +0200
commita384c205acaa4b6fe6d4d392af47b49b2c448eb4 (patch)
treee4169ed10e099e09ce4fa4209ac29fb9afa36a0d /audio/audio.c
parent2ef45716e1d4820f10a90ee2f17a9cb4fe5a8806 (diff)
audio: clean up before monitor clean up
Since aa5cb7f5e, the chardevs are being cleaned up when leaving qemu, before the atexit() handlers. audio_cleanup() may use the monitor to notify of changes. For compatibility reasons, let's clean up audio before the monitor so it keeps emitting monitor events. The audio_atexit() function is made idempotent (so it can be called multiple times), and renamed to audio_cleanup(). Since coreaudio backend is using a 'isAtexit' code path, change it to check audio_is_cleaning_up() instead, so the path is taken during normal exit. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20160801112343.29082-3-marcandre.lureau@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
Diffstat (limited to 'audio/audio.c')
-rw-r--r--audio/audio.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 9d4dcc72dd..c845a44f0a 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1739,13 +1739,21 @@ static void audio_vm_change_state_handler (void *opaque, int running,
audio_reset_timer (s);
}
-static void audio_atexit (void)
+static bool is_cleaning_up;
+
+bool audio_is_cleaning_up(void)
+{
+ return is_cleaning_up;
+}
+
+void audio_cleanup(void)
{
AudioState *s = &glob_audio_state;
- HWVoiceOut *hwo = NULL;
- HWVoiceIn *hwi = NULL;
+ HWVoiceOut *hwo, *hwon;
+ HWVoiceIn *hwi, *hwin;
- while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
+ is_cleaning_up = true;
+ QLIST_FOREACH_SAFE(hwo, &glob_audio_state.hw_head_out, entries, hwon) {
SWVoiceCap *sc;
if (hwo->enabled) {
@@ -1761,17 +1769,20 @@ static void audio_atexit (void)
cb->ops.destroy (cb->opaque);
}
}
+ QLIST_REMOVE(hwo, entries);
}
- while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
+ QLIST_FOREACH_SAFE(hwi, &glob_audio_state.hw_head_in, entries, hwin) {
if (hwi->enabled) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
}
hwi->pcm_ops->fini_in (hwi);
+ QLIST_REMOVE(hwi, entries);
}
if (s->drv) {
s->drv->fini (s->drv_opaque);
+ s->drv = NULL;
}
}
@@ -1799,7 +1810,7 @@ static void audio_init (void)
QLIST_INIT (&s->hw_head_out);
QLIST_INIT (&s->hw_head_in);
QLIST_INIT (&s->cap_head);
- atexit (audio_atexit);
+ atexit(audio_cleanup);
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
@@ -1966,8 +1977,7 @@ CaptureVoiceOut *AUD_add_capture (
QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
- hw = NULL;
- while ((hw = audio_pcm_hw_find_any_out (hw))) {
+ QLIST_FOREACH(hw, &glob_audio_state.hw_head_out, entries) {
audio_attach_capture (hw);
}
return cap;