qemu-char: convert stdio backend to data-driven creation
The backend now always returns errors via the Error* argument. This avoids a double error message. Before: qemu-system-x86_64: -chardev stdio,id=base: cannot use stdio with -daemonize qemu-system-x86_64: -chardev stdio,id=base: Failed to create chardev After: qemu-system-x86_64: -chardev stdio,id=base: cannot use stdio with -daemonize Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
0498790173
commit
8c84b25d97
57
qemu-char.c
57
qemu-char.c
@ -1168,19 +1168,23 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
|
|||||||
fd_chr_close(chr);
|
fd_chr_close(chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
static CharDriverState *qemu_chr_open_stdio(const char *id,
|
||||||
|
ChardevBackend *backend,
|
||||||
|
ChardevReturn *ret,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
ChardevStdio *opts = backend->stdio;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
|
||||||
if (is_daemonized()) {
|
if (is_daemonized()) {
|
||||||
error_report("cannot use stdio with -daemonize");
|
error_setg(errp, "cannot use stdio with -daemonize");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdio_in_use) {
|
if (stdio_in_use) {
|
||||||
error_report("cannot use stdio by multiple character devices");
|
error_setg(errp, "cannot use stdio by multiple character devices");
|
||||||
exit(1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stdio_in_use = true;
|
stdio_in_use = true;
|
||||||
@ -2341,7 +2345,10 @@ static void win_stdio_close(CharDriverState *chr)
|
|||||||
g_free(chr);
|
g_free(chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
static CharDriverState *qemu_chr_open_stdio(const char *id,
|
||||||
|
ChardevBackend *backend,
|
||||||
|
ChardevReturn *ret,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
WinStdioCharState *stdio;
|
WinStdioCharState *stdio;
|
||||||
@ -2353,8 +2360,8 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
|
|
||||||
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
|
if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "cannot open stdio: invalid handle\n");
|
error_setg(errp, "cannot open stdio: invalid handle");
|
||||||
exit(1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
|
is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
|
||||||
@ -2366,25 +2373,30 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
if (is_console) {
|
if (is_console) {
|
||||||
if (qemu_add_wait_object(stdio->hStdIn,
|
if (qemu_add_wait_object(stdio->hStdIn,
|
||||||
win_stdio_wait_func, chr)) {
|
win_stdio_wait_func, chr)) {
|
||||||
fprintf(stderr, "qemu_add_wait_object: failed\n");
|
error_setg(errp, "qemu_add_wait_object: failed");
|
||||||
|
goto err1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DWORD dwId;
|
DWORD dwId;
|
||||||
|
|
||||||
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
|
if (stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
|
||||||
chr, 0, &dwId);
|
|
||||||
|
|
||||||
if (stdio->hInputThread == INVALID_HANDLE_VALUE
|
|
||||||
|| stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
|
|
||||||
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
|
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "cannot create stdio thread or event\n");
|
error_setg(errp, "cannot create event");
|
||||||
exit(1);
|
goto err2;
|
||||||
}
|
}
|
||||||
if (qemu_add_wait_object(stdio->hInputReadyEvent,
|
if (qemu_add_wait_object(stdio->hInputReadyEvent,
|
||||||
win_stdio_thread_wait_func, chr)) {
|
win_stdio_thread_wait_func, chr)) {
|
||||||
fprintf(stderr, "qemu_add_wait_object: failed\n");
|
error_setg(errp, "qemu_add_wait_object: failed");
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
|
||||||
|
chr, 0, &dwId);
|
||||||
|
|
||||||
|
if (stdio->hInputThread == INVALID_HANDLE_VALUE) {
|
||||||
|
error_setg(errp, "cannot create stdio thread");
|
||||||
|
goto err3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2402,6 +2414,15 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
qemu_chr_fe_set_echo(chr, false);
|
qemu_chr_fe_set_echo(chr, false);
|
||||||
|
|
||||||
return chr;
|
return chr;
|
||||||
|
|
||||||
|
err3:
|
||||||
|
qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
|
||||||
|
err2:
|
||||||
|
CloseHandle(stdio->hInputReadyEvent);
|
||||||
|
CloseHandle(stdio->hInputDoneEvent);
|
||||||
|
err1:
|
||||||
|
qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif /* !_WIN32 */
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
@ -4321,7 +4342,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
|||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
case CHARDEV_BACKEND_KIND_STDIO:
|
case CHARDEV_BACKEND_KIND_STDIO:
|
||||||
chr = qemu_chr_open_stdio(backend->stdio);
|
abort();
|
||||||
break;
|
break;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
case CHARDEV_BACKEND_KIND_CONSOLE:
|
case CHARDEV_BACKEND_KIND_CONSOLE:
|
||||||
@ -4411,7 +4432,7 @@ static void register_types(void)
|
|||||||
register_char_driver("file", CHARDEV_BACKEND_KIND_FILE,
|
register_char_driver("file", CHARDEV_BACKEND_KIND_FILE,
|
||||||
qemu_chr_parse_file_out, qmp_chardev_open_file);
|
qemu_chr_parse_file_out, qmp_chardev_open_file);
|
||||||
register_char_driver("stdio", CHARDEV_BACKEND_KIND_STDIO,
|
register_char_driver("stdio", CHARDEV_BACKEND_KIND_STDIO,
|
||||||
qemu_chr_parse_stdio, NULL);
|
qemu_chr_parse_stdio, qemu_chr_open_stdio);
|
||||||
#if defined HAVE_CHARDEV_SERIAL
|
#if defined HAVE_CHARDEV_SERIAL
|
||||||
register_char_driver("serial", CHARDEV_BACKEND_KIND_SERIAL,
|
register_char_driver("serial", CHARDEV_BACKEND_KIND_SERIAL,
|
||||||
qemu_chr_parse_serial, qmp_chardev_open_serial);
|
qemu_chr_parse_serial, qmp_chardev_open_serial);
|
||||||
|
Loading…
Reference in New Issue
Block a user