paulfloyd / freebsd_valgrind

Git repo used to Upstream the FreeBSD Port of Valgrind
GNU General Public License v2.0
15 stars 4 forks source link

Implement rfork #197

Open paulfloyd opened 1 year ago

paulfloyd commented 1 year ago

I'm sure that I've run konsole and trace children in the past and don't remember seeing this.

Nonetheless I just noticed with ksh93 I get

paulf> ./vg-in-place ksh93
==1509== Memcheck, a memory error detector
==1509== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==1509== Using Valgrind-3.21.0.GIT and LibVEX; rerun with -h for copyright info
==1509== Command: ksh93
==1509== 
euler:/usr/home/paulf/scratch/valgrind
paulf> ==1509== rfork() not implemented
==1509== Valgrind detected that your program requires
==1509== the following unimplemented functionality:
==1509==    Valgrind does not support rfork().
==1509== This may be because the functionality is hard to implement,
==1509== or because no reasonable program would behave this way,
==1509== or because nobody has yet needed it.  In any case, let us know at
==1509== www.valgrind.org and/or try to work around the problem, if you can.
==1509== 
==1509== Valgrind has to exit now.  Sorry.  Bye!
==1509== 

posix_spawn contains

#ifdef _RFORK_THREAD_STACK_SIZE
    /*
     * x86 stores the return address on the stack, so rfork(2) cannot work
     * as-is because the child would clobber the return address om the
     * parent.  Because of this, we must use rfork_thread instead while
     * almost every other arch stores the return address in a register.
     */
    p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa);
    free(stack);
#else
    p = rfork(RFSPAWN);
    if (p == 0)
        /* _posix_spawn_thr does not return */
        _posix_spawn_thr(&psa);
#endif
    /*
     * The above block should leave us in a state where we've either
     * succeeded and we're ready to process the results, or we need to
     * fallback to vfork() if the kernel didn't like RFSPAWN.
     */

    if (p == -1 && errno == EINVAL) {
        p = vfork();
        if (p == 0)
            /* _posix_spawn_thr does not return */
            _posix_spawn_thr(&psa);
    }

So at least it would be better to fail the syscall.

Man page says

     If RFSPAWN is passed, rfork will use vfork(2) semantics but reset all
     signal actions in the child to default.  This flag is used by the
     posix_spawn(3) implementation in libc.
paulfloyd commented 1 year ago

As a partial workaround I've changed it to not terminate and either return EINVAL (pretend that we don't support RFSPAWN) or ENOSYS