예제 #1
0
파일: virdbus.c 프로젝트: avdv/libvirt
static dbus_bool_t virDBusAddWatch(DBusWatch *watch,
                                   void *data)
{
    int flags = 0;
    int fd;
    struct virDBusWatch *info;

    if (VIR_ALLOC(info) < 0)
        return 0;

    if (dbus_watch_get_enabled(watch))
        flags = virDBusTranslateWatchFlags(dbus_watch_get_flags(watch));

# if HAVE_DBUS_WATCH_GET_UNIX_FD
    fd = dbus_watch_get_unix_fd(watch);
# else
    fd = dbus_watch_get_fd(watch);
# endif
    info->bus = (DBusConnection *)data;
    info->watch = virEventAddHandle(fd, flags,
                                    virDBusWatchCallback,
                                    watch, NULL);
    if (info->watch < 0) {
        VIR_FREE(info);
        return 0;
    }
    dbus_watch_set_data(watch, info, virDBusWatchFree);

    return 1;
}
예제 #2
0
static int
libxlDomainObjFDRegisterEventHook(void *priv,
                                  int fd,
                                  void **hndp,
                                  short events,
                                  void *xl_priv)
{
    int vir_events = VIR_EVENT_HANDLE_ERROR;
    libxlEventHookInfoPtr info;

    if (VIR_ALLOC(info) < 0)
        return -1;

    info->priv = priv;
    info->xl_priv = xl_priv;

    if (events & POLLIN)
        vir_events |= VIR_EVENT_HANDLE_READABLE;
    if (events & POLLOUT)
        vir_events |= VIR_EVENT_HANDLE_WRITABLE;

    info->id = virEventAddHandle(fd, vir_events, libxlDomainObjFDEventCallback,
                                 info, libxlDomainObjFDEventHookInfoFree);
    if (info->id < 0) {
        VIR_FREE(info);
        return -1;
    }

    *hndp = info;

    return 0;
}
예제 #3
0
virLogHandlerPtr
virLogHandlerNewPostExecRestart(virJSONValuePtr object,
                                bool privileged,
                                virLogHandlerShutdownInhibitor inhibitor,
                                void *opaque)
{
    virLogHandlerPtr handler;
    virJSONValuePtr files;
    ssize_t n;
    size_t i;

    if (!(handler = virLogHandlerNew(privileged,
                                     inhibitor,
                                     opaque)))
        return NULL;

    if (!(files = virJSONValueObjectGet(object, "files"))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Missing files data from JSON file"));
        goto error;
    }

    if ((n = virJSONValueArraySize(files)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Malformed files data from JSON file"));
        goto error;
    }

    for (i = 0; i < n; i++) {
        virLogHandlerLogFilePtr file;
        virJSONValuePtr child = virJSONValueArrayGet(files, i);

        if (!(file = virLogHandlerLogFilePostExecRestart(handler, child)))
            goto error;

        if (VIR_APPEND_ELEMENT_COPY(handler->files, handler->nfiles, file) < 0)
            goto error;

        if ((file->watch = virEventAddHandle(file->pipefd,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virLogHandlerDomainLogFileEvent,
                                             handler,
                                             NULL)) < 0) {
            VIR_DELETE_ELEMENT(handler->files, handler->nfiles - 1, handler->nfiles);
            goto error;
        }
    }


    return handler;

 error:
    virObjectUnref(handler);
    return NULL;
}
static int
virFDStreamAddCallback(virStreamPtr st,
                       int events,
                       virStreamEventCallback cb,
                       void *opaque,
                       virFreeCallback ff)
{
    struct virFDStreamData *fdst = st->privateData;
    int ret = -1;

    if (!fdst) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("stream is not open"));
        return -1;
    }

    virMutexLock(&fdst->lock);
    if (fdst->watch != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("stream already has a callback registered"));
        goto cleanup;
    }

    if ((fdst->watch = virEventAddHandle(fdst->fd,
                                           events,
                                           virFDStreamEvent,
                                           st,
                                           virFDStreamCallbackFree)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot register file watch on stream"));
        goto cleanup;
    }

    fdst->cbRemoved = false;
    fdst->cb = cb;
    fdst->opaque = opaque;
    fdst->ff = ff;
    fdst->events = events;
    fdst->abortCallbackCalled = false;
    virStreamRef(st);

    ret = 0;

 cleanup:
    virMutexUnlock(&fdst->lock);
    return ret;
}
예제 #5
0
bhyveMonitorPtr
bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
{
    bhyveMonitorPtr mon = NULL;
    struct kevent kev;
    int rc;

    if (VIR_ALLOC(mon) < 0)
        return NULL;

    mon->driver = driver;

    mon->kq = kqueue();
    if (mon->kq < 0) {
        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
                       _("Unable to create kqueue"));
        goto cleanup;
    }

    EV_SET(&kev, vm->pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, mon);
    rc = kevent(mon->kq, &kev, 1, NULL, 0, NULL);
    if (rc < 0) {
        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
                       _("Unable to register process kevent"));
        goto cleanup;
    }

    mon->watch = virEventAddHandle(mon->kq,
                                   VIR_EVENT_HANDLE_READABLE |
                                   VIR_EVENT_HANDLE_ERROR |
                                   VIR_EVENT_HANDLE_HANGUP,
                                   bhyveMonitorIO,
                                   vm,
                                   bhyveMonitorRelease);
    if (mon->watch < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unable to register monitor events"));
        goto cleanup;
    }

    return mon;

 cleanup:
    bhyveMonitorRelease(mon);
    return NULL;
}
예제 #6
0
static void lxcServerAccept(int watch ATTRIBUTE_UNUSED, int fd, int events ATTRIBUTE_UNUSED, void *opaque)
{
    struct lxcMonitor *monitor = opaque;
    int client;

    if ((client = accept(fd, NULL, NULL)) < 0) {
        /* First reflex may be simply to declare accept failure
           to be a fatal error.  However, accept may fail when
           a client quits between the above poll and here.
           That case is not fatal, but rather to be expected,
           if not common, so ignore it.  */
        if (ignorable_accept_errno(errno))
            return;
        virReportSystemError(errno, "%s",
                             _("Unable to accept monitor client"));
        virMutexLock(&lock);
        quit = true;
        virMutexUnlock(&lock);
        return;
    }
    VIR_DEBUG("New client %d (old %d)\n", client, monitor->clientFd);
    VIR_FORCE_CLOSE(monitor->clientFd);
    virEventRemoveHandle(monitor->clientWatch);

    monitor->clientFd = client;
    if ((monitor->clientWatch = virEventAddHandle(monitor->clientFd,
                                                  VIR_EVENT_HANDLE_READABLE,
                                                  lxcClientIO,
                                                  monitor,
                                                  NULL)) < 0) {
        lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                 _("Unable to watch client socket"));
        virMutexLock(&lock);
        quit = true;
        virMutexUnlock(&lock);
        return;
    }
}
예제 #7
0
파일: virnetlink.c 프로젝트: intgr/libvirt
/**
 * virNetlinkEventServiceStart:
 *
 * start a monitor to receive netlink messages for libvirtd.
 * This registers a netlink socket with the event interface.
 *
 * Returns -1 if the monitor cannot be registered, 0 upon success
 */
