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)
|
||||
|
||||
/* 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 int run = 0;
|
||||
|
||||
@ -48,20 +34,6 @@ static int run = 0;
|
||||
const char *eventToString(int event);
|
||||
int myDomainEventCallback1(virConnectPtr conn, virDomainPtr dom,
|
||||
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);
|
||||
|
||||
@ -70,103 +42,6 @@ struct domain_info {
|
||||
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
|
||||
is_in_directory(const char *dir, const char *pathspec)
|
||||
{
|
||||
@ -395,6 +270,30 @@ struct event_args {
|
||||
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
|
||||
myDomainEventCallback1(virConnectPtr conn,
|
||||
@ -425,7 +324,6 @@ event_thread(void *arg)
|
||||
struct event_args *args = (struct event_args *)arg;
|
||||
virConnectPtr dconn = NULL;
|
||||
int callback1ret = -1;
|
||||
int sts;
|
||||
|
||||
dbg_printf(3, "Libvirt event listener starting\n");
|
||||
if (args->uri)
|
||||
@ -434,13 +332,10 @@ event_thread(void *arg)
|
||||
dbg_printf(3," * Socket path: %s\n", args->path);
|
||||
dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial");
|
||||
|
||||
top:
|
||||
virEventRegisterImpl(myEventAddHandleFunc,
|
||||
myEventUpdateHandleFunc,
|
||||
myEventRemoveHandleFunc,
|
||||
myEventAddTimeoutFunc,
|
||||
myEventUpdateTimeoutFunc,
|
||||
myEventRemoveTimeoutFunc);
|
||||
if (virEventRegisterDefaultImpl() < 0) {
|
||||
dbg_printf(1, "Failed to register default event impl\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dconn = virConnectOpen(args->uri);
|
||||
if (!dconn) {
|
||||
@ -448,6 +343,8 @@ top:
|
||||
goto out;
|
||||
}
|
||||
|
||||
virConnectRegisterCloseCallback(dconn, connectClose, NULL, NULL);
|
||||
|
||||
DEBUG0("Registering domain event cbs");
|
||||
|
||||
registerExisting(dconn, args->path, args->mode);
|
||||
@ -455,43 +352,14 @@ top:
|
||||
callback1ret =
|
||||
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) {
|
||||
struct pollfd pfd = {
|
||||
.fd = h_fd,
|
||||
.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);
|
||||
if (virEventRunDefaultImpl() < 0) {
|
||||
dbg_printf(1, "RunDefaultImpl Failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user