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>
This commit is contained in:
Marc-André Lureau 2016-08-01 15:23:43 +04:00 committed by Markus Armbruster
parent 2ef45716e1
commit a384c205ac
4 changed files with 24 additions and 18 deletions

View File

@ -1739,13 +1739,21 @@ static void audio_vm_change_state_handler (void *opaque, int running,
audio_reset_timer (s); 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; AudioState *s = &glob_audio_state;
HWVoiceOut *hwo = NULL; HWVoiceOut *hwo, *hwon;
HWVoiceIn *hwi = NULL; 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; SWVoiceCap *sc;
if (hwo->enabled) { if (hwo->enabled) {
@ -1761,17 +1769,20 @@ static void audio_atexit (void)
cb->ops.destroy (cb->opaque); 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) { if (hwi->enabled) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
} }
hwi->pcm_ops->fini_in (hwi); hwi->pcm_ops->fini_in (hwi);
QLIST_REMOVE(hwi, entries);
} }
if (s->drv) { if (s->drv) {
s->drv->fini (s->drv_opaque); 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_out);
QLIST_INIT (&s->hw_head_in); QLIST_INIT (&s->hw_head_in);
QLIST_INIT (&s->cap_head); QLIST_INIT (&s->cap_head);
atexit (audio_atexit); atexit(audio_cleanup);
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); 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 (&s->cap_head, cap, entries);
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries); QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
hw = NULL; QLIST_FOREACH(hw, &glob_audio_state.hw_head_out, entries) {
while ((hw = audio_pcm_hw_find_any_out (hw))) {
audio_attach_capture (hw); audio_attach_capture (hw);
} }
return cap; return cap;

View File

@ -163,4 +163,7 @@ static inline void *advance (void *p, int incr)
int wav_start_capture (CaptureState *s, const char *path, int freq, int wav_start_capture (CaptureState *s, const char *path, int freq,
int bits, int nchannels); int bits, int nchannels);
bool audio_is_cleaning_up(void);
void audio_cleanup(void);
#endif /* QEMU_AUDIO_H */ #endif /* QEMU_AUDIO_H */

View File

@ -36,8 +36,6 @@
#define MAC_OS_X_VERSION_10_6 1060 #define MAC_OS_X_VERSION_10_6 1060
#endif #endif
static int isAtexit;
typedef struct { typedef struct {
int buffer_frames; int buffer_frames;
int nbuffers; int nbuffers;
@ -378,11 +376,6 @@ static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
return result; return result;
} }
static void coreaudio_atexit (void)
{
isAtexit = 1;
}
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
{ {
int err; int err;
@ -630,7 +623,7 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
int err; int err;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
if (!isAtexit) { if (!audio_is_cleaning_up()) {
/* stop playback */ /* stop playback */
if (isPlaying(core->outputDeviceID)) { if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, core->ioprocid); status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
@ -673,7 +666,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
case VOICE_DISABLE: case VOICE_DISABLE:
/* stop playback */ /* stop playback */
if (!isAtexit) { if (!audio_is_cleaning_up()) {
if (isPlaying(core->outputDeviceID)) { if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, status = AudioDeviceStop(core->outputDeviceID,
core->ioprocid); core->ioprocid);
@ -697,7 +690,6 @@ static void *coreaudio_audio_init (void)
CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf)); CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
*conf = glob_conf; *conf = glob_conf;
atexit(coreaudio_atexit);
return conf; return conf;
} }

1
vl.c
View File

@ -4612,6 +4612,7 @@ int main(int argc, char **argv, char **envp)
/* vhost-user must be cleaned up before chardevs. */ /* vhost-user must be cleaned up before chardevs. */
net_cleanup(); net_cleanup();
audio_cleanup();
monitor_cleanup(); monitor_cleanup();
qemu_chr_cleanup(); qemu_chr_cleanup();