kern/73821: poll(2) returns POLLIN / POLLOUT on TS_ZOMBIE ttys

Diomidis Spinellis dds at aueb.gr
Thu Nov 11 07:20:19 PST 2004


>Number:         73821
>Category:       kern
>Synopsis:       poll(2) returns POLLIN / POLLOUT on TS_ZOMBIE ttys
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 11 15:20:18 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Diomidis Spinellis
>Release:        FreeBSD 4.10-STABLE i386
>Organization:
AUEB
>Environment:
System: FreeBSD istlab.dmst.aueb.gr 4.10-STABLE FreeBSD 4.10-STABLE #23: Fri Oct 8 15:53:45 EEST 2004 dds at istlab.dmst.aueb.gr:/usr/obj/usr/src/sys/ISTLAB i386

>Description:
When a tty line toggles its DCD it enters the TS_ZOMBIE state.  In
that state input and output are not possible.  Yet poll(2) will
return POLLIN / POLLOUT in that state - even if no I/O is possible.

Example:

$ pstat -t
  LINE RAW CAN OUT IHIWT ILOWT OHWT LWT     COL STATE  SESS      PGID DISC
  cuaa0 22   0   0 11520 10080 4104 256    7274 OlZ           0     0 term

$ strace -p 8539
poll([{fd=4, events=POLLIN|POLLRDNORM|POLLERR, revents=POLLIN|POLLRDNORM}], 1, 0) = 1
read(4, "", 1024)                       = 0

In the above example /dev/cuaa0 is in the TS_ZOMBIE state (Z).  Poll(2) returns
POLLIN, yet read(2) returns 0.

>How-To-Repeat:
Probably by toggling the DCD line of a device read by a program using
poll(2).
>Fix:
Modify tty's poll(2) interface to return POLLERR for TS_ZOMBIE ttys.
POLLERR is defined as:
    An error has occurred on the device or stream.

Can not return POLLHUP because according to POSIX 1003.1 (2004):
POLLHUP
    The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.


The following patch implements the proposed change:
Index: tty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty.c,v
retrieving revision 1.240
diff -u -r1.240 tty.c
--- tty.c	3 Nov 2004 19:16:55 -0000	1.240
+++ tty.c	11 Nov 2004 14:55:25 -0000
@@ -1283,19 +1283,20 @@
 
 	s = spltty();
 	if (events & (POLLIN | POLLRDNORM)) {
-		if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
+		if (ttnread(tp) > 0)
 			revents |= events & (POLLIN | POLLRDNORM);
 		else
 			selrecord(td, &tp->t_rsel);
 	}
 	if (events & (POLLOUT | POLLWRNORM)) {
-		if ((tp->t_outq.c_cc <= tp->t_olowat &&
-		     ISSET(tp->t_state, TS_CONNECTED))
-		    || ISSET(tp->t_state, TS_ZOMBIE))
+		if (tp->t_outq.c_cc <= tp->t_olowat &&
+		    ISSET(tp->t_state, TS_CONNECTED))
 			revents |= events & (POLLOUT | POLLWRNORM);
 		else
 			selrecord(td, &tp->t_wsel);
 	}
+	if (ISSET(tp->t_state, TS_ZOMBIE))
+		revents |= POLLERR;
 	splx(s);
 	return (revents);
 }
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list