int
virNetlinkEventServiceStart(void)
{
    virNetlinkEventSrvPrivatePtr srv;
    int fd;
    int ret = -1;

    if (server)
        return 0;

    VIR_INFO("starting netlink event service");

    if (VIR_ALLOC(srv) < 0) {
        virReportOOMError();
        return -1;
    }

    if (virMutexInit(&srv->lock) < 0) {
        VIR_FREE(srv);
        return -1;
    }

    virNetlinkEventServerLock(srv);

    /* Allocate a new socket and get fd */
    srv->netlinknh = virNetlinkAlloc();

    if (!srv->netlinknh) {
        virReportSystemError(errno,
                             "%s", _("cannot allocate nlhandle for virNetlinkEvent server"));
        goto error_locked;
    }

    if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot connect to netlink socket"));
        goto error_server;
    }

    fd = nl_socket_get_fd(srv->netlinknh);

    if (fd < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot get netlink socket fd"));
        goto error_server;
    }

    if (nl_socket_set_nonblocking(srv->netlinknh)) {
        virReportSystemError(errno, "%s",
                             _("cannot set netlink socket nonblocking"));
        goto error_server;
    }

    if ((srv->eventwatch = virEventAddHandle(fd,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virNetlinkEventCallback,
                                             srv, NULL)) < 0) {
        netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("Failed to add netlink event handle watch"));
        goto error_server;
    }

    srv->netlinkfd = fd;
    VIR_DEBUG("netlink event listener on fd: %i running", fd);

    ret = 0;
    server = srv;

