sendto: don't clear transient errors for atomic protocols

The changeset 65572cade3 uncovered the fact that top layer of sendto(2)
would clear a transient error code if some data was copied out of uio.
The clearing of the error makes sense for non-atomic protocols, since
they have sent some data.  The atomic protocols send all or nothing.

The current implementation of unix/dgram uses sosend_generic(), which
would always copyout and only then it may fail to deliver a message.
The sosend_dgram(), currently used by UDP only, also has same behavior.

Reported by:		pho
Reviewed by:		pho, markj
Differential revision:	https://reviews.freebsd.org/D34309
This commit is contained in:
Gleb Smirnoff 2022-02-17 09:07:31 -08:00
parent e0ac9dc2b0
commit d2b3a0ed31

View File

@ -785,8 +785,10 @@ kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
len = auio.uio_resid;
error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
if (error != 0) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
if (auio.uio_resid != len &&
(so->so_proto->pr_flags & PR_ATOMIC) == 0 &&
(error == ERESTART || error == EINTR ||
error == EWOULDBLOCK))
error = 0;
/* Generation of SIGPIPE can be controlled per socket */
if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&