PERFORCE change 123818 for review
Peter Wemm
peter at FreeBSD.org
Fri Jul 20 18:59:17 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123818
Change 123818 by peter at peter_overcee on 2007/07/20 18:58:39
Fix guaranteed crash when ttys go away while a kevent is active.
Affected files ...
.. //depot/projects/hammer/sys/kern/tty.c#54 edit
Differences ...
==== //depot/projects/hammer/sys/kern/tty.c#54 (text+ko) ====
@@ -1319,6 +1319,8 @@
int s;
tp = tty_gettp(dev);
+ if (tp->t_state & TS_GONE)
+ return (ENODEV);
switch (kn->kn_filter) {
case EVFILT_READ:
@@ -1333,7 +1335,7 @@
return (EINVAL);
}
- kn->kn_hook = (caddr_t)dev;
+ kn->kn_hook = (caddr_t)tp;
s = spltty();
knlist_add(klist, kn, 0);
@@ -1345,7 +1347,7 @@
static void
filt_ttyrdetach(struct knote *kn)
{
- struct tty *tp = ((struct cdev *)kn->kn_hook)->si_tty;
+ struct tty *tp = (struct tty *)kn->kn_hook;
int s = spltty();
knlist_remove(&tp->t_rsel.si_note, kn, 0);
@@ -1355,10 +1357,10 @@
static int
filt_ttyread(struct knote *kn, long hint)
{
- struct tty *tp = ((struct cdev *)kn->kn_hook)->si_tty;
+ struct tty *tp = (struct tty *)kn->kn_hook;
kn->kn_data = ttnread(tp);
- if (ISSET(tp->t_state, TS_ZOMBIE)) {
+ if ((tp->t_state & TS_GONE) || ISSET(tp->t_state, TS_ZOMBIE)) {
kn->kn_flags |= EV_EOF;
return (1);
}
@@ -1368,7 +1370,7 @@
static void
filt_ttywdetach(struct knote *kn)
{
- struct tty *tp = ((struct cdev *)kn->kn_hook)->si_tty;
+ struct tty *tp = (struct tty *)kn->kn_hook;
int s = spltty();
knlist_remove(&tp->t_wsel.si_note, kn, 0);
@@ -1378,10 +1380,10 @@
static int
filt_ttywrite(struct knote *kn, long hint)
{
- struct tty *tp = ((struct cdev *)kn->kn_hook)->si_tty;
+ struct tty *tp = (struct tty *)kn->kn_hook;
kn->kn_data = tp->t_outq.c_cc;
- if (ISSET(tp->t_state, TS_ZOMBIE))
+ if ((tp->t_state & TS_GONE) || ISSET(tp->t_state, TS_ZOMBIE))
return (1);
return (kn->kn_data <= tp->t_olowat &&
ISSET(tp->t_state, TS_CONNECTED));
@@ -3015,11 +3017,19 @@
{
tp->t_state |= TS_GONE;
+ if (SEL_WAITING(&tp->t_rsel))
+ selwakeuppri(&tp->t_rsel, TTIPRI);
+ if (SEL_WAITING(&tp->t_wsel))
+ selwakeuppri(&tp->t_wsel, TTOPRI);
+ if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
+ pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
wakeup(&tp->t_dtr_wait);
wakeup(TSA_CARR_ON(tp));
wakeup(TSA_HUP_OR_INPUT(tp));
wakeup(TSA_OCOMPLETE(tp));
wakeup(TSA_OLOWAT(tp));
+ KNOTE_UNLOCKED(&tp->t_rsel.si_note, 0);
+ KNOTE_UNLOCKED(&tp->t_wsel.si_note, 0);
tt_purge(tp);
}
@@ -3040,6 +3050,7 @@
ttygone(tp);
unit = tp->t_devunit;
destroy_dev(tp->t_mdev);
+ ttyrel(tp); /* release refcount from ttyalloc() */
free_unr(tty_unit, unit);
}
More information about the p4-projects
mailing list