[PATCH 07/24] virCommandSetDryRun: Rework resetting of the dry run data

Peter Krempa pkrempa at redhat.com
Fri Apr 9 06:37:51 UTC 2021


On Wed, Apr 07, 2021 at 20:06:30 +0200, Pavel Hrdina wrote:
> On Wed, Apr 07, 2021 at 05:09:30PM +0200, Peter Krempa wrote:
> > While virCommandSetDryRun is used in tests only, there were some cases
> > when error paths would not call the function with NULL arguments to
> > reset the dry run infrastructure.
> > 
> > Introduce VIR_COMMAND_DRY_RUN_TOKEN macro which declares a variable
> > called 'dryRunToken' which must be passed to virCommandSetDryRun.
> > 
> > This way we can use automatic variable cleaning to trigger the cleanup
> > of virCommandSetDryRun parameters and also the use of the token variable
> > ensures that all callers of virCommandSetDryRun clean up after
> > themselves and also that VIR_COMMAND_DRY_RUN_TOKEN isn't left unused in
> > the code.
> > 
> > Signed-off-by: Peter Krempa <pkrempa at redhat.com>
> > ---
> >  src/libvirt_private.syms         |  1 +
> >  src/util/vircommand.c            | 13 ++++++++++-
> >  src/util/vircommandpriv.h        | 10 +++++++-
> >  tests/networkxml2firewalltest.c  |  4 ++--
> >  tests/nodedevmdevctltest.c       |  8 +++----
> >  tests/nwfilterebiptablestest.c   | 28 +++++++++++-----------
> >  tests/nwfilterxml2firewalltest.c |  4 ++--
> >  tests/sysinfotest.c              |  4 ++--
> >  tests/virfirewalltest.c          | 40 ++++++++++++++++----------------
> >  tests/viriscsitest.c             | 12 +++++-----
> >  tests/virkmodtest.c              |  8 +++----
> >  tests/virnetdevbandwidthtest.c   |  4 ++--
> >  12 files changed, 78 insertions(+), 58 deletions(-)
> > 
> > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> > index caa0fd18f8..e32088badb 100644
> > --- a/src/libvirt_private.syms
> > +++ b/src/libvirt_private.syms
> > @@ -1983,6 +1983,7 @@ virCommandAllowCap;
> >  virCommandClearCaps;
> >  virCommandDaemonize;
> >  virCommandDoAsyncIO;
> > +virCommandDryRunResetHelper;
> >  virCommandExec;
> >  virCommandFree;
> >  virCommandGetArgList;
> > diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> > index 8ae5badf0f..7b2588f5c8 100644
> > --- a/src/util/vircommand.c
> > +++ b/src/util/vircommand.c
> > @@ -3132,7 +3132,8 @@ virCommandDoAsyncIO(virCommandPtr cmd)
> >   * To cancel this effect pass NULL for @buf and @callback.
> >   */
> >  void
> > -virCommandSetDryRun(virBufferPtr buf,
> > +virCommandSetDryRun(virCommandDryRunToken tok G_GNUC_UNUSED,
> > +                    virBufferPtr buf,
> >                      virCommandDryRunCallback cb,
> >                      void *opaque)
> >  {
> > @@ -3141,6 +3142,16 @@ virCommandSetDryRun(virBufferPtr buf,
> >      dryRunOpaque = opaque;
> >  }
> > 
> > +
> > +void
> > +virCommandDryRunResetHelper(virCommandDryRunToken *tok G_GNUC_UNUSED)
> > +{
> > +    dryRunBuffer = NULL;
> > +    dryRunCallback = NULL;
> > +    dryRunOpaque = NULL;
> > +}
> > +
> > +
> >  #ifndef WIN32
> >  /**
> >   * virCommandRunRegex:
> > diff --git a/src/util/vircommandpriv.h b/src/util/vircommandpriv.h
> > index 80f1d1376c..8a47a6d5e3 100644
> > --- a/src/util/vircommandpriv.h
> > +++ b/src/util/vircommandpriv.h
> > @@ -35,6 +35,14 @@ typedef void (*virCommandDryRunCallback)(const char *const*args,
> >                                           int *status,
> >                                           void *opaque);
> > 
> > -void virCommandSetDryRun(virBufferPtr buf,
> > +typedef int virCommandDryRunToken;
> > +
> > +void virCommandSetDryRun(virCommandDryRunToken tok,
> > +                         virBufferPtr buf,
> >                           virCommandDryRunCallback cb,
> >                           void *opaque);
> > +
> > +void
> > +virCommandDryRunResetHelper(virCommandDryRunToken *tok);
> > +
> > +#define VIR_COMMAND_DRY_RUN_TOKEN __attribute__((cleanup(virCommandDryRunResetHelper))) virCommandDryRunToken dryRunToken = 0
> 
> How about using this instead:
> 
> G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virCommandDryRunToken, virCommandDryRunResetHelper);
> 
> > diff --git a/tests/networkxml2firewalltest.c b/tests/networkxml2firewalltest.c
> > index d358f12897..574b553fa6 100644
> > --- a/tests/networkxml2firewalltest.c
> > +++ b/tests/networkxml2firewalltest.c
> > @@ -96,8 +96,9 @@ static int testCompareXMLToArgvFiles(const char *xml,
> >      virNetworkDefPtr def = NULL;
> >      int ret = -1;
> >      char *actual;
> > +    VIR_COMMAND_DRY_RUN_TOKEN;
> 
> I don't like this at all, specifically the fact that it hides
> declaration of dryRunToken variable.
> 
> Here we could use this:
> 
>     g_auto(virCommandDryRunToken) dryRunToken = 0;
> 
> 
> This would be probably acceptable but I would still prefer if we could
> create a new struct, for example:
> 
> struct _virCommandDryData {
>     virBufferPtr buf;
>     virCommandDryRunCallback callback;
>     void *opaque;
> };
> 
> That way the struct would be used so clang will not complain about
> unused variable and there is no need for the dummy dryRunToken.

I didn't like the VIR_COMMAND_DRY_RUN_TOKEN either but I think the
semantics of usage with the token are good.

IMO a better solution which we could also possibly use instead of the
VIR_XPATH_CTXT_AUTORESTORE macro would be to create a function which
allocates the token (thus shifting responsibility of deallocating it to
the caller/programmer) and provide a autoptr cleanup function for it to
preserve the semantics we have.

While this adds an allocation, the declaration of the variable will be
cleaner.

P.S.: looks like this series had a few conflicts recently with test
changes so if you don't plan on continuing the review right away I'll be
posting another fixed version soon.




More information about the libvir-list mailing list