error_server:
    if (ret < 0) {
        nl_close(srv->netlinknh);
        virNetlinkFree(srv->netlinknh);
    }
error_locked:
    virNetlinkEventServerUnlock(srv);
    if (ret < 0) {
        virMutexDestroy(&srv->lock);
        VIR_FREE(srv);
    }
    return ret;
}
예제 #8
0
/**
 * virNetlinkEventServiceStart:
 *
 * start a monitor to receive netlink messages for libvirtd.
 * This registers a netlink socket with the event interface.
 *
 * @protocol: netlink protocol
 * @groups: broadcast groups to join in
 * Returns -1 if the monitor cannot be registered, 0 upon success
 */
int
virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups)
{
    virNetlinkEventSrvPrivatePtr srv;
    int fd;
    int ret = -1;

    if (protocol >= MAX_LINKS) {
        virReportSystemError(EINVAL,
                             _("invalid protocol argument: %d"), protocol);
        return -EINVAL;
    }

    if (server[protocol])
        return 0;

    VIR_INFO("starting netlink event service with protocol %d", protocol);

    if (VIR_ALLOC(srv) < 0)
        return -1;

    if (virMutexInit(&srv->lock) < 0) {
        VIR_FREE(srv);
        return -1;
    }

    virNetlinkEventServerLock(srv);

    /* Allocate a new socket and get fd */
    if (!(srv->netlinknh = virNetlinkCreateSocket(protocol)))
        goto error_locked;

    fd = nl_socket_get_fd(srv->netlinknh);
    if (fd < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot get netlink socket fd"));
        goto error_server;
    }

    if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot add netlink membership"));
        goto error_server;
    }

    if (nl_socket_set_nonblocking(srv->netlinknh)) {
        virReportSystemError(errno, "%s",
                             _("cannot set netlink socket nonblocking"));
        goto error_server;
    }

    if ((srv->eventwatch = virEventAddHandle(fd,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virNetlinkEventCallback,
                                             srv, NULL)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to add netlink event handle watch"));
        goto error_server;
    }

    srv->netlinkfd = fd;
    VIR_DEBUG("netlink event listener on fd: %i running", fd);

    ret = 0;
    server[protocol] = srv;

 error_server:
    if (ret < 0) {
        nl_close(srv->netlinknh);
        virNetlinkFree(srv->netlinknh);
    }
 error_locked:
    virNetlinkEventServerUnlock(srv);
    if (ret < 0) {
        virMutexDestroy(&srv->lock);
        VIR_FREE(srv);
    }
    return ret;
}
예제 #9
0
/**
 * xenInotifyOpen:
 * @conn: pointer to the connection block
 * @name: URL for the target, NULL for local
 * @flags: combination of virDrvOpenFlag(s)
 *
 * Connects and starts listening for inotify events
 *
 * Returns 0 or -1 in case of error.
 */
