At 05/30/2012 09:17 PM, Eric Blake Wrote:
On 05/30/2012 03:20 AM, Wen Congyang wrote:
> fdstream:
> If fd is fds[0] or fds[1], we should set to -1 if we meet
> some error.
>
> childfd is fds[0] or fds[1], so we should close it only when
> virFDStreamOpenFileInternal() successes.
>
> qemu_migration:
> If we migrate to fd, spec->fwdType is not MIGRATION_FWD_DIRECT,
> we will close spec->dest.fd.local in qemuMigrationRun(). So we
> should set spec->dest.fd.local to -1 in qemuMigrationRun().
>
> command:
> we should not set *outfd or *errfd if virExecWithHook() failed
> because the caller may close these fds.
We should split this into three separate patches, to aid backporting
each patch across appropriate versions. Needs a v2 for this reason; as
I want these bugs fixed sooner rather than later, I'll probably help by
reposting things myself.
>
> ---
> src/fdstream.c | 15 ++++++++++-----
> src/qemu/qemu_migration.c | 4 +++-
> src/util/command.c | 8 ++++----
> 3 files changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/src/fdstream.c b/src/fdstream.c
> index 32d386d..d0ea0ee 100644
> --- a/src/fdstream.c
> +++ b/src/fdstream.c
> @@ -581,6 +581,7 @@ virFDStreamOpenFileInternal(virStreamPtr st,
> struct stat sb;
> virCommandPtr cmd = NULL;
> int errfd = -1;
> + int childfd = -1;
>
> VIR_DEBUG("st=%p path=%s oflags=%x offset=%llu length=%llu mode=%o",
> st, path, oflags, offset, length, mode);
> @@ -619,7 +620,6 @@ virFDStreamOpenFileInternal(virStreamPtr st,
> if ((st->flags & VIR_STREAM_NONBLOCK) &&
> (!S_ISCHR(sb.st_mode) &&
> !S_ISFIFO(sb.st_mode))) {
> - int childfd;
>
> if ((oflags & O_ACCMODE) == O_RDWR) {
> streamsReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -652,15 +652,20 @@ virFDStreamOpenFileInternal(virStreamPtr st,
> }
> virCommandSetErrorFD(cmd, &errfd);
>
> - if (virCommandRunAsync(cmd, NULL) < 0)
> + if (virCommandRunAsync(cmd, NULL) < 0) {
> + /* donot close fd twice if we meet some error */
s/donot/don't/
> + fd = -1;
> goto error;
> -
> - VIR_FORCE_CLOSE(childfd);
> + }
> }
>
> - if (virFDStreamOpenInternal(st, fd, cmd, errfd, length) < 0)
> + if (virFDStreamOpenInternal(st, fd, cmd, errfd, length) < 0) {
> + /* donot close fd twice if we meet some error */
and again.
> + fd = -1;
> goto error;
> + }
>
> + VIR_FORCE_CLOSE(childfd);
> return 0;
Doesn't this leak childfd on error?
No, childfd is fds[0] or fds[1]. We have closed fds[0] and fds[1] on error,
so we should not close childfd on error.
Maybe a better solution here would be that when we assign fd and childfd
to elements of fds[], then we also assign fds to -1, as in:
Good idea.
Thanks
Wen Congyang
diff --git i/src/fdstream.c w/src/fdstream.c
index 32d386d..b797a05 100644
--- i/src/fdstream.c
+++ w/src/fdstream.c
@@ -581,6 +581,7 @@ virFDStreamOpenFileInternal(virStreamPtr st,
struct stat sb;
virCommandPtr cmd = NULL;
int errfd = -1;
+ int childfd = -1;
VIR_DEBUG("st=%p path=%s oflags=%x offset=%llu length=%llu mode=%o",
st, path, oflags, offset, length, mode);
@@ -619,7 +620,6 @@ virFDStreamOpenFileInternal(virStreamPtr st,
if ((st->flags & VIR_STREAM_NONBLOCK) &&
(!S_ISCHR(sb.st_mode) &&
!S_ISFIFO(sb.st_mode))) {
- int childfd;
if ((oflags & O_ACCMODE) == O_RDWR) {
streamsReportError(VIR_ERR_INTERNAL_ERROR,
@@ -650,6 +650,7 @@ virFDStreamOpenFileInternal(virStreamPtr st,
fd = fds[1];
virCommandSetInputFD(cmd, childfd);
}
+ fds[0] = fds[1] = -1;
virCommandSetErrorFD(cmd, &errfd);
if (virCommandRunAsync(cmd, NULL) < 0)
@@ -668,6 +669,7 @@ error:
VIR_FORCE_CLOSE(fds[0]);
VIR_FORCE_CLOSE(fds[1]);
VIR_FORCE_CLOSE(fd);
+ VIR_FORCE_CLOSE(childfd);
if (oflags & O_CREAT)
unlink(path);
return -1;
> +++ b/src/qemu/qemu_migration.c
> @@ -1910,8 +1910,10 @@ qemuMigrationRun(struct qemud_driver *driver,
> break;
>
> case MIGRATION_DEST_FD:
> - if (spec->fwdType != MIGRATION_FWD_DIRECT)
> + if (spec->fwdType != MIGRATION_FWD_DIRECT) {
> fd = spec->dest.fd.local;
> + spec->dest.fd.local = -1;
> + }
> ret = qemuMonitorMigrateToFd(priv->mon, migrate_flags,
> spec->dest.fd.qemu);
> VIR_FORCE_CLOSE(spec->dest.fd.qemu);
This hunk is probably okay on its own.
> diff --git a/src/util/command.c b/src/util/command.c
> index eaa9f16..2723fde 100644
> --- a/src/util/command.c
> +++ b/src/util/command.c
> @@ -493,6 +493,10 @@ virExecWithHook(const char *const*argv,
> }
>
> if (pid) { /* parent */
> + if (forkRet < 0) {
> + goto cleanup;
> + }
> +
> VIR_FORCE_CLOSE(null);
> if (outfd && *outfd == -1) {
> VIR_FORCE_CLOSE(pipeout[1]);
> @@ -503,10 +507,6 @@ virExecWithHook(const char *const*argv,
> *errfd = pipeerr[0];
> }
>
> - if (forkRet < 0) {
> - goto cleanup;
> - }
> -
> *retpid = pid;
>
> if (binary != argv[0])
And this one is probably okay as well (I'll have to spend more time
reading it); again a reason for splitting these into independent patches.