Fix serial domain handling

This commit is contained in:
Lon Hohberger 2011-10-25 19:29:24 -04:00
parent 5652c743a2
commit e96ef84b3e
3 changed files with 54 additions and 38 deletions

View File

@ -76,6 +76,7 @@ typedef struct _serial_info {
history_info_t *history;
map_object_t *maps;
int mode;
int wake_fd;
} serial_info;
@ -262,12 +263,16 @@ serial_dispatch(listener_context_t c, struct timeval *timeout)
struct timeval tv;
int max;
int n, x, ret;
char tmp_buf[32];
info = (serial_info *)c;
VALIDATE(info);
FD_ZERO(&rfds);
domain_sock_fdset(&rfds, &max);
FD_SET(info->wake_fd, &rfds);
if (info->wake_fd > max)
max = info->wake_fd;
n = select(max+1, &rfds, NULL, NULL, timeout);
if (n < 0) {
@ -275,6 +280,18 @@ serial_dispatch(listener_context_t c, struct timeval *timeout)
return n;
}
/*
* See if the goal was just to be woken up in order to refill our
* file descriptor set. For example, if multiple domains were
* created simultaneously, we would have to refill our fd_set
*/
if (FD_ISSET(info->wake_fd, &rfds)) {
tv.tv_sec = 0;
tv.tv_usec = 10000;
_read_retry(info->wake_fd, &c, 1, &tv);
return 0;
}
/*
* If no requests, we're done
*/
@ -392,7 +409,7 @@ serial_init(listener_context_t *c, const fence_callbacks_t *cb,
info->magic = SERIAL_PLUG_MAGIC;
info->history = history_init(check_history, 10, sizeof(fence_req_t));
*c = (listener_context_t)info;
start_event_listener(info->uri, info->path, info->mode);
start_event_listener(info->uri, info->path, info->mode, &info->wake_fd);
sleep(1);
return 0;

View File

@ -13,7 +13,7 @@ int domain_sock_name(int fd, char *outbuf, size_t buflen);
int domain_sock_cleanup(void);
/* virt-serial.c - event thread control functions */
int start_event_listener(const char *uri, const char *path, int mode);
int start_event_listener(const char *uri, const char *path, int mode, int *wake_fd);
int stop_event_listener(void);

View File

@ -69,25 +69,6 @@ struct domain_info {
};
int
myDomainEventCallback1(virConnectPtr conn,
virDomainPtr dom, int event, int detail, void *opaque)
{
struct domain_info *dinfo = (struct domain_info *) opaque;
if (event == VIR_DOMAIN_EVENT_STARTED ||
event == VIR_DOMAIN_EVENT_STOPPED) {
virDomainRef(dom);
dinfo->dom = dom;
dinfo->event = event;
} else {
dinfo->event = VIR_DOMAIN_EVENT_UNDEFINED;
}
return 0;
}
/* EventImpl Functions */
int
myEventHandleTypeToPollEvent(virEventHandleType events)
@ -413,15 +394,38 @@ struct event_args {
char *uri;
char *path;
int mode;
int wake_fd;
};
int
myDomainEventCallback1(virConnectPtr conn,
virDomainPtr dom, int event, int detail, void *opaque)
{
struct event_args *args = (struct event_args *)opaque;
if (event == VIR_DOMAIN_EVENT_STARTED ||
event == VIR_DOMAIN_EVENT_STOPPED) {
virDomainRef(dom);
if (event == VIR_DOMAIN_EVENT_STARTED) {
domainStarted(dom, args->path, args->mode);
virDomainFree(dom);
write(args->wake_fd, "x", 1);
} else if (event == VIR_DOMAIN_EVENT_STOPPED) {
domainStopped(dom);
virDomainFree(dom);
}
}
return 0;
}
static void *
event_thread(void *arg)
{
struct event_args *args = (struct event_args *)arg;
virConnectPtr dconn = NULL;
struct domain_info dinfo;
int callback1ret = -1;
int sts;
@ -450,11 +454,9 @@ event_thread(void *arg)
registerExisting(dconn, args->path, args->mode);
/* Add 2 callbacks to prove this works with more than just one */
memset(&dinfo, 0, sizeof (dinfo));
dinfo.event = VIR_DOMAIN_EVENT_UNDEFINED;
callback1ret =
virConnectDomainEventRegister(dconn, myDomainEventCallback1,
&dinfo, NULL);
arg, NULL);
if ((callback1ret == 0)) {
while (run) {
@ -469,18 +471,6 @@ event_thread(void *arg)
t_cb(t_timeout, t_opaque);
}
if (dinfo.event == VIR_DOMAIN_EVENT_STARTED) {
domainStarted(dinfo.dom, args->path, args->mode);
virDomainFree(dinfo.dom);
dinfo.dom = NULL;
dinfo.event = VIR_DOMAIN_EVENT_UNDEFINED;
} else if (dinfo.event == VIR_DOMAIN_EVENT_STOPPED) {
domainStopped(dinfo.dom);
virDomainFree(dinfo.dom);
dinfo.dom = NULL;
dinfo.event = VIR_DOMAIN_EVENT_UNDEFINED;
}
if (sts == 0) {
/* DEBUG0("Poll timeout"); */
continue;
@ -522,9 +512,10 @@ out:
int
start_event_listener(const char *uri, const char *path, int mode)
start_event_listener(const char *uri, const char *path, int mode, int *wake_fd)
{
struct event_args *args = NULL;
int wake_pipe[2];
virInitialize();
@ -533,6 +524,10 @@ start_event_listener(const char *uri, const char *path, int mode)
return -1;
memset(args, 0, sizeof(*args));
if (pipe2(wake_pipe, O_CLOEXEC) < 0) {
goto out_fail;
}
if (uri) {
args->uri = strdup(uri);
if (args->uri == NULL)
@ -546,6 +541,10 @@ start_event_listener(const char *uri, const char *path, int mode)
}
args->mode = mode;
//args->p_tid = pthread_self();
*wake_fd = wake_pipe[0];
args->wake_fd = wake_pipe[1];
run = 1;
return pthread_create(&event_tid, NULL, event_thread, args);