short read/write and error code

David Xu listlog2011 at gmail.com
Thu Aug 2 11:53:55 UTC 2012


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.

-------------- next part --------------
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


More information about the freebsd-arch mailing list