int
xenInotifyOpen(virConnectPtr conn,
               virConnectAuthPtr auth ATTRIBUTE_UNUSED,
               unsigned int flags)
{
    DIR *dh;
    struct dirent *ent;
    char *path;
    xenUnifiedPrivatePtr priv = conn->privateData;

    virCheckFlags(VIR_CONNECT_RO, -1);

    if (priv->configDir) {
        priv->useXenConfigCache = 1;
    } else {
        /* /var/lib/xend/domains/<uuid>/config.sxp */
        priv->configDir = XEND_DOMAINS_DIR;
        priv->useXenConfigCache = 0;

        if (VIR_ALLOC(priv->configInfoList) < 0)
            return -1;

        /* populate initial list */
        if (!(dh = opendir(priv->configDir))) {
            virReportSystemError(errno,
                                 _("cannot open directory: %s"),
                                 priv->configDir);
            return -1;
        }
        while ((ent = readdir(dh))) {
            if (STRPREFIX(ent->d_name, "."))
                continue;

            /* Build the full file path */
            if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) {
                closedir(dh);
                return -1;
            }

            if (xenInotifyAddDomainConfigInfo(conn, path) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("Error adding file to config list"));
                closedir(dh);
                VIR_FREE(path);
                return -1;
            }

            VIR_FREE(path);
        }
        closedir(dh);
    }

    if ((priv->inotifyFD = inotify_init()) < 0) {
        virReportSystemError(errno,
                             "%s", _("initializing inotify"));
        return -1;
    }

    VIR_DEBUG("Adding a watch on %s", priv->configDir);
    if (inotify_add_watch(priv->inotifyFD,
                          priv->configDir,
                          IN_CREATE |
                          IN_CLOSE_WRITE | IN_DELETE |
                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
        virReportSystemError(errno,
                             _("adding watch on %s"),
                             priv->configDir);
        return -1;
    }

    VIR_DEBUG("Building initial config cache");
    if (priv->useXenConfigCache &&
        xenXMConfigCacheRefresh(conn) < 0) {
        VIR_DEBUG("Failed to enable XM config cache %s", conn->err.message);
        return -1;
    }

    VIR_DEBUG("Registering with event loop");
    /* Add the handle for monitoring */
    if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
                                                xenInotifyEvent, conn, NULL)) < 0) {
        VIR_DEBUG("Failed to add inotify handle, disabling events");
    }

    return 0;
}
예제 #10
0
qemuAgentPtr
qemuAgentOpen(virDomainObjPtr vm,
              virDomainChrSourceDefPtr config,
              qemuAgentCallbacksPtr cb)
{
    qemuAgentPtr mon;

    if (!cb || !cb->eofNotify) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("EOF notify callback must be supplied"));
        return NULL;
    }

    if (qemuAgentInitialize() < 0)
        return NULL;

    if (!(mon = virObjectNew(qemuAgentClass)))
        return NULL;

    if (virMutexInit(&mon->lock) < 0) {
        virReportSystemError(errno, "%s",
                             _("cannot initialize monitor mutex"));
        VIR_FREE(mon);
        return NULL;
    }
    if (virCondInit(&mon->notify) < 0) {
        virReportSystemError(errno, "%s",
                             _("cannot initialize monitor condition"));
        virMutexDestroy(&mon->lock);
        VIR_FREE(mon);
        return NULL;
    }
    mon->fd = -1;
    mon->vm = vm;
    mon->cb = cb;
    qemuAgentLock(mon);

    switch (config->type) {
    case VIR_DOMAIN_CHR_TYPE_UNIX:
        mon->fd = qemuAgentOpenUnix(config->data.nix.path, vm->pid,
                                    &mon->connectPending);
        break;

    case VIR_DOMAIN_CHR_TYPE_PTY:
        mon->fd = qemuAgentOpenPty(config->data.file.path);
        break;

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to handle monitor type: %s"),
                       virDomainChrTypeToString(config->type));
        goto cleanup;
    }

    if (mon->fd == -1)
        goto cleanup;

    if ((mon->watch = virEventAddHandle(mon->fd,
                                        VIR_EVENT_HANDLE_HANGUP |
                                        VIR_EVENT_HANDLE_ERROR |
                                        VIR_EVENT_HANDLE_READABLE |
                                        (mon->connectPending ?
                                         VIR_EVENT_HANDLE_WRITABLE :
                                         0),
                                        qemuAgentIO,
                                        mon,
                                        virObjectFreeCallback)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unable to register monitor events"));
        goto cleanup;
    }
    virObjectRef(mon);

    VIR_DEBUG("New mon %p fd =%d watch=%d", mon, mon->fd, mon->watch);
    qemuAgentUnlock(mon);

    return mon;

cleanup:
    /* We don't want the 'destroy' callback invoked during
     * cleanup from construction failure, because that can
     * give a double-unref on virDomainObjPtr in the caller,
     * so kill the callbacks now.
     */
    mon->cb = NULL;
    qemuAgentUnlock(mon);
    qemuAgentClose(mon);
    return NULL;
}
예제 #11
0
int
virshRunConsole(vshControl *ctl,
                virDomainPtr dom,
                const char *dev_name,
                unsigned int flags)
{
    virConsolePtr con = NULL;
    virshControlPtr priv = ctl->privData;
    int ret = -1;

    struct sigaction old_sigquit;
    struct sigaction old_sigterm;
    struct sigaction old_sigint;
    struct sigaction old_sighup;
    struct sigaction old_sigpipe;
    struct sigaction sighandler = {.sa_handler = virConsoleHandleSignal,
                                   .sa_flags = SA_SIGINFO };

    sigemptyset(&sighandler.sa_mask);

    /* Put STDIN into raw mode so that stuff typed does not echo to the screen
     * (the TTY reads will result in it being echoed back already), and also
     * ensure Ctrl-C, etc is blocked, and misc other bits */
    if (vshTTYMakeRaw(ctl, true) < 0)
        goto resettty;

    if (!(con = virConsoleNew()))
        goto resettty;

    virObjectLock(con);

    /* Trap all common signals so that we can safely restore the original
     * terminal settings on STDIN before the process exits - people don't like
     * being left with a messed up terminal ! */
    sigaction(SIGQUIT, &sighandler, &old_sigquit);
    sigaction(SIGTERM, &sighandler, &old_sigterm);
    sigaction(SIGINT,  &sighandler, &old_sigint);
    sigaction(SIGHUP,  &sighandler, &old_sighup);
    sigaction(SIGPIPE, &sighandler, &old_sigpipe);

    con->escapeChar = virshGetEscapeChar(priv->escapeChar);
    con->st = virStreamNew(virDomainGetConnect(dom),
                           VIR_STREAM_NONBLOCK);
    if (!con->st)
        goto cleanup;

    if (virDomainOpenConsole(dom, dev_name, con->st, flags) < 0)
        goto cleanup;

    virObjectRef(con);
    if ((con->stdinWatch = virEventAddHandle(STDIN_FILENO,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virConsoleEventOnStdin,
                                             con,
                                             virObjectFreeCallback)) < 0) {
        virObjectUnref(con);
        goto cleanup;
    }

    virObjectRef(con);
    if ((con->stdoutWatch = virEventAddHandle(STDOUT_FILENO,
                                              0,
                                              virConsoleEventOnStdout,
                                              con,
                                              virObjectFreeCallback)) < 0) {
        virObjectUnref(con);
        goto cleanup;
    }

    virObjectRef(con);
    if (virStreamEventAddCallback(con->st,
                                  VIR_STREAM_EVENT_READABLE,
                                  virConsoleEventOnStream,
                                  con,
                                  virObjectFreeCallback) < 0) {
        virObjectUnref(con);
        goto cleanup;
    }

    while (!con->quit) {
        if (virCondWait(&con->cond, &con->parent.lock) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to wait on console condition"));
            goto cleanup;
        }
    }

    if (con->error.code == VIR_ERR_OK)
        ret = 0;

 cleanup:
    virConsoleShutdown(con);

    if (ret < 0) {
        vshResetLibvirtError();
        virSetError(&con->error);
        vshSaveLibvirtHelperError();
    }

    virObjectUnlock(con);
    virObjectUnref(con);

    /* Restore original signal handlers */
    sigaction(SIGQUIT, &old_sigquit, NULL);
    sigaction(SIGTERM, &old_sigterm, NULL);
    sigaction(SIGINT,  &old_sigint,  NULL);
    sigaction(SIGHUP,  &old_sighup,  NULL);
    sigaction(SIGPIPE, &old_sigpipe, NULL);

 resettty:
    /* Put STDIN back into the (sane?) state we found
       it in before starting */
    vshTTYRestore(ctl);

    return ret;
}
예제 #12
0
파일: console.c 프로젝트: mohankku/libvirt
int vshRunConsole(virDomainPtr dom,
                  const char *dev_name,
                  const char *escape_seq,
                  unsigned int flags)
{
    int ret = -1;
    struct termios ttyattr;
    void (*old_sigquit)(int);
    void (*old_sigterm)(int);
    void (*old_sigint)(int);
    void (*old_sighup)(int);
    void (*old_sigpipe)(int);
    virConsolePtr con = NULL;

    /* Put STDIN into raw mode so that stuff typed
       does not echo to the screen (the TTY reads will
       result in it being echoed back already), and
       also ensure Ctrl-C, etc is blocked, and misc
       other bits */
    if (vshMakeStdinRaw(&ttyattr, true) < 0)
        goto resettty;

    /* Trap all common signals so that we can safely restore
       the original terminal settings on STDIN before the
       process exits - people don't like being left with a
       messed up terminal ! */
    old_sigquit = signal(SIGQUIT, do_signal);
    old_sigterm = signal(SIGTERM, do_signal);
    old_sigint = signal(SIGINT, do_signal);
    old_sighup = signal(SIGHUP, do_signal);
    old_sigpipe = signal(SIGPIPE, do_signal);
    got_signal = 0;

    if (VIR_ALLOC(con) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    con->escapeChar = vshGetEscapeChar(escape_seq);
    con->st = virStreamNew(virDomainGetConnect(dom),
                           VIR_STREAM_NONBLOCK);
    if (!con->st)
        goto cleanup;

    if (virDomainOpenConsole(dom, dev_name, con->st, flags) < 0)
        goto cleanup;

    if (virCondInit(&con->cond) < 0 || virMutexInit(&con->lock) < 0)
        goto cleanup;

    con->stdinWatch = virEventAddHandle(STDIN_FILENO,
                                        VIR_EVENT_HANDLE_READABLE,
                                        virConsoleEventOnStdin,
                                        con,
                                        NULL);
    con->stdoutWatch = virEventAddHandle(STDOUT_FILENO,
                                         0,
                                         virConsoleEventOnStdout,
                                         con,
                                         NULL);

    virStreamEventAddCallback(con->st,
                              VIR_STREAM_EVENT_READABLE,
                              virConsoleEventOnStream,
                              con,
                              NULL);

    while (!con->quit) {
        if (virCondWait(&con->cond, &con->lock) < 0) {
            VIR_ERROR(_("unable to wait on console condition"));
            goto cleanup;
        }
    }

    ret = 0;

 cleanup:

    if (con) {
        if (con->st)
            virStreamFree(con->st);
        virMutexDestroy(&con->lock);
        ignore_value(virCondDestroy(&con->cond));
        VIR_FREE(con);
    }

    /* Restore original signal handlers */
    signal(SIGPIPE, old_sigpipe);
    signal(SIGHUP, old_sighup);
    signal(SIGINT, old_sigint);
    signal(SIGTERM, old_sigterm);
    signal(SIGQUIT, old_sigquit);

resettty:
    /* Put STDIN back into the (sane?) state we found
       it in before starting */
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);

    return ret;
}
예제 #13
0
/**
 * lxcControllerMain
 * @serverFd: server socket fd to accept client requests
 * @clientFd: initial client which is the libvirtd daemon
 * @hostFd: open fd for application facing Pty
 * @contFd: open fd for container facing Pty
 *
 * Processes I/O on consoles and the monitor
 *
 * Returns 0 on success or -1 in case of error
 */
