event-test.c 23.4 KB
Newer Older
1
#include <config.h>
2

3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <signal.h>
7
#include <inttypes.h>
8

9 10
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
11

12
#define VIR_DEBUG(fmt) printf("%s:%d: " fmt "\n", __func__, __LINE__)
13
#define STREQ(a,b) (strcmp(a,b) == 0)
14

15 16 17
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__((__unused__))
#endif
18

19 20
int run = 1;

21 22 23
/* Prototypes */
const char *eventToString(int event);
int myEventAddHandleFunc  (int fd, int event,
24 25 26
                           virEventHandleCallback cb,
                           void *opaque,
                           virFreeCallback ff);
27 28
void myEventUpdateHandleFunc(int watch, int event);
int  myEventRemoveHandleFunc(int watch);
29

30 31 32 33
int myEventAddTimeoutFunc(int timeout,
                          virEventTimeoutCallback cb,
                          void *opaque,
                          virFreeCallback ff);
34 35 36 37 38 39 40 41 42 43
void myEventUpdateTimeoutFunc(int timer, int timout);
int myEventRemoveTimeoutFunc(int timer);

int myEventHandleTypeToPollEvent(virEventHandleType events);
virEventHandleType myPollEventToEventHandleType(int events);

void usage(const char *pname);

/* Callback functions */

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

static void connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
                         int reason,
                         void *opaque ATTRIBUTE_UNUSED)
{
    switch (reason) {
    case VIR_CONNECT_CLOSE_REASON_ERROR:
        fprintf(stderr, "Connection closed due to I/O error\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_EOF:
        fprintf(stderr, "Connection closed due to end of file\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
        fprintf(stderr, "Connection closed due to keepalive timeout\n");
        break;
    case VIR_CONNECT_CLOSE_REASON_CLIENT:
        fprintf(stderr, "Connection closed due to client request\n");
        break;
    default:
        fprintf(stderr, "Connection closed due to unknown reason\n");
        break;
    };
    run = 0;
}

69
const char *eventToString(int event) {
70
    const char *ret = "";
71
    switch ((virDomainEventType) event) {
72 73
        case VIR_DOMAIN_EVENT_DEFINED:
            ret ="Defined";
74
            break;
75 76
        case VIR_DOMAIN_EVENT_UNDEFINED:
            ret ="Undefined";
77 78 79 80 81 82 83 84 85 86 87 88 89
            break;
        case VIR_DOMAIN_EVENT_STARTED:
            ret ="Started";
            break;
        case VIR_DOMAIN_EVENT_SUSPENDED:
            ret ="Suspended";
            break;
        case VIR_DOMAIN_EVENT_RESUMED:
            ret ="Resumed";
            break;
        case VIR_DOMAIN_EVENT_STOPPED:
            ret ="Stopped";
            break;
90 91 92
        case VIR_DOMAIN_EVENT_SHUTDOWN:
            ret = "Shutdown";
            break;
J
Jiri Denemark 已提交
93 94 95
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
            ret = "PMSuspended";
            break;
96 97 98 99 100 101
    }
    return ret;
}

static const char *eventDetailToString(int event, int detail) {
    const char *ret = "";
102
    switch ((virDomainEventType) event) {
103 104 105 106 107 108 109 110 111
        case VIR_DOMAIN_EVENT_DEFINED:
            if (detail == VIR_DOMAIN_EVENT_DEFINED_ADDED)
                ret = "Added";
            else if (detail == VIR_DOMAIN_EVENT_DEFINED_UPDATED)
                ret = "Updated";
            break;
        case VIR_DOMAIN_EVENT_UNDEFINED:
            if (detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED)
                ret = "Removed";
112
            break;
113
        case VIR_DOMAIN_EVENT_STARTED:
114
            switch ((virDomainEventStartedDetailType) detail) {
115 116 117 118 119 120 121 122 123
            case VIR_DOMAIN_EVENT_STARTED_BOOTED:
                ret = "Booted";
                break;
            case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
                ret = "Migrated";
                break;
            case VIR_DOMAIN_EVENT_STARTED_RESTORED:
                ret = "Restored";
                break;
124 125 126
            case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
127 128 129
            case VIR_DOMAIN_EVENT_STARTED_WAKEUP:
                ret = "Event wakeup";
                break;
130 131 132
            }
            break;
        case VIR_DOMAIN_EVENT_SUSPENDED:
133
            switch ((virDomainEventSuspendedDetailType) detail) {
134
            case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
135
                ret = "Paused";
136 137
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
138
                ret = "Migrated";
139 140 141 142 143 144 145 146 147 148 149 150 151 152
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
                ret = "I/O Error";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
                ret = "Watchdog";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
                ret = "Restored";
                break;
            case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
            }
153 154
            break;
        case VIR_DOMAIN_EVENT_RESUMED:
155
            switch ((virDomainEventResumedDetailType) detail) {
156
            case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
157
                ret = "Unpaused";
158 159
                break;
            case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
160
                ret = "Migrated";
161 162 163 164 165
                break;
            case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
            }
166 167
            break;
        case VIR_DOMAIN_EVENT_STOPPED:
168
            switch ((virDomainEventStoppedDetailType) detail) {
169 170 171 172 173 174 175 176 177 178 179 180 181
            case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
                ret = "Shutdown";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
                ret = "Destroyed";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
                ret = "Crashed";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
                ret = "Migrated";
                break;
            case VIR_DOMAIN_EVENT_STOPPED_SAVED:
182
                ret = "Saved";
183 184 185 186
                break;
            case VIR_DOMAIN_EVENT_STOPPED_FAILED:
                ret = "Failed";
                break;
187 188 189
            case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
                ret = "Snapshot";
                break;
190
            }
191
            break;
192 193 194 195 196 197 198
        case VIR_DOMAIN_EVENT_SHUTDOWN:
            switch ((virDomainEventShutdownDetailType) detail) {
            case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
                ret = "Finished";
                break;
            }
            break;
J
Jiri Denemark 已提交
199 200 201 202 203
        case VIR_DOMAIN_EVENT_PMSUSPENDED:
            switch ((virDomainEventPMSuspendedDetailType) detail) {
            case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
                ret = "Memory";
                break;
204 205 206
            case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK:
                ret = "Disk";
                break;
J
Jiri Denemark 已提交
207 208
            }
            break;
209 210 211 212
    }
    return ret;
}

213 214 215 216 217
static int myDomainEventCallback1(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
218
{
219
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
220 221
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
222 223 224
    return 0;
}

225 226 227 228 229
static int myDomainEventCallback2(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virDomainPtr dom,
                                  int event,
                                  int detail,
                                  void *opaque ATTRIBUTE_UNUSED)
230
{
231
    printf("%s EVENT: Domain %s(%d) %s %s\n", __func__, virDomainGetName(dom),
232 233
           virDomainGetID(dom), eventToString(event),
           eventDetailToString(event, detail));
234 235 236
    return 0;
}

237 238 239 240 241 242 243 244 245 246
static int myDomainEventRebootCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                       virDomainPtr dom,
                                       void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) rebooted\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    return 0;
}

247 248 249 250 251
static int myDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          long long offset,
                                          void *opaque ATTRIBUTE_UNUSED)
{
252 253 254 255 256 257 258 259 260 261
    char *str = NULL;
    /* HACK: use asprintf since we have gnulib's wrapper for %lld on Win32
     * but don't have a printf() replacement with %lld */
    if (asprintf(&str, "%s EVENT: Domain %s(%d) rtc change %lld\n",
                 __func__, virDomainGetName(dom),
                 virDomainGetID(dom), offset) < 0)
        return 0;

    printf("%s", str);
    free(str);
262 263 264 265

    return 0;
}

