Example #1
0
bool libxl__async_exec_inuse(const libxl__async_exec_state *aes)
{
    bool time_inuse = libxl__ev_time_isregistered(&aes->time);
    bool child_inuse = libxl__ev_child_inuse(&aes->child);
    assert(time_inuse == child_inuse);
    return child_inuse;
}
Example #2
0
static void helper_done(libxl__egc *egc, libxl__save_helper_state *shs)
{
    STATE_AO_GC(shs->ao);

    libxl__ev_fd_deregister(gc, &shs->readable);
    libxl__carefd_close(shs->pipes[0]);  shs->pipes[0] = 0;
    libxl__carefd_close(shs->pipes[1]);  shs->pipes[1] = 0;
    assert(!libxl__ev_child_inuse(&shs->child));
    if (shs->toolstack_data_file) fclose(shs->toolstack_data_file);

    shs->egc = egc;
    shs->completion_callback(egc, shs->caller_state,
                             shs->rc, shs->retval, shs->errnoval);
    shs->egc = 0;
}
Example #3
0
/* might be called at any time, provided it's init'd */
static void bootloader_stop(libxl__egc *egc,
                            libxl__bootloader_state *bl, int rc)
{
    STATE_AO_GC(bl->ao);
    int r;

    libxl__datacopier_kill(&bl->keystrokes);
    libxl__datacopier_kill(&bl->display);
    if (libxl__ev_child_inuse(&bl->child)) {
        r = kill(bl->child.pid, SIGTERM);
        if (r) LOGE(WARN, "%sfailed to kill bootloader [%lu]",
                        rc ? "after failure, " : "", (unsigned long)bl->child.pid);
    }
    if (!bl->rc)
        bl->rc = rc;
}
Example #4
0
static void helper_failed(libxl__egc *egc, libxl__save_helper_state *shs,
                          int rc)
{
    STATE_AO_GC(shs->ao);

    if (!shs->rc)
        shs->rc = rc;

    libxl__ev_fd_deregister(gc, &shs->readable);

    if (!libxl__ev_child_inuse(&shs->child)) {
        helper_done(egc, shs);
        return;
    }

    int r = kill(shs->child.pid, SIGKILL);
    if (r) LOGE(WARN, "failed to kill save/restore helper [%lu]",
                (unsigned long)shs->child.pid);
}
Example #5
0
static void async_exec_timeout(libxl__egc *egc,
                               libxl__ev_time *ev,
                               const struct timeval *requested_abs,
                               int rc)
{
    libxl__async_exec_state *aes = CONTAINER_OF(ev, *aes, time);
    STATE_AO_GC(aes->ao);

    if (!aes->rc)
        aes->rc = rc;

    libxl__ev_time_deregister(gc, &aes->time);

    assert(libxl__ev_child_inuse(&aes->child));
    LOG(ERROR, "killing execution of %s because of timeout", aes->what);

    if (kill(aes->child.pid, SIGKILL)) {
        LOGEV(ERROR, errno, "unable to kill %s [%ld]",
              aes->what, (unsigned long)aes->child.pid);
    }

    return;
}
Example #6
0
int libxl__openptys(libxl__openpty_state *op,
                    struct termios *termp,
                    struct winsize *winp) {
    /*
     * This is completely crazy.  openpty calls grantpt which the spec
     * says may fork, and may not be called with a SIGCHLD handler.
     * Now our application may have a SIGCHLD handler so that's bad.
     * We could perhaps block it but we'd need to block it on all
     * threads.  This is just Too Hard.
     *
     * So instead, we run openpty in a child process.  That child
     * process then of course has only our own thread and our own
     * signal handlers.  We pass the fds back.
     *
     * Since our only current caller actually wants two ptys, we
     * support calling openpty multiple times for a single fork.
     */
    STATE_AO_GC(op->ao);
    int count = op->count;
    int r, i, rc, sockets[2], ptyfds[count][2];
    libxl__carefd *for_child = 0;
    pid_t pid = -1;

    for (i=0; i<count; i++) {
        ptyfds[i][0] = ptyfds[i][1] = -1;
        libxl__openpty_result *res = &op->results[i];
        assert(!res->master);
        assert(!res->slave);
    }
    sockets[0] = sockets[1] = -1; /* 0 is for us, 1 for our child */

    libxl__carefd_begin();
    r = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
    if (r) { sockets[0] = sockets[1] = -1; }
    for_child = libxl__carefd_opened(CTX, sockets[1]);
    if (r) { LOGE(ERROR,"socketpair failed"); rc = ERROR_FAIL; goto out; }

    pid = libxl__ev_child_fork(gc, &op->child, openpty_exited);
    if (pid == -1) {
        rc = ERROR_FAIL;
        goto out;
    }

    if (!pid) {
        /* child */
        close(sockets[0]);
        signal(SIGCHLD, SIG_DFL);

        for (i=0; i<count; i++) {
            r = openpty(&ptyfds[i][0], &ptyfds[i][1], NULL, termp, winp);
            if (r) { LOGE(ERROR,"openpty failed"); _exit(-1); }
        }
        rc = libxl__sendmsg_fds(gc, sockets[1], "",1,
                                2*count, &ptyfds[0][0], "ptys");
        if (rc) { LOGE(ERROR,"sendmsg to parent failed"); _exit(-1); }
        _exit(0);
    }

    libxl__carefd_close(for_child);
    for_child = 0;

    /* this should be fast so do it synchronously */

    libxl__carefd_begin();
    char buf[1];
    rc = libxl__recvmsg_fds(gc, sockets[0], buf,1,
                            2*count, &ptyfds[0][0], "ptys");
    if (!rc) {
        for (i=0; i<count; i++) {
            libxl__openpty_result *res = &op->results[i];
            res->master = libxl__carefd_record(CTX, ptyfds[i][0]);
            res->slave =  libxl__carefd_record(CTX, ptyfds[i][1]);
        }
    }
    /* now the pty fds are in the carefds, if they were ever open */
    libxl__carefd_unlock();
    if (rc)
        goto out;

    rc = 0;

 out:
    if (sockets[0] >= 0) close(sockets[0]);
    libxl__carefd_close(for_child);
    if (libxl__ev_child_inuse(&op->child)) {
        op->rc = rc;
        /* we will get a callback when the child dies */
        return 0;
    }

    assert(rc);
    openpty_cleanup(op);
    return rc;
}