#include #include #include #include #include #include #include #include #include char * malloc_copy(const char *src) { int len = strlen(src); char * dst = malloc(strlen(src)+1); strncpy(dst, src, len); return dst; } libxl_ctx *ctx; int self_pipe_wakeup(int fd) { /* Called from signal handlers, so needs to be async-signal-safe */ static const char buf[1] = ""; for (;;) { int r = write(fd, buf, 1); if (r==1) return 0; assert(r==-1); if (errno == EINTR) continue; if (errno == EWOULDBLOCK) return 0; if (!errno) abort(); return errno; } } int self_pipe_eatall(int fd) { char buf[256]; for (;;) { int r = read(fd, buf, sizeof(buf)); if (r == sizeof(buf)) continue; if (r >= 0) return 0; assert(r == -1); if (errno == EINTR) continue; if (errno == EWOULDBLOCK) return 0; assert(errno); return errno; } } int sigchld_selfpipe[2]; static void *sigchld_helper(void *fd) { struct pollfd pfd; int r; pfd.fd = (int)(unsigned long)fd; pfd.events = POLLIN | POLLHUP; while (true) { // Wait for a sigchld on [0] fprintf(stderr, "Waiting for self-pipe\n"); r = poll(&pfd, 1, -1); if (r < 0) { if (errno == EINTR) continue; perror("poll"); return NULL; } if (pfd.revents == POLLHUP) { fprintf(stderr, "Received POLLHUP, closing helper\n"); return NULL; } fprintf(stderr, "Self-pipe received, calling libxl_childproc_sigchld_occurred\n"); self_pipe_eatall(pfd.fd); libxl_childproc_sigchld_occurred(ctx); } return NULL; } static void sigchld_handler(int signo) { // Signal on pipe [1] fprintf(stderr, "SIGCHLD received, self-signaling\n"); self_pipe_wakeup(sigchld_selfpipe[1]); } void setup_sigchld(void) { struct sigaction ours, old; pthread_t t; int i, flags, r; // Get self-signal pipe if (pipe(sigchld_selfpipe) < 0) { perror("Failed to create a pipe"); exit(1); } r = pthread_create(&t, NULL, sigchld_helper, (void *)(unsigned long)sigchld_selfpipe[0]); if (r < 0) { perror("Creating helper thread"); exit(1); } // Make non-blocking for (i = 0; i < 2; i++) { int fd = sigchld_selfpipe[i]; flags = fcntl(fd, F_GETFL); if (flags == -1) { perror("Getting block flags"); exit(1); } flags |= O_NONBLOCK; r = fcntl(fd, F_SETFL, flags); if (flags == -1) { perror("Setting pipe non-blocking"); exit(1); } } memset(&ours,0,sizeof(ours)); ours.sa_handler = sigchld_handler; sigemptyset(&ours.sa_mask); ours.sa_flags = SA_NOCLDSTOP | SA_RESTART; r = sigaction(SIGCHLD, &ours, &old); assert(!r); } int main(int argc, char * argv[]) { int rc; xentoollog_logger_stdiostream * xtl; libxl_domain_config cconfig; uint32_t domid; bool mainloop = false; if (argc > 1) mainloop=true; if (mainloop) setup_sigchld(); xtl = xtl_createlogger_stdiostream(stderr, XTL_DEBUG, 0); rc = libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, (xentoollog_logger*)xtl); if (rc) { fprintf(stderr, "Getting libxl_ctx: %d", rc); exit(1); } if (mainloop) { libxl_childproc_hooks *cp = malloc(sizeof(*cp)); cp->chldowner = libxl_sigchld_owner_mainloop; libxl_childproc_setmode(ctx, cp, NULL); } libxl_domain_config_init(&cconfig); libxl_domain_build_info_init_type(&cconfig.b_info, LIBXL_DOMAIN_TYPE_PV); cconfig.c_info.type = LIBXL_DOMAIN_TYPE_PV; cconfig.c_info.name = malloc_copy("c6-01"); cconfig.b_info.max_vcpus = 4; cconfig.b_info.max_memkb = 2048*1024; cconfig.b_info.target_memkb = 2048*1024; cconfig.on_crash = LIBXL_ACTION_ON_SHUTDOWN_DESTROY; cconfig.b_info.bootloader = malloc_copy("pygrub"); cconfig.num_disks = 1; cconfig.disks = malloc(sizeof(libxl_device_disk)); libxl_device_disk_init(cconfig.disks); cconfig.disks[0].vdev = malloc_copy("hda"); cconfig.disks[0].format = LIBXL_DISK_FORMAT_RAW; cconfig.disks[0].pdev_path = malloc_copy("/images/c6-01.raw"); cconfig.disks[0].readwrite = 1; cconfig.num_nics = 1; cconfig.nics = malloc(sizeof(libxl_device_nic)); libxl_device_nic_init(cconfig.nics); rc = libxl_domain_create_new(ctx, &cconfig, &domid, NULL, NULL); if (rc) { fprintf(stderr, "Creating domain: %d", rc); exit(1); } printf("Created domain with id %d", domid); libxl_domain_config_dispose(&cconfig); if (mainloop) { close(sigchld_selfpipe[1]); close(sigchld_selfpipe[0]); } return 0; }