266 267 268 269 270 271 272 273 274 275 276
static int myDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              virDomainPtr dom,
                                              unsigned long long actual,
                                              void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) balloon change %" PRIuMAX "KB\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom), (uintmax_t)actual);

    return 0;
}

277 278 279 280 281 282 283 284 285 286 287
static int myDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int action,
                                         void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) watchdog action=%d\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom), action);

    return 0;
}

288 289 290 291 292 293 294 295 296 297 298 299 300
static int myDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        virDomainPtr dom,
                                        const char *srcPath,
                                        const char *devAlias,
                                        int action,
                                        void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) io error path=%s alias=%s action=%d\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom), srcPath, devAlias, action);

    return 0;
}

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
static int myDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int phase,
                                         virDomainEventGraphicsAddressPtr local,
                                         virDomainEventGraphicsAddressPtr remote,
                                         const char *authScheme,
                                         virDomainEventGraphicsSubjectPtr subject,
                                         void *opaque ATTRIBUTE_UNUSED)
{
    int i;
    printf("%s EVENT: Domain %s(%d) graphics ", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    switch (phase) {
    case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
        printf("connected ");
        break;
    case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
        printf("initialized ");
        break;
    case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
        printf("disconnected ");
        break;
    }

    printf("local: family=%d node=%s service=%s ",
           local->family, local->node, local->service);
    printf("remote: family=%d node=%s service=%s ",
           remote->family, remote->node, remote->service);

    printf("auth: %s ", authScheme);
    for (i = 0 ; i < subject->nidentity ; i++) {
        printf(" identity: %s=%s",
               subject->identities[i].type,
               subject->identities[i].name);
    }
    printf("\n");

    return 0;
}

342 343 344 345 346 347 348 349 350 351 352
static int myDomainEventControlErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                             virDomainPtr dom,
                                             void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) control error\n", __func__, virDomainGetName(dom),
           virDomainGetID(dom));

    return 0;
}


