Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 02 Aug 2012 19:53:47 +0800
From:      David Xu <listlog2011@gmail.com>
To:        davidxu@freebsd.org
Cc:        Konstantin Belousov <kostikbel@gmail.com>, arch@freebsd.org
Subject:   Re: short read/write and error code
Message-ID:  <501A6A4B.8060209@gmail.com>
In-Reply-To: <501A69EB.9000701@gmail.com>
References:  <5018992C.8000207@freebsd.org> <20120801071934.GJ2676@deviant.kiev.zoral.com.ua> <20120801183240.K1291@besplex.bde.org> <20120801162836.GO2676@deviant.kiev.zoral.com.ua> <20120802040542.G2978@besplex.bde.org> <20120802100240.GV2676@deviant.kiev.zoral.com.ua> <501A69EB.9000701@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020705050204070000090402
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

On 2012/8/2 19:52, David Xu wrote:
> On 2012/8/2 18:02, Konstantin Belousov wrote:
>> diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
>> index 338256c..1a61b93 100644
>> --- a/sys/kern/sys_pipe.c
>> +++ b/sys/kern/sys_pipe.c
>> @@ -1286,13 +1286,13 @@ pipe_write(fp, uio, active_cred, flags, td)
>>       }
>>         /*
>> -     * Don't return EPIPE if I/O was successful
>> +     * Don't return EPIPE if any byte was written.
>> +     * EINTR and other interrupts are handled by generic I/O layer.
>> +     * Do not pretend that I/O succeeded for obvious user error
>> +     * like EFAULT.
>>        */
>> -    if ((wpipe->pipe_buffer.cnt == 0) &&
>> -        (uio->uio_resid == 0) &&
>> -        (error == EPIPE)) {
>> +    if (uio->uio_resid != orig_resid && error == EPIPE)
>>           error = 0;
>> -    }
>>         if (error == 0)
>>           vfs_timestamp(&wpipe->pipe_mtime);
>
> I dislike the patch, if I thought it is right, I would have already 
> submit such
> a patch. Now let us see why your patch is wore than my version 
> (attached):
> -current:
>     short write is done, some bytes were sent
>     dofilewrite returns -1, errno is EPIPE
>     dofilewrite sends SIGPIPE
>     application is killed by SIGPIPE
> -my attached version:
>    short write is done, some bytes were sent
>    dofilewrite return number of bytes sent, errno is zero
>    dofilewrite sends SIGPIPE.
>   application is killed by SIGPIPE
> -you version:
>   short write is done, some bytes were sent.
>   dofilewrite returns number of bytes sent,  errno is zero.
>   dofilewrite does not send SIGPIPE signal
>   application is not killed
>   application does not check return value from write()
>   application thinks it is successful, application does other things,
>   application might begin a bank account transaction.
>   ...
>   application never comes back...
>
> my patch is more compatible with -current. if application does not
> setup a signal handler for SIGPIPE, when short write happens, it is 
> killed,
> it is same as -current. if the application set up a signal handler for 
> the signal,
> it always should check the return value from write(), this is how 
> traditional
> code works.
>
> in your patch, short write does not kill application,  you can not assume
> that the application will request a next write() on the pipe, and you 
> hope
> the second write to kill the application, but there is always exception,
> the next write does not happen,  application works on other things.
> This is too incompatible with -current.
>
>
Oops, I forgot to attach it.


--------------020705050204070000090402
Content-Type: text/plain; charset=gb18030;
	name="sys_generic_short_pipe_write.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="sys_generic_short_pipe_write.diff"

Index: sys_generic.c
===================================================================
--- sys_generic.c	(revision 238927)
+++ sys_generic.c	(working copy)
@@ -539,15 +539,21 @@
 	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) {
+			if (error == ERESTART || error == EINTR ||
+			    error == EWOULDBLOCK)
+				error = 0;
+			else if (error == EPIPE && 
+				 (fp->f_type == DTYPE_PIPE ||
+			          fp->f_type == DTYPE_FIFO))
+				error = 0;
+		}
 	}
 	cnt -= auio->uio_resid;
 #ifdef KTRACE

--------------020705050204070000090402--



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