Page MenuHomeFreeBSD

D35863.id114149.diff
No OneTemporary

D35863.id114149.diff

diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -562,12 +562,16 @@
ktruio = cloneuio(auio);
#endif
cnt = auio->uio_resid;
- if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) {
+ error = fo_write(fp, auio, td->td_ucred, flags, td);
+ /*
+ * Socket layer is responsible for special error handling,
+ * see sousrsend().
+ */
+ if (error != 0 && fp->f_type != DTYPE_SOCKET) {
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) {
+ if (error == EPIPE) {
PROC_LOCK(td->td_proc);
tdsignal(td, SIGPIPE);
PROC_UNLOCK(td->td_proc);
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -145,13 +145,7 @@
if (error)
return (error);
#endif
- error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td);
- if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) {
- PROC_LOCK(uio->uio_td->td_proc);
- tdsignal(uio->uio_td, SIGPIPE);
- PROC_UNLOCK(uio->uio_td->td_proc);
- }
- return (error);
+ return (sousrsend(so, NULL, uio, NULL, 0, NULL));
}
static int
@@ -646,15 +640,10 @@
error = mac_socket_check_send(fp->f_cred, so);
if (error == 0)
#endif
- error = sosend(so, NULL, job->uiop, NULL, NULL, flags,
- td);
+ error = sousrsend(so, NULL, job->uiop, NULL, flags,
+ job->userproc);
if (td->td_ru.ru_msgsnd != ru_before)
job->msgsnd = 1;
- if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) {
- PROC_LOCK(job->userproc);
- kern_psignal(job->userproc, SIGPIPE);
- PROC_UNLOCK(job->userproc);
- }
}
done += cnt - job->uiop->uio_resid;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1822,6 +1822,14 @@
return (error);
}
+/*
+ * Send to a socket from a kernel thread.
+ *
+ * XXXGL: in almost all cases uio is NULL and the mbuf is supplied.
+ * Exception is nfs/bootp_subr.c. It is arguable that the VNET context needs
+ * to be set at all. This function should just boil down to a static inline
+ * calling the protocol method.
+ */
int
sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
struct mbuf *top, struct mbuf *control, int flags, struct thread *td)
@@ -1835,6 +1843,47 @@
return (error);
}
+/*
+ * send(2), write(2) or aio_write(2) on a socket.
+ */
+int
+sousrsend(struct socket *so, struct sockaddr *addr, struct uio *uio,
+ struct mbuf *control, int flags, struct proc *userproc)
+{
+ struct thread *td;
+ ssize_t len;
+ int error;
+
+ td = uio->uio_td;
+ len = uio->uio_resid;
+ CURVNET_SET(so->so_vnet);
+ error = so->so_proto->pr_sosend(so, addr, uio, NULL, control, flags,
+ td);
+ CURVNET_RESTORE();
+ if (error != 0) {
+ if (uio->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) == 0 &&
+ (flags & MSG_NOSIGNAL) == 0) {
+ if (userproc != NULL) {
+ /* aio(4) job */
+ PROC_LOCK(userproc);
+ kern_psignal(userproc, SIGPIPE);
+ PROC_UNLOCK(userproc);
+ } else {
+ PROC_LOCK(td->td_proc);
+ tdsignal(td, SIGPIPE);
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ }
+ return (error);
+}
+
/*
* The part of soreceive() that implements reading non-inline out-of-band
* data from a socket. For more complete comments, see soreceive(), from
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -798,21 +798,7 @@
ktruio = cloneuio(&auio);
#endif
len = auio.uio_resid;
- error = sosend(so, mp->msg_name, &auio, 0, control, flags, td);
- if (error != 0) {
- 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) &&
- !(flags & MSG_NOSIGNAL)) {
- PROC_LOCK(td->td_proc);
- tdsignal(td, SIGPIPE);
- PROC_UNLOCK(td->td_proc);
- }
- }
+ error = sousrsend(so, mp->msg_name, &auio, control, flags, NULL);
if (error == 0)
td->td_retval[0] = len - auio.uio_resid;
#ifdef KTRACE
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -506,6 +506,8 @@
int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
struct mbuf *top, struct mbuf *control, int flags,
struct thread *td);
+int sousrsend(struct socket *so, struct sockaddr *addr, struct uio *uio,
+ struct mbuf *control, int flags, struct proc *);
int sosend_dgram(struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top, struct mbuf *control,
int flags, struct thread *td);

File Metadata

Mime Type
text/plain
Expires
Tue, Oct 1, 4:09 AM (13 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13227365
Default Alt Text
D35863.id114149.diff (5 KB)

Event Timeline