353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
const char *diskChangeReasonStrings[] = {
    "startupPolicy", /* 0 */
    /* add new reason here */
};
static int myDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           const char *oldSrcPath,
                                           const char *newSrcPath,
                                           const char *devAlias,
                                           int reason,
                                           void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom),
           oldSrcPath, newSrcPath, devAlias, diskChangeReasonStrings[reason]);
    return 0;
}

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
const char *trayChangeReasonStrings[] = {
    "open",
    "close",
};

static int myDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           const char *devAlias,
                                           int reason,
                                           void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) removable disk's tray change devAlias: %s reason: %s\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom),
           devAlias, trayChangeReasonStrings[reason]);
    return 0;
}
387

O
Osier Yang 已提交
388 389 390 391 392
static int myDomainEventPMWakeupCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         int reason ATTRIBUTE_UNUSED,
                                         void *opaque ATTRIBUTE_UNUSED)
{
393
    printf("%s EVENT: Domain %s(%d) system pmwakeup\n",
O
Osier Yang 已提交
394 395 396 397
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

O
Osier Yang 已提交
398 399 400 401 402
static int myDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int reason ATTRIBUTE_UNUSED,
                                          void *opaque ATTRIBUTE_UNUSED)
{
403
    printf("%s EVENT: Domain %s(%d) system pmsuspend\n",
O
Osier Yang 已提交
404 405 406 407
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

408 409 410 411 412 413 414 415 416 417
static int myDomainEventPMSuspendDiskCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              virDomainPtr dom,
                                              int reason ATTRIBUTE_UNUSED,
                                              void *opaque ATTRIBUTE_UNUSED)
{
    printf("%s EVENT: Domain %s(%d) system pmsuspend-disk\n",
           __func__, virDomainGetName(dom), virDomainGetID(dom));
    return 0;
}

418 419 420
static void myFreeFunc(void *opaque)
{
    char *str = opaque;
421
    printf("%s: Freeing [%s]\n", __func__, str);
422 423 424
    free(str);
}

425 426 427 428 429 430 431 432

/* main test functions */

void usage(const char *pname)
{
    printf("%s uri\n", pname);
}

433 434 435 436 437 438 439 440

static void stop(int sig)
{
    printf("Exiting on signal %d\n", sig);
    run = 0;
}


441 442
int main(int argc, char **argv)
{
443 444
    int callback1ret = -1;
    int callback2ret = -1;
445
    int callback3ret = -1;
446
    int callback4ret = -1;
447
    int callback5ret = -1;
448
    int callback6ret = -1;
449
    int callback7ret = -1;
450
    int callback8ret = -1;
451
    int callback9ret = -1;
452
    int callback10ret = -1;
O
Osier Yang 已提交
453
    int callback11ret = -1;
O
Osier Yang 已提交
454
    int callback12ret = -1;
455
    int callback13ret = -1;
456
    int callback14ret = -1;
457
    struct sigaction action_stop;
458

459
    memset(&action_stop, 0, sizeof(action_stop));
460 461

    action_stop.sa_handler = stop;
462

463
    if (argc > 1 && STREQ(argv[1], "--help")) {
464 465 466
        usage(argv[0]);
        return -1;
    }
467

468
    virEventRegisterDefaultImpl();
469 470

    virConnectPtr dconn = NULL;
471 472 473
    dconn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
                               virConnectAuthPtrDefault,
                               VIR_CONNECT_RO);
474 475 476 477 478
    if (!dconn) {
        printf("error opening\n");
        return -1;
    }

479 480 481
    virConnectRegisterCloseCallback(dconn,
                                    connectClose, NULL, NULL);

482 483 484
    sigaction(SIGTERM, &action_stop, NULL);
    sigaction(SIGINT, &action_stop, NULL);

485
    VIR_DEBUG("Registering domain event cbs");
486 487

    /* Add 2 callbacks to prove this works with more than just one */
488 489
    callback1ret = virConnectDomainEventRegister(dconn, myDomainEventCallback1,
                                                 strdup("callback 1"), myFreeFunc);
490 491 492 493 494
    callback2ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback2),
                                                    strdup("callback 2"), myFreeFunc);
