Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Jul 2012 21:11:37 -0700
From:      Alfred Perlstein <alfred@freebsd.org>
To:        David Xu <davidxu@freebsd.org>
Cc:        arch@freebsd.org
Subject:   Re: short read/write and error code
Message-ID:  <20120801041137.GA56944@elvis.mu.org>
In-Reply-To: <5018992C.8000207@freebsd.org>
References:  <5018992C.8000207@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is cool, is there a test case that you can run
on Linux/Solaris to compare expected vs actual
behavior?

* David Xu <davidxu@freebsd.org> [120731 19:49] wrote:
> POSIX requires write() to return actually bytes written, same rule is
> applied to read().
> 
> http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html
> >ETURN VALUE
> >
> >Upon successful completion, write() [XSI]   and pwrite()  shall
> > return the number of bytes actually written to the file associated
> >with fildes. This number shall never be greater than nbyte.
> > Otherwise, -1 shall be returned and errno set to indicate the error.
> 
> 
> http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html
> >RETURN VALUE
> >
> >Upon successful completion, read() [XSI]   and pread()  shall return
> > a non-negative integer indicating the number of bytes actually read.
> > Otherwise, the functions shall return -1 and set errno to indicate
> > the error.
> 
> I have following patch to fix our code to be compatible with POSIX:
> 
> Index: sys_generic.c
> ===================================================================
> --- sys_generic.c	(revision 238927)
> +++ sys_generic.c	(working copy)
> @@ -333,8 +333,7 @@
>  #endif
>  	cnt = auio->uio_resid;
>  	if ((error = fo_read(fp, auio, td->td_ucred, flags, td))) {
> -		if (auio->uio_resid != cnt && (error == ERESTART ||
> -		    error == EINTR || error == EWOULDBLOCK))
> +		if (auio->uio_resid != cnt)
>  			error = 0;
>  	}
>  	cnt -= auio->uio_resid;
> @@ -539,15 +538,14 @@
>  	if (fp->f_type == DTYPE_VNODE)
>  		bwillwrite();
>  	if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) {
> -		if (auio->uio_resid != cnt && (error == ERESTART ||
> -		    error == EINTR || error == EWOULDBLOCK))
> -			error = 0;
>  		/* Socket layer is responsible for issuing SIGPIPE. */
>  		if (fp->f_type != DTYPE_SOCKET && error == EPIPE) {
>  			PROC_LOCK(td->td_proc);
>  			tdsignal(td, SIGPIPE);
>  			PROC_UNLOCK(td->td_proc);
>  		}
> +		if (auio->uio_resid != cnt)
> +			error = 0;
>  	}
>  	cnt -= auio->uio_resid;
>  #ifdef KTRACE
> 
> 
> -current only resets error code to zero for short write when code is
> ERESTART, EINTR or EWOULDBLOCK.
> But this is incorrect, at least for pipe, when EPIPE is returned,
> some bytes may have already been written. For a named pipe, I may don't
> care a reader is disappeared or not, because for named pipe, a new
> reader can come in and talk with writer again,  so I need to know
> how many bytes have been written, same is applied to reader, I don't
> care writer is gone, it can come in again and talk with reader. So I
> suggest to remove surplus code in -current's dofilewrite() and
> dofileread().
> For EPIPE, We still deliver SIGPIPE to current thread, but returns
> actually bytes written.
> 
> Regards,
> David Xu
> _______________________________________________
> freebsd-arch@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"

-- 
- Alfred Perlstein
.- VMOA #5191, 03 vmax, 92 gs500, 85 ch250, 07 zx10
.- FreeBSD committer



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