svn commit: r294778 - in head: lib/libc/sys sys/kern

Kubilay Kocak koobs at FreeBSD.org
Tue Jan 26 09:10:39 UTC 2016


On 26/01/2016 6:57 PM, Konstantin Belousov wrote:
> Author: kib
> Date: Tue Jan 26 07:57:44 2016
> New Revision: 294778
> URL: https://svnweb.freebsd.org/changeset/base/294778
> 
> Log:
>   Restore flushing of output for revoke(2) again.  Document revoke()'s
>   intended behaviour in its man page.  Simplify tty_drain() to match.
>   Don't call ttydevsw methods in tty_flush() if the device is gone
>   since we now sometimes call it then.
>   
>   The flushing was supposed to be implemented by passing the FNONBLOCK
>   flag to VOP_CLOSE() for revoke().  The tty driver is one of the few
>   that can block in close and was one of the fewer that knew about this.
>   
>   This almost worked in FreeBSD-1 and similarly in Net/2.  These
>   versions only almost worked because there was and is considerable
>   confusion between IO_NDELAY and FNONBLOCK (aka O_NONBLOCK).  IO_NDELAY
>   is only valid for VOP_READ() and VOP_WRITE().  For other VOPs it has
>   the same value as O_SHLOCK.  But since vfs_subr.c and tty.c
>   consistently used the wrong flag and the O_SHLOCK flag is rarely set,
>   this mostly worked.  It also gave the feature than applications could
>   get the non-blocking close by abusing O_SHLOCK.
>   
>   This was first broken then fixed in 1995.  I changed only the tty
>   driver to use FNONBLOCK, as a hack to get non-blocking via the normal
>   flag FNONBLOCK for last closes.  I didn't know about revoke()'s use
>   of IO_NDELAY or change it to be consistent, so revoke() was broken.
>   Then I changed revoke() to match.

Seems like

>   This was next broken in 1997 then fixed in 1998.  Importing Lite2 made
>   the flags inconsistent again by undoing the fix only in vfs_subr.c.

A fantastic

>   This was next broken in 2008 by replacing everything in tty.c and not
>   checking any flags in last close.  Other bugs in draining limited the
>   resulting unbounded waits to drain in some cases.

Regression test candidate :)

>   It is now possible to fix this better using the new FREVOKE flag.
>   Just restore flushing for revoke() for now.  Don't restore or undo any
>   hacks for ordinary last closes yet.  But remove dead code in the
>   1-second relative timeout (r272789).  This did extra work to extend
>   the buggy draining for revoke() for as long as possible.  The 1-second
>   timeout made this not very long by usually flushing after 1 second.
>   
>   Submitted by:	bde
>   MFC after:	2 weeks
> 
> Modified:
>   head/lib/libc/sys/revoke.2
>   head/sys/kern/tty.c
> 
> Modified: head/lib/libc/sys/revoke.2
> ==============================================================================
> --- head/lib/libc/sys/revoke.2	Tue Jan 26 07:49:11 2016	(r294777)
> +++ head/lib/libc/sys/revoke.2	Tue Jan 26 07:57:44 2016	(r294778)
> @@ -31,7 +31,7 @@
>  .\"     @(#)revoke.2	8.1 (Berkeley) 6/4/93
>  .\" $FreeBSD$
>  .\"
> -.Dd June 4, 1993
> +.Dd Jan 25, 2016
>  .Dt REVOKE 2
>  .Os
>  .Sh NAME
> @@ -59,7 +59,8 @@ and a
>  system call will succeed.
>  If the file is a special file for a device which is open,
>  the device close function
> -is called as if all open references to the file had been closed.
> +is called as if all open references to the file had been closed
> +using a special close method which does not block.
>  .Pp
>  Access to a file may be revoked only by its owner or the super user.
>  The
> @@ -104,3 +105,6 @@ The
>  .Fn revoke
>  system call first appeared in
>  .Bx 4.3 Reno .
> +.Sh BUGS
> +The non-blocking close method is only correctly implemented for
> +terminal devices.
> 
> Modified: head/sys/kern/tty.c
> ==============================================================================
> --- head/sys/kern/tty.c	Tue Jan 26 07:49:11 2016	(r294777)
> +++ head/sys/kern/tty.c	Tue Jan 26 07:57:44 2016	(r294778)
> @@ -126,7 +126,7 @@ static int
>  tty_drain(struct tty *tp, int leaving)
>  {
>  	size_t bytesused;
> -	int error, revokecnt;
> +	int error;
>  
>  	if (ttyhook_hashook(tp, getc_inject))
>  		/* buffer is inaccessible */
> @@ -141,18 +141,10 @@ tty_drain(struct tty *tp, int leaving)
>  
>  		/* Wait for data to be drained. */
>  		if (leaving) {
> -			revokecnt = tp->t_revokecnt;
>  			error = tty_timedwait(tp, &tp->t_outwait, hz);
> -			switch (error) {
> -			case ERESTART:
> -				if (revokecnt != tp->t_revokecnt)
> -					error = 0;
> -				break;
> -			case EWOULDBLOCK:
> -				if (ttyoutq_bytesused(&tp->t_outq) < bytesused)
> -					error = 0;
> -				break;
> -			}
> +			if (error == EWOULDBLOCK &&
> +			    ttyoutq_bytesused(&tp->t_outq) < bytesused)
> +				error = 0;
>  		} else
>  			error = tty_wait(tp, &tp->t_outwait);
>  
> @@ -356,6 +348,10 @@ ttydev_close(struct cdev *dev, int fflag
>  		return (0);
>  	}
>  
> +	/* If revoking, flush output now to avoid draining it later. */
> +	if (fflag & FREVOKE)
> +		tty_flush(tp, FWRITE);
> +
>  	/*
>  	 * This can only be called once. The callin and the callout
>  	 * devices cannot be opened at the same time.
> @@ -1460,13 +1456,16 @@ tty_flush(struct tty *tp, int flags)
>  		tp->t_flags &= ~TF_HIWAT_OUT;
>  		ttyoutq_flush(&tp->t_outq);
>  		tty_wakeup(tp, FWRITE);
> -		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE);
> +		if (!tty_gone(tp))
> +			ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE);
>  	}
>  	if (flags & FREAD) {
>  		tty_hiwat_in_unblock(tp);
>  		ttyinq_flush(&tp->t_inq);
> -		ttydevsw_inwakeup(tp);
> -		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD);
> +		if (!tty_gone(tp)) {
> +			ttydevsw_inwakeup(tp);
> +			ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD);
> +		}
>  	}
>  }
>  



More information about the svn-src-all mailing list