Skip to content

Commit

Permalink
char: free the tcp connection data when closing
Browse files Browse the repository at this point in the history
Make sure the connection data got freed when closing the chardev, to
avoid leaks. Introduce tcp_chr_free_connection() to clean all connection
related data, and move some tcp_chr_close() clean-ups there.

(while at it, set write_msgfds_num to 0 when clearing array in
tcp_set_msgfds())

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
elmarco committed Aug 7, 2016
1 parent 157e94e commit 5b49845
Showing 1 changed file with 31 additions and 19 deletions.
50 changes: 31 additions & 19 deletions qemu-char.c
Expand Up @@ -2763,6 +2763,7 @@ static int tcp_set_msgfds(CharDriverState *chr, int *fds, int num)
/* clear old pending fd array */
g_free(s->write_msgfds);
s->write_msgfds = NULL;
s->write_msgfds_num = 0;

if (!s->connected ||
!qio_channel_has_feature(s->ioc,
Expand Down Expand Up @@ -2843,26 +2844,49 @@ static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond)
return qio_channel_create_watch(s->ioc, cond);
}

static void tcp_chr_disconnect(CharDriverState *chr)
static void tcp_chr_free_connection(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
int i;

if (!s->connected) {
return;
}

s->connected = 0;
if (s->listen_ioc) {
s->listen_tag = qio_channel_add_watch(
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
if (s->read_msgfds_num) {
for (i = 0; i < s->read_msgfds_num; i++) {
close(s->read_msgfds[i]);
}
g_free(s->read_msgfds);
s->read_msgfds = NULL;
s->read_msgfds_num = 0;
}

tcp_set_msgfds(chr, NULL, 0);
remove_fd_in_watch(chr);
object_unref(OBJECT(s->sioc));
s->sioc = NULL;
object_unref(OBJECT(s->ioc));
s->ioc = NULL;
g_free(chr->filename);
chr->filename = NULL;
s->connected = 0;
}

static void tcp_chr_disconnect(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;

if (!s->connected) {
return;
}

tcp_chr_free_connection(chr);

if (s->listen_ioc) {
s->listen_tag = qio_channel_add_watch(
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
}
chr->filename = SocketAddress_to_str("disconnected:", s->addr,
s->is_listen, s->is_telnet);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
Expand Down Expand Up @@ -3177,36 +3201,24 @@ int qemu_chr_wait_connected(CharDriverState *chr, Error **errp)
static void tcp_chr_close(CharDriverState *chr)
{
TCPCharDriver *s = chr->opaque;
int i;

tcp_chr_free_connection(chr);

if (s->reconnect_timer) {
g_source_remove(s->reconnect_timer);
s->reconnect_timer = 0;
}
qapi_free_SocketAddress(s->addr);
remove_fd_in_watch(chr);
if (s->ioc) {
object_unref(OBJECT(s->ioc));
}
if (s->listen_tag) {
g_source_remove(s->listen_tag);
s->listen_tag = 0;
}
if (s->listen_ioc) {
object_unref(OBJECT(s->listen_ioc));
}
if (s->read_msgfds_num) {
for (i = 0; i < s->read_msgfds_num; i++) {
close(s->read_msgfds[i]);
}
g_free(s->read_msgfds);
}
if (s->tls_creds) {
object_unref(OBJECT(s->tls_creds));
}
if (s->write_msgfds_num) {
g_free(s->write_msgfds);
}
g_free(s);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
Expand Down

0 comments on commit 5b49845

Please sign in to comment.