summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_socket.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2005-03-11 15:06:16 +0000
committerrwatson <rwatson@FreeBSD.org>2005-03-11 15:06:16 +0000
commita052488bb700c4c2bf0e8a936d9fd4263a733415 (patch)
treed0fc20ba407901bebe6289147ff19032e831fef5 /sys/kern/sys_socket.c
parent60ecbe760f21f3245c98e7bd94862e44208927f2 (diff)
downloadFreeBSD-src-a052488bb700c4c2bf0e8a936d9fd4263a733415.zip
FreeBSD-src-a052488bb700c4c2bf0e8a936d9fd4263a733415.tar.gz
The SO_NOSIGPIPE socket option allows a user process to mark a socket
so that the socket does not generate SIGPIPE, only EPIPE, when a write is attempted after socket shutdown. When the option was introduced in 2002, this required the logic for determining whether SIGPIPE was generated to be pushed down from dofilewrite() to the socket layer so that the socket options could be considered. However, the change in 2002 omitted modification to soo_write() required to add that logic, resulting in SIGPIPE not being generated even without SO_NOSIGPIPE when the socket was written to using write() or related generic system calls. This change adds the EPIPE logic to soo_write(), generating a SIGPIPE signal to the process associated with the passed uio in the event that the SO_NOSIGPIPE option is not set. Notes: - The are upsides and downsides to placing this logic in the socket layer as opposed to the file descriptor layer. This is really fd layer logic, but because we need so_options, we have a choice of layering violations and pick this one. - SIGPIPE possibly should be delivered to the thread performing the write, not the process performing the write. - uio->uio_td and the td argument to soo_write() might potentially differ; we use the thread in the uio argument. - The "sigpipe" regression test in src/tools/regression/sockets/sigpipe tests for the bug. Submitted by: Mikko Tyolajarvi <mbsd at pacbell dot net> Talked with: glebius, alfred PR: 78478 MFC after: 1 week
Diffstat (limited to 'sys/kern/sys_socket.c')
-rw-r--r--sys/kern/sys_socket.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index e196b6d..b12809f 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -39,8 +39,11 @@ __FBSDID("$FreeBSD$");
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/mac.h>
+#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/sigio.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/filio.h> /* XXX */
@@ -114,6 +117,11 @@ soo_write(fp, uio, active_cred, flags, td)
#endif
error = so->so_proto->pr_usrreqs->pru_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);
+ psignal(uio->uio_td->td_proc, SIGPIPE);
+ PROC_UNLOCK(uio->uio_td->td_proc);
+ }
NET_UNLOCK_GIANT();
return (error);
}
OpenPOWER on IntegriCloud