getppid blindly follows the parent pointer and reads the pid. The problem is that ptrace reparents the traced process, so in particular if you gdb -p $something, the target proc will start seeing gdb instead of its actual parent.
There is a lot to say about the entire reparenting business or storing the original pid in ps_oppid (instead of some form of a reference to the process). However, I think the most feasible fix for now is the same thing FreeBSD did: *always* store the actual parent pid in ps_oppid. This means all repareting will keep updating it (most notably when abandoning children on exit), while ptrace will skip that part. Side effect of such a change be that getppid will stop requiring the kernel lock. -- Mateusz Guzik <mjguzik gmail.com>