Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Sep 2000 13:28:03 -0400 (EDT)
From:      Bosko Milekic <bmilekic@technokratis.com>
To:        Alfred Perlstein <bright@wintelcom.net>
Cc:        arch@FreeBSD.ORG, cp@FreeBSD.ORG
Subject:   Re: need advice, fsetown annoyances and mpsafeness.
Message-ID:  <Pine.BSF.4.21.0009251314260.15801-100000@jehovah.technokratis.com>
In-Reply-To: <20000924125311.Q9141@fw.wintelcom.net>

next in thread | previous in thread | raw e-mail | index | archive | help

On Sun, 24 Sep 2000, Alfred Perlstein wrote:

> It's really a lot more evil than you think.

	Yeah, I noticed after sending the Email.

> The race is in the object (socket/tty) checking the pointer and
> then dereferencing it.
> 
> A broken solution is to lock the sigio struct or provide a backreference
> to the socket/tty lock, after banging my head against my desk for some time I came across this solution:

	This looks somewhat like what you mentionned in (2) in your earlier
  post. The sigio struct will only be freed by the object. I think this is
  a reasonable solution.

> (assuming pfind/pgfind return the proc/pgrp locked)
> 
[...]
> 	/*
> 	 * ok this is somewhat tricky, we examine what the sigio is attached
> 	 * to, whatever it is proc/pgrp we need to use the search functions
> 	 * to ensure atomicity.  If we get back ESRCH that's ok, that means
> 	 * we lost the race, just free it.
> 	 * if we get back a pointer we then need to make sure that the pgid
> 	 * hasn't been NULLed out because we lost the race between looking
> 	 * at the sigio and locking the proc/pgrp
> 	 * (most likely pid/pgid wraparound)
> 	 */
> 	pid = sigio->sio_pgid;
> 
> 	if (pid < 0) {
> 		struct pgrp *p;
> 
> 		if ((pgrp = pgfind(pid)) != NULL) {
> 			/* funsetown_proc would have set this to zero */
> 			if (sigio->sio_pgid != 0)
> 				SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,
> 					sigio, sio_pgsigio);
> 			PGRP_UNLOCK(&sigio->sio_pgrp);
> 		}
> 	} else if (pid > 0) {
> 		struct proc *p;
> 
> 		if ((p = pfind(pid)) != NULL) {
> 			/* funsetown_proc would have set this to zero */
> 			if (sigio->sio_pgid != 0)
> 				SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,
> 					sigio, sio_pgsigio);
> 			PROC_UNLOCK(&sigio->sio_proc);
> 		}
> 	}
> 
> out:
> 	crfree(sigio->sio_ucred);
> 	FREE(sigio, M_SIGIO);
> }

	Looks good.

> /*
>  * NULL out a sigio struct attached to a process/pgrp
>  * must be called with the object (struct proc/pgrp) locked
>  * this is to be called from the perspective of the process/pgrp
>  *
>  * called from the proc/pgid at teardown
>  * proc/pgid must be locked
>  */
> void
> funsetown_proc(sigio)
> 	struct sigio *sigio;
> {
> 	int s;
> 
> 	if (sigio == NULL)
> 		return;
> 	if (sigio->sio_pgid < 0) {
> 		SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,
> 			     sigio, sio_pgsigio);
> 	} else /* if ((*sigiop)->sio_pgid > 0) */ {
> 		SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,
> 			     sigio, sio_pgsigio);
> 	}
> 	sigio->sio_pgid = 0;
> }
> 
> /*
>  * Free a list of sigio structures.
>  *
>  * called from the proc/pgid at teardown
>  * proc/pgid must be locked
>  */
> void
> funsetownlst(sigiolst)
> 	struct sigiolst *sigiolst;
> {
> 	struct sigio *sigio;
> 
> 	while ((sigio = SLIST_FIRST(sigiolst)) != NULL)
> 		funsetown(sigio);
> }
> 
> 
> Questions?  Comments?

	Question: You don't seem to be protecting the actual sigiolst list
  with a lock. What happens if you've got two different processes
  manipulating the list? Each one may be locked, but regardless, your list
  can still be trashed.

> -- 
> -Alfred Perlstein - [bright@wintelcom.net|alfred@freebsd.org]
> "I have the heart of a child; I keep it in a jar on my desk."

  Regards,

  Bosko Milekic
  bmilekic@technokratis.com




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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0009251314260.15801-100000>