Update the uio resid counts appropriately when any error occurs

(not just EPIPE), so that the higher-level code would note partial
write has happened and DTRT if the write was interrupted due to
e.g. delivery of signal.

This fixes kern/14087 by Frank van der Linden.
Much thanks to Frank for extensive help with debugging this, and review
of the fix.

Note: EPIPE/SIGPIPE delivery behaviour was retained - they're delivered
even if the write was partially successful.
This commit is contained in:
jdolecek 2001-09-29 13:48:11 +00:00
parent 24980f6902
commit 18c0643bfb

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_pipe.c,v 1.14 2001/09/25 19:01:21 jdolecek Exp $ */
/* $NetBSD: sys_pipe.c,v 1.15 2001/09/29 13:48:11 jdolecek Exp $ */
/*
* Copyright (c) 1996 John S. Dyson
@ -1086,23 +1086,22 @@ retry:
pipe_loan_free(wpipe);
pipeunlock(wpipe);
if (error == EPIPE) {
if (error) {
pipeselwakeup(wpipe, wpipe);
/*
* If anything was read from what we offered, return success
* and short write. We return EOF on next write(2).
* If nothing was read from what we offered, return error
* streight on. Otherwise update uio resid first. Caller
* will deal with the error condition, returning short
* write, error, or restarting the write(2) as appropriate.
*/
if (wpipe->pipe_map.cnt < bcnt) {
bcnt -= wpipe->pipe_map.cnt;
error = 0;
}
}
if (error) {
if (wpipe->pipe_map.cnt == bcnt) {
error:
wakeup(wpipe);
return (error);
wakeup(wpipe);
return (error);
}
bcnt -= wpipe->pipe_map.cnt;
}
uio->uio_resid -= bcnt;
@ -1114,7 +1113,7 @@ retry:
uio->uio_iovcnt--;
}
return (0);
return (error);
}
#endif /* !PIPE_NODIRECT */
#endif /* NetBSD */