On 9/1/20 9:24 AM, Richard W.M. Jones wrote:
On Wed, Aug 26, 2020 at 09:16:48PM -0500, Eric Blake wrote:
Implementing .default_export with its 'const char *' return is tricky
in the sh plugin: we must return dynamic memory, but must avoid a
use-after-free.  And we don't want to change the return type of
.default_export to 'char *', because that would make our choice of
malloc()/free() part of the API, preventing either nbdkit or a plugin
from experimenting with an alternate allocator implementation.
Elsewhere, we have done things like nbdkit_extents_new(), so that even
though the client is directing allocation, the actual call to malloc()
is done by nbdkit proper, so that nbdkit later calling free() does not
tie the plugin's hands, and nbdkit could change its underlying
allocation without breaking ABI.  (Note that nbdkit_realpath() and
nbdkit_absolute_path() require the caller to use free(), but as they
are used during .config, it's less of a burden for plugins to take
care of that in .unload.)

We could document that the burden is on the plugin to avoid the memory
leak, by making sh track all strings it returns, then finally clean
them up during .unload.  But this is still a memory leak in the case
of .default_export, which can be called multiple times when there are
multiple clients, and presumably with different values per client
call; better would be freeing the memory at .close when each client
goes away.  Except that .default_export is called before .open, and
therefore before we have access to the handle struct that will
eventually make it to .close.

So, the solution is to let nbdkit track an alternate string on our
behalf, where nbdkit then cleans it up as the client goes away.

There are several places in the existing code base that can also take
advantage of this copying functionality, including in filters that
want to pass altered strings to .config while still obeying lifetime
rules.

We should probably just push this one straight away, with
one small change:

diff --git a/server/public.c b/server/public.c
index d10d466e..512e9caa 100644
--- a/server/public.c
+++ b/server/public.c

This file is probably going to need:

   #include "strndup.h"

somewhere near the top because unbelievably Win32 lacks this function.

Sounds good. I'm also finding that nbdkit_printf_intern(const char *fmt, ...) and nbdkit_vprintf_intern(const char *, va_list) are going to be useful, so I'll add those, get this in, then post a v3 of the rest of the series with further doc cleanups.

Another use for this new function (capturing the essence of an IRC discussion): we have several language plugins that mention that things like .config_help is not overrideable. The full set of struct plugin strings that would be nicer as functions:
.longname
.description
.config_help
.magic_config_key

(Maybe .name or .version as well, but I see less reason to want to make those dynamic)

Having a callback function that returns a const char * would let language bindings return a description or similar as set by the script; it would also allow us to alter the magic config key in a stateful manner according to what previous config keys have been parsed. So, for example, we could allow:

nbdkit python file.py myfile

as shorthand for

nbdkit python script=file.py file=myfile

by having file.py provide an overload for a new .get_magic_config_key() function.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org

_______________________________________________
Libguestfs mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libguestfs

Reply via email to