Vincent Bernat
2016-Aug-03 09:00 UTC
[libvirt-users] Crash after connection close when callback is in progress
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)