Date: Mon, 28 Jun 2010 08:33:54 -0400 From: John Baldwin <jhb@freebsd.org> To: threads@freebsd.org Cc: kib@freebsd.org Subject: SIGPIPE and threads Message-ID: <201006280833.54224.jhb@freebsd.org>
next in thread | raw e-mail | index | archive | help
Currently when a thread performs a write(2) on a disconnected socket or a FIFO with no readers the SIGPIPE signal is posted to the entire process via psignal(). This means that the signal can be delivered to any thread in the process. However, it seems more intuitive to me that SIGPIPE should be sent to the "offending" thread similar to signals sent in response to traps via trapsignal(). POSIX seems to require this in that the description of the EPIPE error return value for write(2) and fflush(3) in the Open Group's online manpages both say that SIGPIPE should be sent to the current thread in addition to returning EPIPE: http://www.opengroup.org/onlinepubs/000095399/functions/write.html http://www.opengroup.org/onlinepubs/000095399/functions/fflush.html I have an untested (only compiled) patch below: Index: kern/uipc_syscalls.c =================================================================== --- kern/uipc_syscalls.c (revision 209571) +++ kern/uipc_syscalls.c (working copy) @@ -738,6 +738,7 @@ struct mbuf *control; enum uio_seg segflg; { + struct ksiginfo ksi; struct file *fp; struct uio auio; struct iovec *iov; @@ -793,8 +794,11 @@ /* Generation of SIGPIPE can be controlled per socket */ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && !(flags & MSG_NOSIGNAL)) { + ksiginfo_init(&ksi); + ksi.ksi_signo = SIGPIPE; + ksi.ksi_code = SI_KERNEL; PROC_LOCK(td->td_proc); - psignal(td->td_proc, SIGPIPE); + tdsignal(td->td_proc, td, SIGPIPE, &ksi); PROC_UNLOCK(td->td_proc); } } @@ -2379,6 +2383,7 @@ { #if (defined(INET) || defined(INET6)) && defined(SCTP) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; + struct ksiginfo ksi; struct socket *so; struct file *fp = NULL; int use_rcvinfo = 1; @@ -2443,8 +2448,11 @@ /* Generation of SIGPIPE can be controlled per socket. */ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && !(uap->flags & MSG_NOSIGNAL)) { + ksiginfo_init(&ksi); + ksi.ksi_signo = SIGPIPE; + ksi.ksi_code = SI_KERNEL; PROC_LOCK(td->td_proc); - psignal(td->td_proc, SIGPIPE); + tdsignal(td->td_proc, td, SIGPIPE, &ksi); PROC_UNLOCK(td->td_proc); } } @@ -2483,6 +2491,7 @@ { #if (defined(INET) || defined(INET6)) && defined(SCTP) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; + struct ksiginfo ksi; struct socket *so; struct file *fp = NULL; int use_rcvinfo = 1; @@ -2561,8 +2570,11 @@ /* Generation of SIGPIPE can be controlled per socket */ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) && !(uap->flags & MSG_NOSIGNAL)) { + ksiginfo_init(&ksi); + ksi.ksi_signo = SIGPIPE; + ksi.ksi_code = SI_KERNEL; PROC_LOCK(td->td_proc); - psignal(td->td_proc, SIGPIPE); + tdsignal(td->td_proc, td, SIGPIPE, &ksi); PROC_UNLOCK(td->td_proc); } } Index: kern/sys_socket.c =================================================================== --- kern/sys_socket.c (revision 209571) +++ kern/sys_socket.c (working copy) @@ -92,6 +92,7 @@ int flags, struct thread *td) { struct socket *so = fp->f_data; + struct ksiginfo ksi; int error; #ifdef MAC @@ -101,8 +102,11 @@ #endif error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td); if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) { + ksiginfo_init(&ksi); + ksi.ksi_signo = SIGPIPE; + ksi.ksi_code = SI_KERNEL; PROC_LOCK(uio->uio_td->td_proc); - psignal(uio->uio_td->td_proc, SIGPIPE); + tdsignal(uio->uio_td->td_proc, uio->uio_td, SIGPIPE, &ksi); PROC_UNLOCK(uio->uio_td->td_proc); } return (error); Index: kern/sys_generic.c =================================================================== --- kern/sys_generic.c (revision 209571) +++ kern/sys_generic.c (working copy) @@ -509,6 +509,7 @@ off_t offset; int flags; { + struct ksiginfo ksi; ssize_t cnt; int error; #ifdef KTRACE @@ -531,8 +532,11 @@ error = 0; /* Socket layer is responsible for issuing SIGPIPE. */ if (fp->f_type != DTYPE_SOCKET && error == EPIPE) { + ksiginfo_init(&ksi); + ksi.ksi_signo = SIGPIPE; + ksi.ksi_code = SI_KERNEL; PROC_LOCK(td->td_proc); - psignal(td->td_proc, SIGPIPE); + tdsignal(td->td_proc, td, SIGPIPE, &ksi); PROC_UNLOCK(td->td_proc); } } -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006280833.54224.jhb>