Hey!
It seems that if I close a connection while a domain event callback is
in progress, I can easily have a crash. Here is a backtrace:
#v+
#0 virFree (ptrptr=0x0) at ../../../src/util/viralloc.c:582
save_errno = <optimized out>
#1 0x00007fc8328a4ad2 in virObjectEventCallbackListPurgeMarked (cbList=0xadfc30) at
../../../src/conf/object_event.c:282
freecb = <optimized out>
n = 0
#2 virObjectEventStateFlush (state=0xaf5380) at ../../../src/conf/object_event.c:819
tempQueue = {
count = 0,
events = 0x0
}
#3 virObjectEventTimer (timer=<optimized out>, opaque=0xaf5380) at
../../../src/conf/object_event.c:560
state = 0xaf5380
#4 0x00007fc83280b7aa in virEventPollDispatchTimeouts () at
../../../src/util/vireventpoll.c:457
cb = 0x7fc8328a48d0 <virObjectEventTimer>
timer = 1
opaque = 0xaf5380
now = 1470212691501
i = 0
ntimeouts = 1
#5 virEventPollRunOnce () at ../../../src/util/vireventpoll.c:653
fds = 0x7fc824000920
ret = <optimized out>
timeout = <optimized out>
nfds = 1
__func__ = "virEventPollRunOnce"
__FUNCTION__ = "virEventPollRunOnce"
#6 0x00007fc83280a141 in virEventRunDefaultImpl () at ../../../src/util/virevent.c:314
__func__ = "virEventRunDefaultImpl"
#7 0x0000000000400b37 in loop (arg=0x0) at crash.c:8
__PRETTY_FUNCTION__ = "loop"
#v-
And the state of cbList:
#v+
>> print *cbList
$2 = {
nextID = 11419456,
count = 1,
callbacks = 0x0
}
#v-
I have another thread, but it is just sleeping when the crash happens.
Here is the source code:
#+begin_src c
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <libvirt/libvirt.h>
void* loop(void *arg) {
while (1) {
assert (virEventRunDefaultImpl() >= 0);
}
return NULL;
}
void callback(virConnectPtr conn, virDomainPtr dom, void *opaque) {
// Do nothing.
}
void freecb(void *opaque) {
// Do nothing.
}
int main() {
assert(virInitialize() >= 0);
assert(virEventRegisterDefaultImpl() >= 0);
pthread_t event_loop;
assert(pthread_create(&event_loop, NULL, loop, NULL) == 0);
virConnectPtr conn = virConnectOpen("test:///default");
assert(conn != NULL);
int cbid = virConnectDomainEventRegisterAny(conn, NULL,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
callback, NULL,
freecb);
assert(cbid != -1);
virDomainPtr dom = virDomainDefineXML(conn,
"<domain
type=\"test\">"
"<name>new VM</name>"
"<memory
unit=\"KiB\">8192</memory>"
"<os><type>hvm</type>
</os>"
"</domain>");
assert(dom != NULL);
assert(virDomainCreate(dom) != -1);
virDomainFree(dom);
assert(virConnectDomainEventDeregisterAny(conn, cbid) != -1);
if (virConnectClose(conn) > 0 ) {
printf("leak...\n");
}
usleep(100000);
return 0;
}
#+end_src
Running this program in an infinite loop triggers the bug in less than 1
second (most of the time, just after displaying "leak...").
I am using libvirt 2.0.0 (in Debian). I have also file the following
bug:
https://bugzilla.redhat.com/show_bug.cgi?id=1363628
--
Write clearly - don't sacrifice clarity for "efficiency".
- The Elements of Programming Style (Kernighan & Plauger)