setenv() is not async-signal-safe and as such should not be used between fork/exec of a multi-threaded app: if one thread is manipulating the current environment (which may entail obtaining a malloc() mutex) when another thread calls fork(), the resulting child's attempt to use setenv() could deadlock or see a broken environ because the thread owning the lock no longer exists to release it. Besides, it is more efficient to update the environment exactly once in the parent, rather than after every fork().
While at it, check for (unlikely) failure of setenv. Signed-off-by: Eric Blake <[email protected]> --- plugins/sh/call.c | 3 --- plugins/sh/sh.c | 6 ++++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/sh/call.c b/plugins/sh/call.c index 871de5c6..9b8b48e2 100644 --- a/plugins/sh/call.c +++ b/plugins/sh/call.c @@ -127,9 +127,6 @@ call3 (const char *wbuf, size_t wbuflen, /* sent to stdin */ /* Restore SIGPIPE back to SIG_DFL, since shell can't undo SIG_IGN */ signal (SIGPIPE, SIG_DFL); - /* Set $tmpdir for the script. */ - setenv ("tmpdir", tmpdir, 1); - execvp (argv[0], (char **) argv); perror (argv[0]); _exit (EXIT_FAILURE); diff --git a/plugins/sh/sh.c b/plugins/sh/sh.c index 737c38cf..e3d3c2f1 100644 --- a/plugins/sh/sh.c +++ b/plugins/sh/sh.c @@ -60,6 +60,12 @@ sh_load (void) nbdkit_error ("mkdtemp: /tmp: %m"); exit (EXIT_FAILURE); } + /* Set $tmpdir for the script. */ + if (setenv ("tmpdir", tmpdir, 1) == -1) { + nbdkit_error ("setenv: tmpdir=%s: %m", tmpdir); + exit (EXIT_FAILURE); + } + nbdkit_debug ("sh: load: tmpdir: %s", tmpdir); } -- 2.20.1 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
