On Mon, Feb 20, 2023 at 07:21:05PM +0100, Laszlo Ersek wrote:
> On 2/15/23 21:57, Eric Blake wrote:
> > On Wed, Feb 15, 2023 at 03:11:36PM +0100, Laszlo Ersek wrote:
> >> Add an assert() variant that we may call between fork() and exec*().
> >>
> >> Signed-off-by: Laszlo Ersek <ler...@redhat.com>
> >> ---
> >>
> > 
> >> +++ b/lib/internal.h
> > 
> >> +
> >> +#ifdef NDEBUG
> >> +#define NBD_INTERNAL_FORK_SAFE_ASSERT(expression) ((void)0)
> > 
> > May be affected by outcome of side discussion on 01/29 about whether
> > we want space after cast.
> > 
> >> +#else
> >> +#define NBD_INTERNAL_FORK_SAFE_ASSERT(expression)                        \
> >> +  (nbd_internal_fork_safe_assert ((expression) != 0, __FILE__, __LINE__, \
> >> +                                  __func__, #expression))
> >> +#endif
> >> +
> >>  #endif /* LIBNBD_INTERNAL_H */
> > 
> >> +++ b/lib/utils.c
> >> @@ -431,13 +431,35 @@ nbd_internal_socketpair (int domain, int type, int 
> >> protocol, int *fds)
> >>    if (ret == 0) {
> >>      for (i = 0; i < 2; i++) {
> >>        if (fcntl (fds[i], F_SETFD, FD_CLOEXEC) == -1) {
> >>          close (fds[0]);
> >>          close (fds[1]);
> >>          return -1;
> >>        }
> >>      }
> >>    }
> >>  #endif
> >>  
> >>    return ret;
> >>  }
> >> +
> >> +void
> >> +nbd_internal_fork_safe_assert (int result, const char *file, long line,
> >> +                               const char *func, const char *assertion)
> >> +{
> >> +  const char *line_out;
> >> +  char line_buf[32];
> >> +
> >> +  if (result)
> >> +    return;
> > 
> > Since no code should ever directly call
> > nbd_internal_fork_safe_assert(0,...), but instead go through our macro
> > that has already filtered on expression's value,
> 
> I either don't understand, or I disagree. With NDEBUG not defined, the
> NBD_INTERNAL_FORK_SAFE_ASSERT macro is always expanded to a call to
> nbd_internal_fork_safe_assert(). And the expression to check is
> evaluated in the first argument of that function call:
> 
> nbd_internal_fork_safe_assert ((expression) != 0, ...
> 
> So I think the early return is definitely necessary here.

Oh, I was confused.  I went back and re-read your macro; I guess I was
thinking it was something like:

do if (!(expression)) nbd_internal_fork_safe_assert (args); while (0)

where the function is only called on failure, but you instead wrote it
as:

nbd_internal_fork_safe_assert ((expression) != 0), args)

So I stand corrected - we do need the early exit here, because we are
unconditionally calling the function (when assertions are enabled) at
least in the current spelling of the macro.

...
> 
> > At any rate, your
> > implementation looks reasonable, and more to the point, satisfies your
> > desire of being async-signal-safe and thus appropriate between fork()
> > and exec().
> > 
> > Reviewed-by: Eric Blake <ebl...@redhat.com>
> > 
> 
> Thanks!

My R-b still stands, and I think you cleared up my confusion without
having to change any code on your part.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to