/* 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; }
int libxl__datacopier_start(libxl__datacopier_state *dc) { int rc; STATE_AO_GC(dc->ao); libxl__datacopier_init(dc); assert(dc->readfd >= 0 || dc->writefd >= 0); assert(!(dc->readbuf && dc->bytes_to_read == -1)); dc->abrt.ao = ao; dc->abrt.callback = datacopier_abort; rc = libxl__ao_abortable_register(&dc->abrt); if (rc) goto out; if (dc->readfd >= 0) { rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable, dc->readfd, POLLIN); if (rc) goto out; } if (dc->writefd >= 0) { rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); if (rc) goto out; } return 0; out: libxl__datacopier_kill(dc); return rc; }
static void bootloader_cleanup(libxl__egc *egc, libxl__bootloader_state *bl) { STATE_AO_GC(bl->ao); int i; if (bl->outputpath) libxl__remove_file(gc, bl->outputpath); if (bl->outputdir) libxl__remove_directory(gc, bl->outputdir); libxl__domaindeathcheck_stop(gc,&bl->deathcheck); libxl__datacopier_kill(&bl->keystrokes); libxl__datacopier_kill(&bl->display); for (i=0; i<2; i++) { libxl__carefd_close(bl->ptys[i].master); libxl__carefd_close(bl->ptys[i].slave); } if (bl->display.log) { fclose(bl->display.log); bl->display.log = NULL; } }
static void bootloader_finished(libxl__egc *egc, libxl__ev_child *child, pid_t pid, int status) { libxl__bootloader_state *bl = CONTAINER_OF(child, *bl, child); STATE_AO_GC(bl->ao); int rc; libxl__datacopier_kill(&bl->keystrokes); libxl__datacopier_kill(&bl->display); if (status) { if (bl->got_pollhup && WIFSIGNALED(status) && WTERMSIG(status)==SIGTERM) LOG(ERROR, "got POLLHUP, sent SIGTERM"); LOG(ERROR, "bootloader failed - consult logfile %s", bl->logfile); libxl_report_child_exitstatus(CTX, XTL_ERROR, "bootloader", pid, status); rc = ERROR_FAIL; goto out; } else { LOG(DEBUG, "bootloader completed"); } if (bl->rc) { /* datacopier went wrong */ rc = bl->rc; goto out; } rc = parse_bootloader_result(egc, bl); if (rc) goto out; rc = 0; LOG(DEBUG, "bootloader execution successful"); out: bootloader_callback(egc, bl, rc); }
static int datacopier_pollhup_handled(libxl__egc *egc, libxl__datacopier_state *dc, int fd, short revents, int onwrite) { STATE_AO_GC(dc->ao); if (dc->callback_pollhup && (revents & POLLHUP)) { LOG(DEBUG, "received POLLHUP on fd %d: %s during copy of %s", fd, onwrite ? dc->writewhat : dc->readwhat, dc->copywhat); libxl__datacopier_kill(dc); dc->callback_pollhup(egc, dc, ERROR_FAIL, onwrite, -1); return 1; } return 0; }
int libxl__datacopier_start(libxl__datacopier_state *dc) { int rc; STATE_AO_GC(dc->ao); libxl__datacopier_init(dc); rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable, dc->readfd, POLLIN); if (rc) goto out; rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); if (rc) goto out; return 0; out: libxl__datacopier_kill(dc); return rc; }
static void datacopier_callback(libxl__egc *egc, libxl__datacopier_state *dc, int rc, int onwrite, int errnoval) { libxl__datacopier_kill(dc); dc->callback(egc, dc, rc, onwrite, errnoval); }