static int lxcControllerMain(int serverFd,
                             int clientFd,
                             int *hostFds,
                             int *contFds,
                             size_t nFds,
                             pid_t container)
{
    struct lxcConsole *consoles;
    struct lxcMonitor monitor = {
        .serverFd = serverFd,
        .clientFd = clientFd,
    };
    virErrorPtr err;
    int rc = -1;
    size_t i;

    if (virMutexInit(&lock) < 0)
        goto cleanup2;

    if (pipe2(sigpipe, O_CLOEXEC|O_NONBLOCK) < 0) {
        virReportSystemError(errno, "%s",
                             _("Cannot create signal pipe"));
        goto cleanup;
    }

    if (virEventAddHandle(sigpipe[0],
                          VIR_EVENT_HANDLE_READABLE,
                          lxcSignalChildIO,
                          &container,
                          NULL) < 0) {
        lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                 _("Unable to watch signal pipe"));
        goto cleanup;
    }

    if (signal(SIGCHLD, lxcSignalChildHandler) == SIG_ERR) {
        virReportSystemError(errno, "%s",
                             _("Cannot install signal handler"));
        goto cleanup;
    }

    VIR_DEBUG("serverFd=%d clientFd=%d",
              serverFd, clientFd);
    virResetLastError();

    if ((monitor.serverWatch = virEventAddHandle(monitor.serverFd,
                                                 VIR_EVENT_HANDLE_READABLE,
                                                 lxcServerAccept,
                                                 &monitor,
                                                 NULL)) < 0) {
        lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                 _("Unable to watch monitor socket"));
        goto cleanup;
    }

    if (monitor.clientFd != -1 &&
        (monitor.clientWatch = virEventAddHandle(monitor.clientFd,
                                                 VIR_EVENT_HANDLE_READABLE,
                                                 lxcClientIO,
                                                 &monitor,
                                                 NULL)) < 0) {
        lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                 _("Unable to watch client socket"));
        goto cleanup;
    }

    if (VIR_ALLOC_N(consoles, nFds) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    for (i = 0 ; i < nFds ; i++) {
        consoles[i].hostFd = hostFds[i];
        consoles[i].contFd = contFds[i];

        if ((consoles[i].hostWatch = virEventAddHandle(consoles[i].hostFd,
                                                       VIR_EVENT_HANDLE_READABLE,
                                                       lxcConsoleIO,
                                                       &consoles[i],
                                                       NULL)) < 0) {
            lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("Unable to watch host console PTY"));
            goto cleanup;
        }

        if ((consoles[i].contWatch = virEventAddHandle(consoles[i].contFd,
                                                       VIR_EVENT_HANDLE_READABLE,
                                                       lxcConsoleIO,
                                                       &consoles[i],
                                                       NULL)) < 0) {
            lxcError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("Unable to watch host console PTY"));
            goto cleanup;
        }
    }

    virMutexLock(&lock);
    while (!quit) {
        virMutexUnlock(&lock);
        if (virEventRunDefaultImpl() < 0)
            goto cleanup;
        virMutexLock(&lock);
    }
    virMutexUnlock(&lock);

    err = virGetLastError();
    if (!err || err->code == VIR_ERR_OK)
        rc = 0;

