The fasttrap fork handler is responsible for removing tracepoints in the

child process that were inherited from its parent. However, this should
not be done in the case of a vfork, since the fork handler ends up removing
the tracepoints from the shared vm space, and userland DTrace probes in the
parent will no longer fire as a result.

Now the child of a vfork may trigger userland DTrace probes enabled in its
parent, so modify the fasttrap probe handler to handle this case and handle
the child process in the same way that it would handle the traced process.
In particular, if once traces function foo() in a process that vforks, and
the child calls foo(), fasttrap will treat this call as having come from the
parent. This is the behaviour of the upstream code.

While here, add #ifdef guards to some code that isn't present upstream.

MFC after:	1 month
This commit is contained in:
Mark Johnston 2013-12-18 01:41:52 +00:00
parent fdc3c84b5b
commit 7159310fa6
2 changed files with 29 additions and 14 deletions

View File

@ -1001,6 +1001,9 @@ int
fasttrap_pid_probe(struct reg *rp)
{
proc_t *p = curproc;
#if !defined(sun)
proc_t *pp;
#endif
uintptr_t pc = rp->r_rip - 1;
uintptr_t new_pc = 0;
fasttrap_bucket_t *bucket;
@ -1036,24 +1039,32 @@ fasttrap_pid_probe(struct reg *rp)
curthread->t_dtrace_regv = 0;
#endif
#if defined(sun)
/*
* Treat a child created by a call to vfork(2) as if it were its
* parent. We know that there's only one thread of control in such a
* process: this one.
*/
#if defined(sun)
while (p->p_flag & SVFORK) {
p = p->p_parent;
}
#endif
pid = p->p_pid;
pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
mutex_enter(pid_mtx);
#else
pp = p;
sx_slock(&proctree_lock);
while (pp->p_vmspace == pp->p_pptr->p_vmspace)
pp = pp->p_pptr;
pid = pp->p_pid;
sx_sunlock(&proctree_lock);
pp = NULL;
PROC_LOCK(p);
_PHOLD(p);
pid = p->p_pid;
#if defined(sun)
pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
mutex_enter(pid_mtx);
#endif
bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
/*
@ -1073,9 +1084,10 @@ fasttrap_pid_probe(struct reg *rp)
if (tp == NULL) {
#if defined(sun)
mutex_exit(pid_mtx);
#endif
#else
_PRELE(p);
PROC_UNLOCK(p);
#endif
return (-1);
}
@ -1197,9 +1209,10 @@ fasttrap_pid_probe(struct reg *rp)
* tracepoint again later if we need to light up any return probes.
*/
tp_local = *tp;
PROC_UNLOCK(p);
#if defined(sun)
mutex_exit(pid_mtx);
#else
PROC_UNLOCK(p);
#endif
tp = &tp_local;
@ -1749,7 +1762,7 @@ fasttrap_pid_probe(struct reg *rp)
#if defined(sun)
if (fasttrap_copyout(scratch, (char *)addr, i)) {
#else
if (uwrite(curproc, scratch, i, addr)) {
if (uwrite(p, scratch, i, addr)) {
#endif
fasttrap_sigtrap(p, curthread, pc);
new_pc = pc;
@ -1808,10 +1821,12 @@ fasttrap_pid_probe(struct reg *rp)
rp->r_rip = new_pc;
#if !defined(sun)
PROC_LOCK(p);
proc_write_regs(curthread, rp);
_PRELE(p);
PROC_UNLOCK(p);
#endif
return (0);
}

View File

@ -676,12 +676,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
#ifdef KDTRACE_HOOKS
/*
* Tell the DTrace fasttrap provider about the new process
* if it has registered an interest. We have to do this only after
* p_state is PRS_NORMAL since the fasttrap module will use pfind()
* later on.
* Tell the DTrace fasttrap provider about the new process so that any
* tracepoints inherited from the parent can be removed. We have to do
* this only after p_state is PRS_NORMAL since the fasttrap module will
* use pfind() later on.
*/
if (dtrace_fasttrap_fork)
if ((flags & RFMEM) == 0 && dtrace_fasttrap_fork)
dtrace_fasttrap_fork(p1, p2);
#endif
if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED |