Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jul 2001 18:44:17 +0300
From:      Ruslan Ermilov <ru@FreeBSD.ORG>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        current@FreeBSD.ORG
Subject:   Re: TIOCSCTTY
Message-ID:  <20010703184417.A69095@sunbay.com>
In-Reply-To: <Pine.BSF.4.21.0107032328020.41126-100000@besplex.bde.org>; from bde@zeta.org.au on Wed, Jul 04, 2001 at 01:15:17AM %2B1000
References:  <20010703152523.C39090@sunbay.com> <Pine.BSF.4.21.0107032328020.41126-100000@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Jul 04, 2001 at 01:15:17AM +1000, Bruce Evans wrote:
> On Tue, 3 Jul 2001, Ruslan Ermilov wrote:
> 
> > Weird.  I figured out what causes this, it's moused(8).  I have inserted
> > some debug code into it to see what's going on:
> > ...
> >   LINE RAW CAN OUT IHIWT ILOWT OHWT LWT     COL STATE  SESS      PGID DISC
> >   cuaa1  0   0   0   512   448  216  60       0 OCcl          0     0 term
> > consolectl  0   0   0   512   448 1296 256      98 OCc    c0b14700     6 term
> >       0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyp0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyv0  0   0   0   512   448 1296 256       0 -             0     0 term
> > 
> > As you can see, process 6 (sh /etc/rc autoboot) is the session leader with
> > /dev/console as the controlling terminal, and the same session is referenced
> > from the `tty' structure for the consolectl device.
> 
> The bug seems to be caused by a combination of sloppy code in moused,
> dubious aliasing in syscons and a known bug in cnclose():
> 1. moused opens /dev/consolectl before becoming a daemon.  This shouldn't
>    be a problem, since /dev/consolectl should be a completely different device
>    from the controlling terminal (which is /dev/console, although you can't
>    really see that from the ps output since "consolectl" is a poorly chosen
>    name which is indistinguishable from "console" after ps truncates it to
>    3 characters).  However:
> 
But my "emulation" program opens /dev/consolectl _after_ becoming a daemon.
And yes, I can distinguish "console" from "consolectl" with ``-O tty''.

> 2. syscons.c makes /dev/consolectl a sort of alias for /dev/consolectl:
> 
>     dev = make_dev(&sc_cdevsw, SC_CONSOLECTL,
> 		   UID_ROOT, GID_WHEEL, 0600, "consolectl");
>     dev->si_tty = sc_console_tty = ttymalloc(sc_console_tty);
> 
>    This obviously breaks the pstat output and complicates debugging (pstat
>    should display "console" instead of "consolectl").  It apparently also
>    breaks last-close stuff when /dev/console is closed.
> 3. cnclose() already has broken handling of controlling terminals when
>    /dev/console is last-closed while the physical device underlying the
>    console is open and /dev/console is a controlling terminal.
>    /dev/consolectl is different from the physical device underlying
>    /dev/console (even if the latter is /dev/ttyv0), and is not understood
>    by cnclose(), but I think the same problem and fix apply.
> 
> > Next, this is after moused(8) calls daemon(3):
> > 
> > USER     PID  PPID  PGID   SESS JOBC STAT  TT       TIME COMMAND
> > ...
> > root     221     1   221 bf8280    0 Ss    ??    0:00.00 moused -3 -p /dev/cuaa1 -t auto
> > root     223   221   221 bf8280    0 S     ??    0:00.00 sh -c (ps axjww; pstat -t) >>/1
> > root     225   223   221 bf8280    0 S     ??    0:00.00 sh -c (ps axjww; pstat -t) >>/1
> > root     227   225   221 bf8280    0 R     ??    0:00.00 ps axjww
> > root       6     1     6 b14700    0 Ss+  con    0:00.14 sh /etc/rc autoboot
> > root     228     6     6 b14700    0 R+   con    0:00.00 sh /etc/rc autoboot
> 
> No problem here.
> 
I did not mean there is.  :-)

> >   LINE RAW CAN OUT IHIWT ILOWT OHWT LWT     COL STATE  SESS      PGID DISC
> >   cuaa1  0   0   0   512   448  216  60       0 OCcl          0     0 term
> > consolectl  0   0   0   512   448 1296 256     109 OCc    c0b14700     6 term
> >       0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyp0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyv0  0   0   0   512   448 1296 256       0 -             0     0 term
> > 
> > Nothing has changed re: consolectl.  It still has session c0b14700 (with
> > the session leader PID = 6) bound to it.
> 
> Nothing should have changed, since moused only closed a dup'ed descriptor
> for /dev/console.
> 
Sure, this is normal.

> The last-close bugs will bite later when ancestors of
> moused all close all their descriptors for /dev/console.
> Here we can still see the consolectl vs console confusion.
> 
How this applies to my "emulation" program, which opens
/dev/consolectl only when in a new session?

> > Next, this is the output after the system has booted into multi-user:
> > ...
> > The session c0b14700 has disappeared from the ps(1) output, but it is still
> > referenced from the `tty' structure:
> > 
> >   LINE RAW CAN OUT IHIWT ILOWT OHWT LWT     COL STATE  SESS      PGID DISC
> >   ttyvb  0   0   0   512   448 1296 256       0 -             0     0 term
> >   ttyva  0   0   0   512   448 2052 256       7 OCc    c0c02c80   263 term
> >   ttyv9  0   0   0   512   448 2052 256       7 OCc    c0c02d40   262 term
> >   ttyv8  0   0   0   512   448 2052 256       7 OCc    c0c02e00   261 term
> >   ttyv7  0   0   0   512   448 2052 256       7 OCc    c0c02800   260 term
> >   ttyv6  0   0   0   512   448 2052 256       7 OCc    c0c028c0   259 term
> >   ttyv5  0   0   0   512   448 2052 256       7 OCc    c0c02900   258 term
> >   ttyv4  0   0   0   512   448 2052 256       7 OCc    c0c02940   257 term
> >   ttyv3  0   0   0   512   448 2052 256       7 OCc    c0c02980   256 term
> >   ttyv2  0   0   0   512   448 2052 256       7 OCc    c0c02a40   255 term
> >   ttyv1  0   0   0   512   448 2052 256       0 OCc    c0c02b00   279 term
> >   cuaa1  0   0   0   512   448  216  60       0 OCcl          0     0 term
> > consolectl  0   0   0   512   448 1296 256       0 OCc    c0b14700     0 term
> >       0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyp0  0   0   0     0     0    0   0       0 -             0     0 term
> >   ttyv0  0   0   0   512   448 2052 256       7 OCc    c0c02bc0   253 term
> 
> Hmm.  ttyv0 apparently doesn't share a tty struct with consolectl/console.
> I'm familiar with this feature from old versions of syscons but thought that
> it was lost.  This used to prevent bug (3) for syscons (it always affected
> sio and maybe pcvt), but we now have it via the consolectl alias.
> 
> I wonder if the bogus line of zeros is related to miscounting the single
> tty struct for console/consolectl as two structs.
> 
> > What I can't understand is how opening a /dev/consolectl in a new session
> > doesn't allow the t_session tty pointer to be reset that points to another
> > (not existing) session.
> > 
> > (This is probably somehow relates to the fact that the device's close()
> > routine is called only on a last reference drop, but I'm not sure.)
> 
> I think I understand the details now:
> - on i386's, sccnprobe() sets the physical device for /dev/console to
>   /dev/consolectl.  Thus /dev/consolectl is more than "sort of" an
>   alias for /dev/console, and bug (3) bites.  I don't understand the
>   minor detail that pstat prefers the "consolectl" alias.
> - on alphas, sccnattach() sets the physical device for /dev/console to
>   /dev/ttyv0.  Thus the bugs are gratuitously different.
> 
> I use the following fix for (3).  This is not suitable for committing,
> due to probable races clearing the state.  E.g., p_session can apparently
> change before d_close() returns, so my closing_ctty flag may become
> invalid, but since there is no explicit locking it's not clear that
> other fatal changes can't happen.  Hopefully everything is protected
> by Giant until d_close() blocks, but the code after d_close() blocks
> isn't very careful about the state.  It needs to be, because d_open()
> can be called successfully while d_close() is blocked!  Note that
> d_close() can block for arbitrarily long waiting for output to drain,
> and it is useful for d_open() to succeed while d_close() is busy,
> if only to unblock the close by changing the drain wait time.
> 
I will try this patch tomorrow and see if it works.


Cheers,
-- 
Ruslan Ermilov		Oracle Developer/DBA,
ru@sunbay.com		Sunbay Software AG,
ru@FreeBSD.org		FreeBSD committer,
+380.652.512.251	Simferopol, Ukraine

http://www.FreeBSD.org	The Power To Serve
http://www.oracle.com	Enabling The Information Age

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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