Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Apr 2002 04:00:04 -0800 (PST)
From:      Mark Kettenis <kettenis@chello.nl>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/35175: ptrace(PT_DETACH, ...) doesn't do signals as advertised
Message-ID:  <200204011200.g31C04804700@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/35175; it has been noted by GNATS.

From: Mark Kettenis <kettenis@chello.nl>
To: freebsd-gnats-submit@FreeBSD.org
Cc: peter.edwards@openet-telecom.com
Subject: Re: kern/35175: ptrace(PT_DETACH, ...) doesn't do signals as advertised
Date: Mon, 1 Apr 2002 13:52:14 +0200 (CEST)

 I can confirm that this is a real bug.  It's easy to reproduce this
 with GDB.  Simply attach to a process, and then immediately detach.
 The process will be suspended.  Even worse, if you let the process run
 under control of GDB before the detach, it'll almost certainly die
 with a Trace/BPT trap on detaching.  Didn't notice this before since
 the part of GDB's regression testsuite that tests the attach/detach
 functionality wasn't run on FreeBSD until recently.
 
 Anyway, I agree with Peter's analysis.  Some archaeology revealed that
 the bug was already present in the 4.4-lite sources and that it has
 been fixed in NetBSD and OpenBSD several years ago.  Attached is an
 alternative patch that bright the FreeBSD code more in line with
 OpenBSD (NetBSD has diverged quite a bit since the bug was fixed).
 The patch is against 4.4-RELEASE, but I think it should apply against
 -STABLE without too much problems.  Fixing -CURRENT along the same
 lines should be doable too.  I'm certainly willing to help out there.
 
 Would be great of someone could take a look at this...  As GDB FreeBSD
 maintainer I'd really like to see this bug go.
 
 Mark
 
 
 --- /usr/src/sys/kern/kern_sig.c.orig	Fri Jul 27 16:06:01 2001
 +++ /usr/src/sys/kern/kern_sig.c	Mon Apr  1 12:59:37 2002
 @@ -1230,7 +1230,7 @@ issignal(p)
  		if (!SIGNOTEMPTY(mask))	 	/* no signal to send */
  			return (0);
  		sig = sig_ffs(&mask);
 -		prop = sigprop(sig);
 +		SIGDELSET(p->p_siglist, sig);	/* take the signal! */
  
  		STOPEVENT(p, S_SIG, sig);
  
 @@ -1238,10 +1238,9 @@ issignal(p)
  		 * We should see pending but ignored signals
  		 * only if P_TRACED was on when they were posted.
  		 */
 -		if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0)) {
 -			SIGDELSET(p->p_siglist, sig);
 +		if (SIGISMEMBER(p->p_sigignore, sig) && (traced == 0))
  			continue;
 -		}
 +
  		if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
  			/*
  			 * If traced, always stop, and stay
 @@ -1256,32 +1255,24 @@ issignal(p)
  				 && p->p_flag & P_TRACED);
  
  			/*
 -			 * If the traced bit got turned off, go back up
 -			 * to the top to rescan signals.  This ensures
 -			 * that p_sig* and ps_sigact are consistent.
 +			 * If we are no longer being traced, or the parent
 +			 * didn't give us a signal, look for more signals.
  			 */
 -			if ((p->p_flag & P_TRACED) == 0)
 +			if ((p->p_flag & P_TRACED) == 0 || p->p_xstat == 0)
  				continue;
  
  			/*
 -			 * If parent wants us to take the signal,
 -			 * then it will leave it in p->p_xstat;
 -			 * otherwise we just look for signals again.
 +			 * If the new signal is being masked, look for other
 +			 * signals.
  			 */
 -			SIGDELSET(p->p_siglist, sig);	/* clear old signal */
  			sig = p->p_xstat;
 -			if (sig == 0)
 -				continue;
 -
 -			/*
 -			 * Put the new signal into p_siglist.  If the
 -			 * signal is being masked, look for other signals.
 -			 */
 -			SIGADDSET(p->p_siglist, sig);
  			if (SIGISMEMBER(p->p_sigmask, sig))
  				continue;
 +			SIGDELSET(p->p_siglist, sig);	/* take the signal! */
  		}
  
 +		prop = sigprop(sig);
 +
  		/*
  		 * Decide whether the signal should be returned.
  		 * Return the signal's number, or fall through
 @@ -1329,7 +1320,7 @@ issignal(p)
  				 */
  				break;		/* == ignore */
  			} else
 -				return (sig);
 +				goto keep;
  			/*NOTREACHED*/
  
  		case (int)SIG_IGN:
 @@ -1348,11 +1339,14 @@ issignal(p)
  			 * This signal has an action, let
  			 * postsig() process it.
  			 */
 -			return (sig);
 +			goto keep;
  		}
 -		SIGDELSET(p->p_siglist, sig);		/* take the signal! */
  	}
  	/* NOTREACHED */
 +
 +keep:
 +	SIGADDSET(p->p_siglist, sig);	/* leave the signal for later */
 +	return (sig);
  }
  
  /*

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200204011200.g31C04804700>