Current implementation of event listener in virt-serial does not support keepalive,
it does not generate nor capable to answer to keepalive requests, which causes libvirt connection to disconnect every 30 seconds (interval*timeout in libvirtd.conf). Furthermore, it does not clean up filehandlers and leaves hanging sockets. Also, if other thread opens its own connection to libvirt (i.e. checkpoint.c), event function in virt-serial.c just updates event listener file handler with a wrong one, what causes checkpoint.c malfunctions, fence_virtd hangs and so on. This patch uses default event listener implementation from libvirt and resolves theese problems.
This commit is contained in:
parent
6d79ea13dd
commit
913e54c544
@ -27,20 +27,6 @@
|
|||||||
|
|
||||||
#define STREQ(a,b) (strcmp((a),(b)) == 0)
|
#define STREQ(a,b) (strcmp((a),(b)) == 0)
|
||||||
|
|
||||||
/* handle globals */
|
|
||||||
static int h_fd = -1;
|
|
||||||
static virEventHandleType h_event = 0;
|
|
||||||
static virEventHandleCallback h_cb = NULL;
|
|
||||||
static virFreeCallback h_ff = NULL;
|
|
||||||
static void *h_opaque = NULL;
|
|
||||||
|
|
||||||
/* timeout globals */
|
|
||||||
#define TIMEOUT_MS 1000
|
|
||||||
static int t_active = 0;
|
|
||||||
static int t_timeout = -1;
|
|
||||||
static virEventTimeoutCallback t_cb = NULL;
|
|
||||||
static virFreeCallback t_ff = NULL;
|
|
||||||
static void *t_opaque = NULL;
|
|
||||||
static pthread_t event_tid = 0;
|
static pthread_t event_tid = 0;
|
||||||
static int run = 0;
|
static int run = 0;
|
||||||
|
|
||||||
@ -48,20 +34,6 @@ static int run = 0;
|
|||||||
const char *eventToString(int event);
|
const char *eventToString(int event);
|
||||||
int myDomainEventCallback1(virConnectPtr conn, virDomainPtr dom,
|
int myDomainEventCallback1(virConnectPtr conn, virDomainPtr dom,
|
||||||
int event, int detail, void *opaque);
|
int event, int detail, void *opaque);
|
||||||
int myEventAddHandleFunc(int fd, int event,
|
|
||||||
virEventHandleCallback cb,
|
|
||||||
void *opaque, virFreeCallback ff);
|
|
||||||
void myEventUpdateHandleFunc(int watch, int event);
|
|
||||||
int myEventRemoveHandleFunc(int watch);
|
|
||||||
|
|
||||||
int myEventAddTimeoutFunc(int timeout,
|
|
||||||
virEventTimeoutCallback cb,
|
|
||||||
void *opaque, virFreeCallback ff);
|
|
||||||
void myEventUpdateTimeoutFunc(int timer, int timout);
|
|
||||||
int myEventRemoveTimeoutFunc(int timer);
|
|
||||||
|
|
||||||
int myEventHandleTypeToPollEvent(virEventHandleType events);
|
|
||||||
virEventHandleType myPollEventToEventHandleType(int events);
|
|
||||||
|
|
||||||
void usage(const char *pname);
|
void usage(const char *pname);
|
||||||
|
|
||||||
@ -70,103 +42,6 @@ struct domain_info {
|
|||||||
virDomainEventType event;
|
virDomainEventType event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* EventImpl Functions */
|
|
||||||
int
|
|
||||||
myEventHandleTypeToPollEvent(virEventHandleType events)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
if (events & VIR_EVENT_HANDLE_READABLE)
|
|
||||||
ret |= POLLIN;
|
|
||||||
if (events & VIR_EVENT_HANDLE_WRITABLE)
|
|
||||||
ret |= POLLOUT;
|
|
||||||
if (events & VIR_EVENT_HANDLE_ERROR)
|
|
||||||
ret |= POLLERR;
|
|
||||||
if (events & VIR_EVENT_HANDLE_HANGUP)
|
|
||||||
ret |= POLLHUP;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
virEventHandleType
|
|
||||||
myPollEventToEventHandleType(int events)
|
|
||||||
{
|
|
||||||
virEventHandleType ret = 0;
|
|
||||||
if (events & POLLIN)
|
|
||||||
ret |= VIR_EVENT_HANDLE_READABLE;
|
|
||||||
if (events & POLLOUT)
|
|
||||||
ret |= VIR_EVENT_HANDLE_WRITABLE;
|
|
||||||
if (events & POLLERR)
|
|
||||||
ret |= VIR_EVENT_HANDLE_ERROR;
|
|
||||||
if (events & POLLHUP)
|
|
||||||
ret |= VIR_EVENT_HANDLE_HANGUP;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
myEventAddHandleFunc(int fd, int event,
|
|
||||||
virEventHandleCallback cb,
|
|
||||||
void *opaque, virFreeCallback ff)
|
|
||||||
{
|
|
||||||
DEBUG1("Add handle %d %d %p %p %p", fd, event, cb, opaque, ff);
|
|
||||||
h_fd = fd;
|
|
||||||
h_event = myEventHandleTypeToPollEvent(event);
|
|
||||||
h_cb = cb;
|
|
||||||
h_opaque = opaque;
|
|
||||||
h_ff = ff;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
myEventUpdateHandleFunc(int fd, int event)
|
|
||||||
{
|
|
||||||
DEBUG1("Updated Handle %d %d", fd, event);
|
|
||||||
h_event = myEventHandleTypeToPollEvent(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
myEventRemoveHandleFunc(int fd)
|
|
||||||
{
|
|
||||||
DEBUG1("Removed Handle %d", fd);
|
|
||||||
h_fd = 0;
|
|
||||||
if (h_ff)
|
|
||||||
(h_ff) (h_opaque);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
myEventAddTimeoutFunc(int timeout,
|
|
||||||
virEventTimeoutCallback cb,
|
|
||||||
void *opaque, virFreeCallback ff)
|
|
||||||
{
|
|
||||||
DEBUG1("Adding Timeout %d %p %p", timeout, cb, opaque);
|
|
||||||
t_active = 1;
|
|
||||||
t_timeout = timeout;
|
|
||||||
t_cb = cb;
|
|
||||||
t_ff = ff;
|
|
||||||
t_opaque = opaque;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
myEventUpdateTimeoutFunc(int timer, int timeout)
|
|
||||||
{
|
|
||||||
/*DEBUG1("Timeout updated %d %d", timer, timeout); */
|
|
||||||
t_timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
myEventRemoveTimeoutFunc(int timer)
|
|
||||||
{
|
|
||||||
DEBUG1("Timeout removed %d", timer);
|
|
||||||
t_active = 0;
|
|
||||||
if (t_ff)
|
|
||||||
(t_ff) (t_opaque);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
is_in_directory(const char *dir, const char *pathspec)
|
is_in_directory(const char *dir, const char *pathspec)
|
||||||
{
|
{
|
||||||
@ -395,6 +270,30 @@ struct event_args {
|
|||||||
int wake_fd;
|
int wake_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
|
int reason,
|
||||||
|
void *opaque ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
switch (reason) {
|
||||||
|
case VIR_CONNECT_CLOSE_REASON_ERROR:
|
||||||
|
dbg_printf(2, "Connection closed due to I/O error\n");
|
||||||
|
break;
|
||||||
|
case VIR_CONNECT_CLOSE_REASON_EOF:
|
||||||
|
dbg_printf(2, "Connection closed due to end of file\n");
|
||||||
|
break;
|
||||||
|
case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
|
||||||
|
dbg_printf(2, "Connection closed due to keepalive timeout\n");
|
||||||
|
break;
|
||||||
|
case VIR_CONNECT_CLOSE_REASON_CLIENT:
|
||||||
|
dbg_printf(2, "Connection closed due to client request\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbg_printf(2, "Connection closed due to unknown reason\n");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
myDomainEventCallback1(virConnectPtr conn,
|
myDomainEventCallback1(virConnectPtr conn,
|
||||||
@ -425,7 +324,6 @@ event_thread(void *arg)
|
|||||||
struct event_args *args = (struct event_args *)arg;
|
struct event_args *args = (struct event_args *)arg;
|
||||||
virConnectPtr dconn = NULL;
|
virConnectPtr dconn = NULL;
|
||||||
int callback1ret = -1;
|
int callback1ret = -1;
|
||||||
int sts;
|
|
||||||
|
|
||||||
dbg_printf(3, "Libvirt event listener starting\n");
|
dbg_printf(3, "Libvirt event listener starting\n");
|
||||||
if (args->uri)
|
if (args->uri)
|
||||||
@ -434,13 +332,10 @@ event_thread(void *arg)
|
|||||||
dbg_printf(3," * Socket path: %s\n", args->path);
|
dbg_printf(3," * Socket path: %s\n", args->path);
|
||||||
dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial");
|
dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial");
|
||||||
|
|
||||||
top:
|
if (virEventRegisterDefaultImpl() < 0) {
|
||||||
virEventRegisterImpl(myEventAddHandleFunc,
|
dbg_printf(1, "Failed to register default event impl\n");
|
||||||
myEventUpdateHandleFunc,
|
goto out;
|
||||||
myEventRemoveHandleFunc,
|
}
|
||||||
myEventAddTimeoutFunc,
|
|
||||||
myEventUpdateTimeoutFunc,
|
|
||||||
myEventRemoveTimeoutFunc);
|
|
||||||
|
|
||||||
dconn = virConnectOpen(args->uri);
|
dconn = virConnectOpen(args->uri);
|
||||||
if (!dconn) {
|
if (!dconn) {
|
||||||
@ -448,6 +343,8 @@ top:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virConnectRegisterCloseCallback(dconn, connectClose, NULL, NULL);
|
||||||
|
|
||||||
DEBUG0("Registering domain event cbs");
|
DEBUG0("Registering domain event cbs");
|
||||||
|
|
||||||
registerExisting(dconn, args->path, args->mode);
|
registerExisting(dconn, args->path, args->mode);
|
||||||
@ -455,43 +352,14 @@ top:
|
|||||||
callback1ret =
|
callback1ret =
|
||||||
virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL);
|
virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL);
|
||||||
|
|
||||||
if (callback1ret == 0) {
|
if (callback1ret != -1) {
|
||||||
|
if (virConnectSetKeepAlive(dconn, 5, 5) < 0) {
|
||||||
|
dbg_printf(1, "Failed to start keepalive protocol\n");
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
while (run) {
|
while (run) {
|
||||||
struct pollfd pfd = {
|
if (virEventRunDefaultImpl() < 0) {
|
||||||
.fd = h_fd,
|
dbg_printf(1, "RunDefaultImpl Failed\n");
|
||||||
.events = h_event,
|
|
||||||
.revents = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
sts = poll(&pfd, 1, TIMEOUT_MS);
|
|
||||||
/* We are assuming timeout of 0 here - so execute every time */
|
|
||||||
if (t_cb && t_active) {
|
|
||||||
t_cb(t_timeout, t_opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sts == 0) {
|
|
||||||
/* DEBUG0("Poll timeout"); */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sts < 0) {
|
|
||||||
DEBUG0("Poll failed");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd.revents & POLLHUP) {
|
|
||||||
DEBUG0("Reset by peer");
|
|
||||||
virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
|
|
||||||
if (dconn && virConnectClose(dconn) < 0)
|
|
||||||
dbg_printf(1, "error closing libvirt connection\n");
|
|
||||||
DEBUG0("Attempting to reinitialize libvirt connection");
|
|
||||||
goto top;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h_cb) {
|
|
||||||
h_cb(0, h_fd,
|
|
||||||
myPollEventToEventHandleType(pfd.revents & h_event),
|
|
||||||
h_opaque);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user