[libvirt-users] Crash after connection close when callback is in progress

Vincent Bernat bernat at luffy.cx
Wed Aug 3 09:00:29 UTC 2016


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)




More information about the libvirt-users mailing list