audio: exit(1) if audio backend failed to be found or initialized

If you specify a known backend but it isn't compiled in, or failed to
initialize, you get a simple warning and the "none" backend as a
fallback, and QEMU runs happily:

$ qemu-system-x86_64 -audiodev id=audio,driver=dsound
audio: Unknown audio driver `dsound'
audio: warning: Using timer based audio emulation
...

Instead, QEMU should fail to start:
$ qemu-system-x86_64 -audiodev id=audio,driver=dsound
audio: Unknown audio driver `dsound'
$

Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1983493

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Volker Rümelin <vr_qemu@t-online.de>
Message-Id: <20220822131021.975656-1-marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2022-08-22 17:10:21 +04:00
parent 0370f239ad
commit 0f957c53c8
3 changed files with 15 additions and 5 deletions

View file

@ -1743,7 +1743,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
atexit(audio_cleanup); atexit(audio_cleanup);
atexit_registered = true; atexit_registered = true;
} }
QTAILQ_INSERT_TAIL(&audio_states, s, list);
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
@ -1769,6 +1768,10 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
} else { } else {
dolog ("Unknown audio driver `%s'\n", drvname); dolog ("Unknown audio driver `%s'\n", drvname);
} }
if (!done) {
free_audio_state(s);
return NULL;
}
} else { } else {
for (i = 0; audio_prio_list[i]; i++) { for (i = 0; audio_prio_list[i]; i++) {
AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]); AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]);
@ -1806,6 +1809,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
"(Audio can continue looping even after stopping the VM)\n"); "(Audio can continue looping even after stopping the VM)\n");
} }
QTAILQ_INSERT_TAIL(&audio_states, s, list);
QLIST_INIT (&s->card_head); QLIST_INIT (&s->card_head);
vmstate_register (NULL, 0, &vmstate_audio, s); vmstate_register (NULL, 0, &vmstate_audio, s);
return s; return s;
@ -2119,13 +2123,17 @@ void audio_define(Audiodev *dev)
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
} }
void audio_init_audiodevs(void) bool audio_init_audiodevs(void)
{ {
AudiodevListEntry *e; AudiodevListEntry *e;
QSIMPLEQ_FOREACH(e, &audiodevs, next) { QSIMPLEQ_FOREACH(e, &audiodevs, next) {
audio_init(e->dev, NULL); if (!audio_init(e->dev, NULL)) {
return false;
}
} }
return true;
} }
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)

View file

@ -170,7 +170,7 @@ void audio_sample_from_uint64(void *samples, int pos,
void audio_define(Audiodev *audio); void audio_define(Audiodev *audio);
void audio_parse_option(const char *opt); void audio_parse_option(const char *opt);
void audio_init_audiodevs(void); bool audio_init_audiodevs(void);
void audio_legacy_help(void); void audio_legacy_help(void);
AudioState *audio_state_by_name(const char *name); AudioState *audio_state_by_name(const char *name);

View file

@ -1885,7 +1885,9 @@ static void qemu_create_early_backends(void)
* setting machine properties, so they can be referred to. * setting machine properties, so they can be referred to.
*/ */
configure_blockdev(&bdo_queue, machine_class, snapshot); configure_blockdev(&bdo_queue, machine_class, snapshot);
audio_init_audiodevs(); if (!audio_init_audiodevs()) {
exit(1);
}
} }