Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 May 1997 04:54:40 +0200
From:      Tor Egge <Tor.Egge@idi.ntnu.no>
To:        Tor.Egge@idi.ntnu.no
Cc:        freebsd-bugs@hub.freebsd.org
Subject:   Re: kern/3581: trap 12 in lockstatus()
Message-ID:  <199705240254.EAA17882@pat.idt.unit.no>
In-Reply-To: Your message of "Fri, 23 May 1997 10:10:01 -0700 (PDT)"
References:  <199705231710.KAA02145@hub.freebsd.org>

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

Some more info:

 skarven:~$ ps axl -M /var/crash/vmcore.1  | grep 28620
 28620  9144 151711   0 -14  0   972    0 vn_loc DEs   p0-   0:00.00  (bash)
 28620  9159 151711 257  28  0   384    0 -      Z     p0-   0:00.00  (desclient-

Here the vnode for /dev/ttyp0 had two references, one from the
controlling tty, and one from the system file table.

process 9144 and 9159 got SIGHUP and started to exit. Since process
9144 was the session leader, it called vop_revoke which called vgone
which called vclean.  When vclean was called, vp->v_usecount was
2. vclean increased vp->usecount to 3. Then vclean blocked in
vinvalbuf (in order to read inodes from disks, to update time stamps).

Process 9159 then continued to close its file descriptors, reducing
the reference counts in the system file table to 0 for the
stdin/stdout/stderr entry which referenced the vnode for
/dev/ttyp0. Thus vn_close was called, and v_usecount was reduced from
3 to 2. Process 9159 then became a zombie.

Then process 9144 continued, called VOP_CLOSE, and a special hack
removed the controlling terminal and reduced v_usecount from 2 to 1.
When vrele was called, v_usecount became 0, and vn_lock was called
with a deadlock as a result.

Suggested Fix:

  First part:

    Don't enable the special `close controlling terminal hack' if
    cleaning of the vnode is in progress.

  Second part:

    Release references to the vnode for the controlling terminal when
    the session structure is freed. This should take care of any
    dangling references introduced by the first part.


--------
Index: spec_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/specfs/spec_vnops.c,v
retrieving revision 1.39
diff -c -r1.39 spec_vnops.c
*** spec_vnops.c	1997/05/01 19:12:22	1.39
--- spec_vnops.c	1997/05/24 00:39:29
***************
*** 595,600 ****
--- 595,601 ----
  		 * plus the session), release the reference from the session.
  		 */
  		if (vcount(vp) == 2 && ap->a_p &&
+ 		    (vp->v_flag & VXLOCK) == 0 &&
  		    vp == ap->a_p->p_session->s_ttyvp) {
  			vrele(vp);
  			ap->a_p->p_session->s_ttyvp = NULL;
Index: kern_proc.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_proc.c,v
retrieving revision 1.26
diff -u -r1.26 kern_proc.c
--- kern_proc.c	1997/03/24 11:24:36	1.26
+++ kern_proc.c	1997/05/24 02:03:59
@@ -56,6 +56,7 @@
 #include <vm/pmap.h>
 #include <vm/vm_map.h>
 #include <sys/user.h>
+#include <sys/vnode.h>
 
 struct prochd qs[NQS];		/* as good a place as any... */
 struct prochd rtqs[NQS];	/* Space for REALTIME queues too */
@@ -285,12 +286,21 @@
 	register struct pgrp *pgrp;
 {
 
-	if (pgrp->pg_session->s_ttyp != NULL &&
-	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
-		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
+	struct session *sp;
+
+	sp = pgrp->pg_session;
+
+	if (sp->s_ttyp != NULL &&
+	    sp->s_ttyp->t_pgrp == pgrp)
+		sp->s_ttyp->t_pgrp = NULL;
 	LIST_REMOVE(pgrp, pg_hash);
-	if (--pgrp->pg_session->s_count == 0)
-		FREE(pgrp->pg_session, M_SESSION);
+	if (--sp->s_count == 0) {
+		if (sp->s_ttyvp)
+			VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
+		if (sp->s_ttyvp)
+			vrele(sp->s_ttyvp);
+		FREE(sp, M_SESSION);
+	}
 	FREE(pgrp, M_PGRP);
 }
 
---------




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