char: make chr_fe_deinit() optionaly delete backend
This simplifies removing a backend for a frontend user (no need to retrieve the associated driver and separate delete call etc). NB: many frontends have questionable handling of ending a chardev. They should probably delete the backend to prevent broken reusage. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
parent
a9b1ca38c2
commit
1ce2610c10
|
@ -145,7 +145,7 @@ static void rng_egd_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
RngEgd *s = RNG_EGD(obj);
|
RngEgd *s = RNG_EGD(obj);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&s->chr);
|
qemu_chr_fe_deinit(&s->chr, false);
|
||||||
g_free(s->chr_name);
|
g_free(s->chr_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ unavailable:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_chr_fe_deinit(CharBackend *b)
|
void qemu_chr_fe_deinit(CharBackend *b, bool del)
|
||||||
{
|
{
|
||||||
assert(b);
|
assert(b);
|
||||||
|
|
||||||
|
@ -224,6 +224,9 @@ void qemu_chr_fe_deinit(CharBackend *b)
|
||||||
MuxChardev *d = MUX_CHARDEV(b->chr);
|
MuxChardev *d = MUX_CHARDEV(b->chr);
|
||||||
d->backends[b->tag] = NULL;
|
d->backends[b->tag] = NULL;
|
||||||
}
|
}
|
||||||
|
if (del) {
|
||||||
|
object_unparent(OBJECT(b->chr));
|
||||||
|
}
|
||||||
b->chr = NULL;
|
b->chr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ static void char_mux_finalize(Object *obj)
|
||||||
be->chr = NULL;
|
be->chr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qemu_chr_fe_deinit(&d->chr);
|
qemu_chr_fe_deinit(&d->chr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
|
void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
|
||||||
|
|
15
gdbstub.c
15
gdbstub.c
|
@ -1678,9 +1678,6 @@ void gdb_exit(CPUArchState *env, int code)
|
||||||
{
|
{
|
||||||
GDBState *s;
|
GDBState *s;
|
||||||
char buf[4];
|
char buf[4];
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
Chardev *chr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s = gdbserver_state;
|
s = gdbserver_state;
|
||||||
if (!s) {
|
if (!s) {
|
||||||
|
@ -1690,19 +1687,13 @@ void gdb_exit(CPUArchState *env, int code)
|
||||||
if (gdbserver_fd < 0 || s->fd < 0) {
|
if (gdbserver_fd < 0 || s->fd < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
chr = qemu_chr_fe_get_driver(&s->chr);
|
|
||||||
if (!chr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||||
put_packet(s, buf);
|
put_packet(s, buf);
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
qemu_chr_fe_deinit(&s->chr);
|
qemu_chr_fe_deinit(&s->chr, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2002,9 +1993,7 @@ int gdbserver_start(const char *device)
|
||||||
NULL, &error_abort);
|
NULL, &error_abort);
|
||||||
monitor_init(mon_chr, 0);
|
monitor_init(mon_chr, 0);
|
||||||
} else {
|
} else {
|
||||||
if (qemu_chr_fe_get_driver(&s->chr)) {
|
qemu_chr_fe_deinit(&s->chr, true);
|
||||||
object_unparent(OBJECT(qemu_chr_fe_get_driver(&s->chr)));
|
|
||||||
}
|
|
||||||
mon_chr = s->mon_chr;
|
mon_chr = s->mon_chr;
|
||||||
memset(s, 0, sizeof(GDBState));
|
memset(s, 0, sizeof(GDBState));
|
||||||
s->mon_chr = mon_chr;
|
s->mon_chr = mon_chr;
|
||||||
|
|
|
@ -905,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp)
|
||||||
|
|
||||||
void serial_exit_core(SerialState *s)
|
void serial_exit_core(SerialState *s)
|
||||||
{
|
{
|
||||||
qemu_chr_fe_deinit(&s->chr);
|
qemu_chr_fe_deinit(&s->chr, false);
|
||||||
|
|
||||||
timer_del(s->modem_status_poll);
|
timer_del(s->modem_status_poll);
|
||||||
timer_free(s->modem_status_poll);
|
timer_free(s->modem_status_poll);
|
||||||
|
|
|
@ -261,7 +261,7 @@ static void con_disconnect(struct XenDevice *xendev)
|
||||||
{
|
{
|
||||||
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
|
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&con->chr);
|
qemu_chr_fe_deinit(&con->chr, false);
|
||||||
xen_pv_unbind_evtchn(&con->xendev);
|
xen_pv_unbind_evtchn(&con->xendev);
|
||||||
|
|
||||||
if (con->sring) {
|
if (con->sring) {
|
||||||
|
|
|
@ -225,7 +225,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
|
||||||
Property *prop = opaque;
|
Property *prop = opaque;
|
||||||
CharBackend *be = qdev_get_prop_ptr(dev, prop);
|
CharBackend *be = qdev_get_prop_ptr(dev, prop);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(be);
|
qemu_chr_fe_deinit(be, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyInfo qdev_prop_chr = {
|
PropertyInfo qdev_prop_chr = {
|
||||||
|
|
|
@ -264,10 +264,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
|
||||||
|
|
||||||
static void ccid_card_vscard_drop_connection(PassthruState *card)
|
static void ccid_card_vscard_drop_connection(PassthruState *card)
|
||||||
{
|
{
|
||||||
Chardev *chr = qemu_chr_fe_get_driver(&card->cs);
|
qemu_chr_fe_deinit(&card->cs, true);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&card->cs);
|
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
card->vscard_in_pos = card->vscard_in_hdr = 0;
|
card->vscard_in_pos = card->vscard_in_hdr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1419,10 +1419,8 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
|
||||||
static void usbredir_unrealize(USBDevice *udev, Error **errp)
|
static void usbredir_unrealize(USBDevice *udev, Error **errp)
|
||||||
{
|
{
|
||||||
USBRedirDevice *dev = USB_REDIRECT(udev);
|
USBRedirDevice *dev = USB_REDIRECT(udev);
|
||||||
Chardev *chr = qemu_chr_fe_get_driver(&dev->cs);
|
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&dev->cs);
|
qemu_chr_fe_deinit(&dev->cs, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
|
|
||||||
/* Note must be done after qemu_chr_close, as that causes a close event */
|
/* Note must be done after qemu_chr_close, as that causes a close event */
|
||||||
qemu_bh_delete(dev->chardev_close_bh);
|
qemu_bh_delete(dev->chardev_close_bh);
|
||||||
|
|
|
@ -30,12 +30,14 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qemu_chr_fe_deinit:
|
* @qemu_chr_fe_deinit:
|
||||||
*
|
* @b: a CharBackend
|
||||||
|
* @del: if true, delete the chardev backend
|
||||||
|
*
|
||||||
* Dissociate the CharBackend from the Chardev.
|
* Dissociate the CharBackend from the Chardev.
|
||||||
*
|
*
|
||||||
* Safe to call without associated Chardev.
|
* Safe to call without associated Chardev.
|
||||||
*/
|
*/
|
||||||
void qemu_chr_fe_deinit(CharBackend *b);
|
void qemu_chr_fe_deinit(CharBackend *b, bool del);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qemu_chr_fe_get_driver:
|
* @qemu_chr_fe_get_driver:
|
||||||
|
|
|
@ -578,7 +578,7 @@ static void monitor_data_init(Monitor *mon)
|
||||||
|
|
||||||
static void monitor_data_destroy(Monitor *mon)
|
static void monitor_data_destroy(Monitor *mon)
|
||||||
{
|
{
|
||||||
qemu_chr_fe_deinit(&mon->chr);
|
qemu_chr_fe_deinit(&mon->chr, false);
|
||||||
if (monitor_is_qmp(mon)) {
|
if (monitor_is_qmp(mon)) {
|
||||||
json_message_parser_destroy(&mon->qmp.parser);
|
json_message_parser_destroy(&mon->qmp.parser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -801,11 +801,9 @@ static void colo_compare_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
CompareState *s = COLO_COMPARE(obj);
|
CompareState *s = COLO_COMPARE(obj);
|
||||||
|
|
||||||
qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL,
|
qemu_chr_fe_deinit(&s->chr_pri_in, false);
|
||||||
s->worker_context, true);
|
qemu_chr_fe_deinit(&s->chr_sec_in, false);
|
||||||
qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL,
|
qemu_chr_fe_deinit(&s->chr_out, false);
|
||||||
s->worker_context, true);
|
|
||||||
qemu_chr_fe_deinit(&s->chr_out);
|
|
||||||
|
|
||||||
g_main_loop_quit(s->compare_loop);
|
g_main_loop_quit(s->compare_loop);
|
||||||
qemu_thread_join(&s->thread);
|
qemu_thread_join(&s->thread);
|
||||||
|
|
|
@ -178,15 +178,15 @@ static void filter_mirror_cleanup(NetFilterState *nf)
|
||||||
{
|
{
|
||||||
MirrorState *s = FILTER_MIRROR(nf);
|
MirrorState *s = FILTER_MIRROR(nf);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&s->chr_out);
|
qemu_chr_fe_deinit(&s->chr_out, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void filter_redirector_cleanup(NetFilterState *nf)
|
static void filter_redirector_cleanup(NetFilterState *nf)
|
||||||
{
|
{
|
||||||
MirrorState *s = FILTER_REDIRECTOR(nf);
|
MirrorState *s = FILTER_REDIRECTOR(nf);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&s->chr_in);
|
qemu_chr_fe_deinit(&s->chr_in, false);
|
||||||
qemu_chr_fe_deinit(&s->chr_out);
|
qemu_chr_fe_deinit(&s->chr_out, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
|
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
|
||||||
|
|
|
@ -151,10 +151,7 @@ static void vhost_user_cleanup(NetClientState *nc)
|
||||||
s->vhost_net = NULL;
|
s->vhost_net = NULL;
|
||||||
}
|
}
|
||||||
if (nc->queue_index == 0) {
|
if (nc->queue_index == 0) {
|
||||||
Chardev *chr = qemu_chr_fe_get_driver(&s->chr);
|
qemu_chr_fe_deinit(&s->chr, true);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&s->chr);
|
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_purge_queued_packets(nc);
|
qemu_purge_queued_packets(nc);
|
||||||
|
|
|
@ -97,8 +97,7 @@ static void char_stdio_test_subprocess(void)
|
||||||
ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
|
ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
|
||||||
g_assert_cmpint(ret, ==, 4);
|
g_assert_cmpint(ret, ==, 4);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void char_stdio_test(void)
|
static void char_stdio_test(void)
|
||||||
|
@ -146,8 +145,7 @@ static void char_ringbuf_test(void)
|
||||||
g_assert_cmpstr(data, ==, "");
|
g_assert_cmpstr(data, ==, "");
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
|
|
||||||
/* check alias */
|
/* check alias */
|
||||||
opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
|
opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
|
||||||
|
@ -231,9 +229,8 @@ static void char_mux_test(void)
|
||||||
g_assert_cmpint(strlen(data), !=, 0);
|
g_assert_cmpint(strlen(data), !=, 0);
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&chr_be1);
|
qemu_chr_fe_deinit(&chr_be1, false);
|
||||||
qemu_chr_fe_deinit(&chr_be2);
|
qemu_chr_fe_deinit(&chr_be2, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct SocketIdleData {
|
typedef struct SocketIdleData {
|
||||||
|
@ -396,8 +393,7 @@ static void char_pipe_test(void)
|
||||||
g_assert_cmpint(fe.read_count, ==, 8);
|
g_assert_cmpint(fe.read_count, ==, 8);
|
||||||
g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
|
g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
|
|
||||||
g_assert(g_unlink(in) == 0);
|
g_assert(g_unlink(in) == 0);
|
||||||
g_assert(g_unlink(out) == 0);
|
g_assert(g_unlink(out) == 0);
|
||||||
|
@ -511,8 +507,7 @@ static void char_file_test(void)
|
||||||
|
|
||||||
g_assert_cmpint(fe.read_count, ==, 8);
|
g_assert_cmpint(fe.read_count, ==, 8);
|
||||||
g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
|
g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, true);
|
||||||
object_unref(OBJECT(chr));
|
|
||||||
g_unlink(fifo);
|
g_unlink(fifo);
|
||||||
g_free(fifo);
|
g_free(fifo);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +544,7 @@ static void char_null_test(void)
|
||||||
error_free_or_abort(&err);
|
error_free_or_abort(&err);
|
||||||
|
|
||||||
/* deinit & reinit */
|
/* deinit & reinit */
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, false);
|
||||||
qemu_chr_fe_init(&be, chr, &error_abort);
|
qemu_chr_fe_init(&be, chr, &error_abort);
|
||||||
|
|
||||||
qemu_chr_fe_set_open(&be, true);
|
qemu_chr_fe_set_open(&be, true);
|
||||||
|
@ -563,8 +558,7 @@ static void char_null_test(void)
|
||||||
ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
|
ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
|
||||||
g_assert_cmpint(ret, ==, 4);
|
g_assert_cmpint(ret, ==, 4);
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&be);
|
qemu_chr_fe_deinit(&be, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void char_invalid_test(void)
|
static void char_invalid_test(void)
|
||||||
|
|
|
@ -488,10 +488,8 @@ static inline void test_server_connect(TestServer *server)
|
||||||
static gboolean _test_server_free(TestServer *server)
|
static gboolean _test_server_free(TestServer *server)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Chardev *chr = qemu_chr_fe_get_driver(&server->chr);
|
|
||||||
|
|
||||||
qemu_chr_fe_deinit(&server->chr);
|
qemu_chr_fe_deinit(&server->chr, true);
|
||||||
object_unparent(OBJECT(chr));
|
|
||||||
|
|
||||||
for (i = 0; i < server->fds_num; i++) {
|
for (i = 0; i < server->fds_num; i++) {
|
||||||
close(server->fds[i]);
|
close(server->fds[i]);
|
||||||
|
|
Loading…
Reference in New Issue