cleanup:
    virMutexDestroy(&lock);
    signal(SIGCHLD, SIG_DFL);
cleanup2:
    VIR_FORCE_CLOSE(monitor.serverFd);
    VIR_FORCE_CLOSE(monitor.clientFd);
    VIR_FREE(consoles);
    return rc;
}
예제 #14
0
/**
 * xenStoreOpen:
 * @conn: pointer to the connection block
 * @name: URL for the target, NULL for local
 * @flags: combination of virDrvOpenFlag(s)
 *
 * Connects to the Xen hypervisor.
 *
 * Returns 0 or -1 in case of error.
 */
int
xenStoreOpen(virConnectPtr conn,
             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
             unsigned int flags)
{
    xenUnifiedPrivatePtr priv = conn->privateData;

    virCheckFlags(VIR_CONNECT_RO, -1);

    if (flags & VIR_CONNECT_RO)
        priv->xshandle = xs_daemon_open_readonly();
    else
        priv->xshandle = xs_daemon_open();

    if (priv->xshandle == NULL) {
        /*
         * not being able to connect via the socket as an unprivileged
         * user is rather normal, this should fallback to the proxy (or
         * remote) mechanism.
         */
        if (xenHavePrivilege()) {
            virReportError(VIR_ERR_NO_XEN,
                           "%s", _("failed to connect to Xen Store"));
        }
        return -1;
    }

    /* Init activeDomainList */
    if (VIR_ALLOC(priv->activeDomainList) < 0)
        return -1;

    /* Init watch list before filling in domInfoList,
       so we can know if it is the first time through
       when the callback fires */
    if (VIR_ALLOC(priv->xsWatchList) < 0)
        return -1;

    /* This will get called once at start */
    if (xenStoreAddWatch(conn, "@releaseDomain",
                         "releaseDomain", xenStoreDomainReleased, priv) < 0)
    {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("adding watch @releaseDomain"));
        return -1;
    }

    /* The initial call of this will fill domInfoList */
    if (xenStoreAddWatch(conn, "@introduceDomain",
                         "introduceDomain", xenStoreDomainIntroduced, priv) < 0)
    {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("adding watch @introduceDomain"));
        return -1;
    }

    /* Add an event handle */
    if ((priv->xsWatch = virEventAddHandle(xs_fileno(priv->xshandle),
                                           VIR_EVENT_HANDLE_READABLE,
                                           xenStoreWatchEvent,
                                           conn,
                                           NULL)) < 0)
        VIR_DEBUG("Failed to add event handle, disabling events");

    return 0;
}