aboutsummaryrefslogtreecommitdiffstats
path: root/tools/console
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2012-08-31 10:42:04 +0100
committerDavid Vrabel <david.vrabel@citrix.com>2012-08-31 10:42:04 +0100
commit2b5fb80ff7f475ab9cd0fed0ffbe15a8acce4494 (patch)
tree8e477b252e47d1032ae240e91be75ab8c0d53fb8 /tools/console
parent36d835637a4687a362405ee94f2867a05ed63ee6 (diff)
downloadxen-2b5fb80ff7f475ab9cd0fed0ffbe15a8acce4494.tar.gz
xen-2b5fb80ff7f475ab9cd0fed0ffbe15a8acce4494.tar.bz2
xen-2b5fb80ff7f475ab9cd0fed0ffbe15a8acce4494.zip
xenconsoled: clean-up after all dead domains
xenconsoled expected domains that are being shutdown to end up in the the DYING state and would only clean-up such domains. HVM domains either didn't enter the DYING state or weren't in long enough for xenconsoled to notice. For every shutdown HVM domain, xenconsoled would leak memory, grow its list of domains and (if guest console logging was enabled) leak the log file descriptor. If the file descriptors were leaked and enough HVM domains were shutdown, no more console connections would work as the evtchn device could not be opened. Guests would then block waiting to send console output. Fix this by tagging domains that exist in enum_domains(). Afterwards, all untagged domains are assumed to be dead and are shutdown and cleaned up. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/console')
-rw-r--r--tools/console/daemon/io.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index f09d63a304..48fe1519d5 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -84,6 +84,7 @@ struct domain {
int slave_fd;
int log_fd;
bool is_dead;
+ unsigned last_seen;
struct buffer buffer;
struct domain *next;
char *conspath;
@@ -727,12 +728,16 @@ static void shutdown_domain(struct domain *d)
d->xce_handle = NULL;
}
+static unsigned enum_pass = 0;
+
void enum_domains(void)
{
int domid = 1;
xc_dominfo_t dominfo;
struct domain *dom;
+ enum_pass++;
+
while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
dom = lookup_domain(dominfo.domid);
if (dominfo.dying) {
@@ -740,8 +745,10 @@ void enum_domains(void)
shutdown_domain(dom);
} else {
if (dom == NULL)
- create_domain(dominfo.domid);
+ dom = create_domain(dominfo.domid);
}
+ if (dom)
+ dom->last_seen = enum_pass;
domid = dominfo.domid + 1;
}
}
@@ -1069,6 +1076,9 @@ void handle_io(void)
&writefds))
handle_tty_write(d);
+ if (d->last_seen != enum_pass)
+ shutdown_domain(d);
+
if (d->is_dead)
cleanup_domain(d);
}