@@ -176,6 +176,11 @@ int qemu_chr_add_client(CharDriverState *s, int fd)
return s->chr_add_client ? s->chr_add_client(s, fd) : -1;
}
+int qemu_chr_remove_clients(CharDriverState *s)
+{
+ return s->chr_remove_clients ? s->chr_remove_clients(s) : -1;
+}
+
void qemu_chr_accept_input(CharDriverState *s)
{
if (s->chr_accept_input)
@@ -2378,6 +2383,22 @@ static int tcp_chr_add_client(CharDriverState *chr, int fd)
return 0;
}
+static int tcp_chr_remove_clients(CharDriverState *chr)
+{
+ TCPCharDriver *s = chr->opaque;
+
+ if (s->fd >= 0) {
+ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+ closesocket(s->fd);
+ s->fd = -1;
+ }
+
+ /* listen for new clients */
+ qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
+
+ return 0;
+}
+
static void tcp_chr_accept(void *opaque)
{
CharDriverState *chr = opaque;
@@ -2417,10 +2438,8 @@ static void tcp_chr_accept(void *opaque)
static void tcp_chr_close(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
- if (s->fd >= 0) {
- qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
- closesocket(s->fd);
- }
+
+ tcp_chr_remove_clients(chr);
if (s->listen_fd >= 0) {
qemu_set_fd_handler2(s->listen_fd, NULL, NULL, NULL, NULL);
closesocket(s->listen_fd);
@@ -2484,6 +2503,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
chr->chr_close = tcp_chr_close;
chr->get_msgfd = tcp_get_msgfd;
chr->chr_add_client = tcp_chr_add_client;
+ chr->chr_remove_clients = tcp_chr_remove_clients;
if (is_listen) {
s->listen_fd = fd;
@@ -60,6 +60,7 @@ struct CharDriverState {
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
int (*get_msgfd)(struct CharDriverState *s);
int (*chr_add_client)(struct CharDriverState *chr, int fd);
+ int (*chr_remove_clients)(struct CharDriverState *chr);
IOEventHandler *chr_event;
IOCanReadHandler *chr_can_read;
IOReadHandler *chr_read;
@@ -232,6 +233,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
void qemu_chr_generic_open(CharDriverState *s);
void qemu_chr_accept_input(CharDriverState *s);
int qemu_chr_add_client(CharDriverState *s, int fd);
+int qemu_chr_remove_clients(CharDriverState *s);
void qemu_chr_info_print(Monitor *mon, const QObject *ret_data);
void qemu_chr_info(Monitor *mon, QObject **ret_data);
CharDriverState *qemu_chr_find(const char *name);
Make it possible for chardev user to disconnect all the clients. The spiceport will remove associated chardev clients when the spice client is disconnected. (since qemu-char could have several clients implementation later, as chr_add_client() name suggests, I chose to have generic name and behaviour that could apply to a single or many clients implementation) Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- qemu-char.c | 28 ++++++++++++++++++++++++---- qemu-char.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-)