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:
parent
24980f6902
commit
18c0643bfb
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user