Subject: problem with spec_close() controlling tty hack
To: None <tech-kern@sun-lamp.cs.berkeley.edu>
From: Andrew Herbert <andrew@werple.apana.org.au>
List: tech-kern
Date: 02/10/1994 12:00:59
The hack introduced to spec_close() on 27 Jan '94 appears to sometimes
conflict with the controlling tty cleanup code in kexit(), in that under
certain circumstances it results in the session struct's s_ttyvp being
clobbered just before a vgoneall() is attempted on this vnode pointer. The
resultant vgoneall(NULL) panics the kernel.
I'm not entirely clear on the benefits of the spec_close() hack, but
assuming it is a Good Thing, below is the counter-hack I'm using in kexit().
A preferable alternate fix which I just thought of would be to test for
!(p->p_flag & SWEXIT) in spec_close() before doing the ttyvp hack. This
would then remove the need for kexit() to worry about pointers disappearing
from under its nose. Patch also below.
Comments?
Andrew
--
*** kern_exit.c.unhacked Wed Feb 9 14:26:16 1994
--- kern_exit.c Thu Feb 10 10:34:16 1994
***************
*** 152,157 ****
--- 152,162 ----
if (sp->s_ttyp->t_pgrp)
pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
(void) ttywait(sp->s_ttyp);
+ if (!sp->s_ttyvp) {
+ log(LOG_WARNING, "kexit(): s_ttyvp for dev(%d,%d) has disappeared!",
+ major(sp->s_ttyp->t_dev), minor(sp->s_ttyp->t_dev));
+ goto skip;
+ }
vgoneall(sp->s_ttyvp);
}
vrele(sp->s_ttyvp);
***************
*** 162,167 ****
--- 167,173 ----
* (for logging and informational purposes)
*/
}
+ skip:
sp->s_leader = NULL;
}
fixjobc(p, p->p_pgrp, 0);
Preferred spec_close() patch:
*** spec_vnops.c.unhacked Thu Feb 10 11:54:40 1994
--- spec_vnops.c Thu Feb 10 11:55:31 1994
***************
*** 460,466 ****
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
! if (vcount(vp) == 2 && p && vp == p->p_session->s_ttyvp) {
vrele(vp);
p->p_session->s_ttyvp = NULL;
}
--- 460,467 ----
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
! if (vcount(vp) == 2 && p && !(p->p_flag & SWEXIT) &&
! vp == p->p_session->s_ttyvp) {
vrele(vp);
p->p_session->s_ttyvp = NULL;
}
------------------------------------------------------------------------------