>From c48ba672cd92d1d173fe9cb93f8e268d0d7952bc Mon Sep 17 00:00:00 2001 From: Charles Duffy Date: Fri, 28 Aug 2009 22:17:47 -0500 Subject: [PATCH 1/2] stop using popen for outgoing migrations --- migration-exec.c | 95 ++++++++++++++++++++++++++++++++++++----------------- qemu-common.h | 2 + 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index b45c833..c36e756 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -31,25 +31,72 @@ do { } while (0) #endif -static int file_errno(FdMigrationState *s) +// opaque is pid +typedef struct ExecMigrationState +{ + pid_t pid; +} ExecMigrationState; + +static int exec_errno(FdMigrationState *s) { return errno; } -static int file_write(FdMigrationState *s, const void * buf, size_t size) +static int exec_write(FdMigrationState *s, const void * buf, size_t size) { return write(s->fd, buf, size); } static int exec_close(FdMigrationState *s) { + int ret, status; + dprintf("exec_close\n"); - if (s->opaque) { - qemu_fclose(s->opaque); - s->opaque = NULL; - s->fd = -1; + + close(s->fd); + + if (!(s->opaque)) + return -1; + + do { + ret = waitpid(((ExecMigrationState*)(s->opaque))->pid, &status, 0); + } while (ret == -1 && errno == EINTR); + + qemu_free(s->opaque); + s->opaque = 0; + + return status; +} + +static pid_t exec_start_migration(const char *command, int *fd) { + const char *argv[] = { "sh", "-c", command, NULL }; + int fds[2]; + pid_t pid; + + if (pipe(fds) == -1) { + dprintf("pipe() (%s)\n", strerr(errno)); + return 0; } - return 0; + + pid = fork(); + if(pid == -1) { + close(fds[0]); + close(fds[1]); + dprintf("fork error (%s)\n", strerror(errno)); + return 0; + } else if (pid == 0) { + /* child process */ + close(fds[1]); + dup2(fds[0], STDIN_FILENO); + execv("/bin/sh", (char **)argv); + exit(1); + } + close(fds[0]); + + fcntl(fds[1], O_NONBLOCK); + + *fd = fds[1]; + return pid; } MigrationState *exec_start_outgoing_migration(const char *command, @@ -57,29 +104,20 @@ MigrationState *exec_start_outgoing_migration(const char *command, int detach) { FdMigrationState *s; - FILE *f; + int fd, pid; - s = qemu_mallocz(sizeof(*s)); + pid = exec_start_migration(command, &fd); + if(!pid) return NULL; - f = popen(command, "w"); - if (f == NULL) { - dprintf("Unable to popen exec target\n"); - goto err_after_alloc; - } - - s->fd = fileno(f); - if (s->fd == -1) { - dprintf("Unable to retrieve file descriptor for popen'd handle\n"); - goto err_after_open; - } - - socket_set_nonblock(s->fd); + s = qemu_mallocz(sizeof(*s)); + s->opaque = qemu_mallocz(sizeof(ExecMigrationState)); - s->opaque = qemu_popen(f, "w"); + ((ExecMigrationState*)(s->opaque))->pid = pid; + s->fd = fd; + s->get_error = exec_errno; + s->write = exec_write; s->close = exec_close; - s->get_error = file_errno; - s->write = file_write; s->mig_state.cancel = migrate_fd_cancel; s->mig_state.get_status = migrate_fd_get_status; s->mig_state.release = migrate_fd_release; @@ -93,14 +131,9 @@ MigrationState *exec_start_outgoing_migration(const char *command, migrate_fd_connect(s); return &s->mig_state; - -err_after_open: - pclose(f); -err_after_alloc: - qemu_free(s); - return NULL; } +/* helper for incoming case */ static void exec_accept_incoming_migration(void *opaque) { QEMUFile *f = opaque; diff --git a/qemu-common.h b/qemu-common.h index c8fb315..aeb1d78 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "config-host.h" #ifndef O_LARGEFILE -- 1.6.4