Change 548124 by willa@willa_repo on 2012/06/22 12:10:33 Fix a panic in userspace dtrace. The bug here is that the proc lock is already held in the case of fasttrap_fork(), which then calls proc_ops(), which tries to hold it again. Upon inspection, every other consumer of proc_ops() has already placed a hold and then dropped the proc lock. Change fasttrap_fork() to match these semantics, which also happen to mirror Solaris. Change proc_ops() to assert that the proc object is held and unlocked, rather than executing a hold/rele cycle itself. Note: fasttrap_fork() is only ever called if an userspace program being dtrace'd happens to fork(). So this bug doesn't apply if you are dtrace'ing a userspace process that doesn't fork. Also, at least for ztest, userspace dtrace is still unusable because when the child process exits, both dtrace and ztest appear to spin forever. The dtrace process doesn't appear to do anything; the ztest process can't be attached via gdb since it's already being ptrace()'d by dtrace. This will require more investigation to fix. Index: cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c =================================================================== --- cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c (revision 248803) +++ cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c (working copy) @@ -74,12 +74,10 @@ uio.uio_segflg = UIO_SYSSPACE; uio.uio_td = curthread; uio.uio_rw = op; - PHOLD(p); - if (proc_rwmem(p, &uio) < 0) { - PRELE(p); + PROC_ASSERT_HELD(p); + PROC_LOCK_ASSERT((p), MA_NOTOWNED); + if (proc_rwmem(p, &uio) < 0) return (-1); - } - PRELE(p); return (0); } Index: cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c =================================================================== --- cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c (revision 248803) +++ cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c (working copy) @@ -498,6 +498,7 @@ mtx_unlock_spin(&cp->p_slock); #else _PHOLD(cp); + PROC_UNLOCK(cp); #endif /* @@ -532,6 +533,7 @@ mutex_enter(&cp->p_lock); sprunlock(cp); #else + PROC_LOCK(cp); _PRELE(cp); #endif }