Subject: problem with TIOCSCTTY & SIGIO
To: None <netbsd-bugs@sun-lamp.cs.berkeley.edu>
From: Brad Parker <brad@fcr.com>
List: netbsd-bugs
Date: 11/16/1993 07:04:59
I'm having a problem and need advice; I have an application which
wants to get SIGIO from a /dev/ttyxx serial port.  In order to do this
it needs to make the /dev/comX device the controlling terminal.

Why?  because F_SETOWN degenerates into TIOCSPGRP in the kernel and
TIOCSPGRP requires that the terminal be the controlling terminal.
(as it turns out, TIOCSCTTY sets the process group anyway)

Anyway, TIOCSCTTY has the side effect of bumping the usecount on the
serial port's vnode, so once you set it controlling, you can't close
the serial port.

this is a problem for me as I *want* to close the serial port even
when the proc (which has forked and is now a daemon) is still running.

the code in vfs_vnnops.c:
        case VCHR:
        case VBLK:
                error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
                if (error == 0 && com == TIOCSCTTY) {
                        p->p_session->s_ttyvp = vp;
                        VREF(vp);
                }
                return (error);

which sets the session's controlling terminal.  Since the code in
kexit() only checks s_ttyvp if the proc is a session leader, I
wondered if this code should do the same (but, the code in tty.c
checks and will error if the proc is not, so that check would be less
obscure but redundant)

I dont know - is bumping the ref count here really necessary? I guess
it is, as it keept the s_ttyvp from pointing into space if you manage
to close the controlling terminal.

I guess I want a "unset controlling terminal" ioctl; unfortunetly,
TIOCNOTTY is not strong enought for this purpose.

Actually, what would happen if TIOCNOTTY zerod p->p_session->s_ttyp
and dropped the use count by 1?

like so:

cttyioctl(dev, cmd, addr, flag, p)
        dev_t dev;
        int cmd;
        caddr_t addr;
        int flag;
        struct proc *p;
{
        struct vnode *ttyvp = cttyvp(p);

        if (ttyvp == NULL)
                return (EIO);
        if (cmd == TIOCNOTTY) {
                if (!SESS_LEADER(p)) {
                        p->p_flag &= ~SCTTY;
>>>			vrele(p->p_session->s_ttyvp);
>>>			p->p_session->s_ttyvp = NULL;
                        return (0);
                } else
                        return (EINVAL);
        }

-brad

------------------------------------------------------------------------------