495 496 497 498 499
    callback3ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_REBOOT,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRebootCallback),
                                                    strdup("callback reboot"), myFreeFunc);
500 501 502 503 504
    callback4ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_RTC_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventRTCChangeCallback),
                                                    strdup("callback rtcchange"), myFreeFunc);
505 506 507 508 509
    callback5ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_WATCHDOG,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventWatchdogCallback),
                                                    strdup("callback watchdog"), myFreeFunc);
510 511 512 513 514
    callback6ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_IO_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventIOErrorCallback),
                                                    strdup("callback io error"), myFreeFunc);
515 516 517 518 519
    callback7ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_GRAPHICS,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventGraphicsCallback),
                                                    strdup("callback graphics"), myFreeFunc);
520 521 522 523 524
    callback8ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_CONTROL_ERROR,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventControlErrorCallback),
                                                    strdup("callback control error"), myFreeFunc);
525 526 527 528 529
    callback9ret = virConnectDomainEventRegisterAny(dconn,
                                                    NULL,
                                                    VIR_DOMAIN_EVENT_ID_DISK_CHANGE,
                                                    VIR_DOMAIN_EVENT_CALLBACK(myDomainEventDiskChangeCallback),
                                                    strdup("disk change"), myFreeFunc);
530 531 532 533 534
    callback10ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_TRAY_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventTrayChangeCallback),
                                                     strdup("tray change"), myFreeFunc);
O
Osier Yang 已提交
535 536 537 538 539
    callback11ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMWAKEUP,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMWakeupCallback),
                                                     strdup("pmwakeup"), myFreeFunc);
O
Osier Yang 已提交
540 541 542 543 544
    callback12ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMSUSPEND,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendCallback),
                                                     strdup("pmsuspend"), myFreeFunc);
545 546 547 548 549
    callback13ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventBalloonChangeCallback),
                                                     strdup("callback balloonchange"), myFreeFunc);
550 551 552 553 554
    callback14ret = virConnectDomainEventRegisterAny(dconn,
                                                     NULL,
                                                     VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK,
                                                     VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendDiskCallback),
                                                     strdup("pmsuspend-disk"), myFreeFunc);
555
    if ((callback1ret != -1) &&
556
        (callback2ret != -1) &&
557
        (callback3ret != -1) &&
558
        (callback4ret != -1) &&
559
        (callback5ret != -1) &&
560
        (callback6ret != -1) &&
561
        (callback7ret != -1) &&
562
        (callback9ret != -1) &&
O
Osier Yang 已提交
563
        (callback10ret != -1) &&
O
Osier Yang 已提交
564
        (callback11ret != -1) &&
565
        (callback12ret != -1) &&
566 567
        (callback13ret != -1) &&
        (callback14ret != -1)) {
568 569 570 571 572 573 574
        if (virConnectSetKeepAlive(dconn, 5, 3) < 0) {
            virErrorPtr err = virGetLastError();
            fprintf(stderr, "Failed to start keepalive protocol: %s\n",
                    err && err->message ? err->message : "Unknown error");
            run = 0;
        }

575
        while (run) {
576 577 578 579
            if (virEventRunDefaultImpl() < 0) {
                virErrorPtr err = virGetLastError();
                fprintf(stderr, "Failed to run event loop: %s\n",
                        err && err->message ? err->message : "Unknown error");
580
            }
581 582
        }

583
        VIR_DEBUG("Deregistering event handlers");
584
        virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
585
        virConnectDomainEventDeregisterAny(dconn, callback2ret);
586
        virConnectDomainEventDeregisterAny(dconn, callback3ret);
587
        virConnectDomainEventDeregisterAny(dconn, callback4ret);
588
        virConnectDomainEventDeregisterAny(dconn, callback5ret);
589
        virConnectDomainEventDeregisterAny(dconn, callback6ret);
590
        virConnectDomainEventDeregisterAny(dconn, callback7ret);
591
        virConnectDomainEventDeregisterAny(dconn, callback9ret);
592
        virConnectDomainEventDeregisterAny(dconn, callback10ret);
O
Osier Yang 已提交
593
        virConnectDomainEventDeregisterAny(dconn, callback11ret);
O
Osier Yang 已提交
594
        virConnectDomainEventDeregisterAny(dconn, callback12ret);
595
        virConnectDomainEventDeregisterAny(dconn, callback13ret);
596 597
        if (callback8ret != -1)
            virConnectDomainEventDeregisterAny(dconn, callback8ret);
598 599
    }

600
    VIR_DEBUG("Closing connection");
601
    if (dconn && virConnectClose(dconn) < 0) {
602 603
        printf("error closing\n");
    }
604

605 606 607
    printf("done\n");
    return 0;
}