[libvirt] [PATCH 08/10] Introduce new APIs for spawning processes

Daniel P. Berrange berrange at redhat.com
Thu Nov 18 09:55:38 UTC 2010


On Wed, Nov 17, 2010 at 09:29:00PM -0700, Eric Blake wrote:
> From: Daniel P. Berrange <berrange at redhat.com>
> 
> This introduces a new set of APIs in src/util/command.h
> to use for invoking commands. This is intended to replace
> all current usage of virRun and virExec variants, with a
> more flexible and less error prone API.
> 
> * src/util/command.c: New file.
> * src/util/command.h: New header.
> * src/Makefile.am (UTIL_SOURCES): Build it.
> * src/libvirt_private.syms: Export symbols internally.
> * tests/commandtest.c: New test.
> * tests/Makefile.am (check_PROGRAMS): Run it.
> * tests/commandhelper.c: Auxiliary program.
> * tests/commanddata/test2.log - test15.log: New expected outputs.
> * cfg.mk (useless_free_options): Add virCommandFree.
> * po/POTFILES.in: New translation.
> * .x-sc_avoid_write: Add exemption.
> * tests/.gitignore: Ignore new built file.


> +struct _virCommand {
> +    int has_error; /* ENOMEM on allocation failure, -1 for anything else.  */
> +
> +    char **args;
> +    size_t nargs;
> +    size_t maxargs;
> +
> +    char **env;
> +    size_t nenv;
> +    size_t maxenv;
> +
> +    char *pwd;
> +
> +    /* XXX Use int[] if we ever need to support more than FD_SETSIZE fd's.  */
> +    fd_set preserve;
> +    unsigned int flags;
> +
> +    char *inbuf;
> +    char **outbuf;
> +    char **errbuf;
> +
> +    int infd;
> +    int inpipe;
> +    int outfd;
> +    int errfd;
> +    int *outfdptr;
> +    int *errfdptr;
> +
> +    virExecHook hook;
> +    void *opaque;
> +
> +    pid_t pid;
> +    char *pidfile;
> +};
> +/*
> + * Release all resources
> + */
> +void
> +virCommandFree(virCommandPtr cmd)
> +{
> +    int i;
> +    if (!cmd)
> +        return;
> +
> +    VIR_FORCE_CLOSE(cmd->outfd);
> +    VIR_FORCE_CLOSE(cmd->errfd);
> +
> +    for (i = 0 ; i < cmd->nargs ; i++)
> +        VIR_FREE(cmd->args[i]);
> +    VIR_FREE(cmd->args);
> +
> +    for (i = 0 ; i < cmd->nenv ; i++)
> +        VIR_FREE(cmd->env[i]);
> +    VIR_FREE(cmd->env);
> +
> +    VIR_FREE(cmd->pwd);
> +
> +    VIR_FREE(cmd->pidfile);
> +
> +    VIR_FREE(cmd);
> +}


My code forgot to ever close() the fds in cmd->preserve. We definitely
need todo it in virCommandFree(), but there's a small argument to say
we should also do it in virCommandRun/virCommandRunAsync so that if
the caller keeps the virCommandPtr alive for a long time, we don't
have the open FDs.

It would also be useful to have a generic API for logging info about
the command to an FD (to let us remove that logging code from UML
and QEMU & LXC drivers).

eg

+void virCommandWriteArgLog(virCommandPtr cmd, int logfd)
+{
+    int ioError = 0;
+    int i;
+
+    for (i = 0 ; i < cmd->nenv ; i++) {
+        if (safewrite(logfd, cmd->env[i], strlen(cmd->env[i])) < 0)
+            ioError = errno;
+        if (safewrite(logfd, " ", 1) < 0)
+            ioError  = errno;
+    }
+    for (i = 0 ; i < cmd->nargs ; i++) {
+        if (safewrite(logfd, cmd->args[i], strlen(cmd->args[i])) < 0)
+            ioError = errno;
+        if (safewrite(logfd, " ", 1) < 0)
+            ioError  = errno;
+    }
+
+    if (ioError) {
+        char ebuf[1024];
+        VIR_WARN("Unable to write command %s args to logfile: %s",
+                 cmd->args[0], virStrerror(ioError, ebuf, sizeof ebuf));
+    }
+}


Regards,
Daniel
-- 
|: Red Hat, Engineering, London    -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org        -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list