From owner-freebsd-threads@FreeBSD.ORG Mon Jun 28 12:33:56 2010 Return-Path: Delivered-To: threads@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B7425106564A; Mon, 28 Jun 2010 12:33:56 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id 8E1B18FC0C; Mon, 28 Jun 2010 12:33:56 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id 1277546B09; Mon, 28 Jun 2010 08:33:56 -0400 (EDT) Received: from jhbbsd.localnet (smtp.hudson-trading.com [209.249.190.9]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id E3EBA8A03C; Mon, 28 Jun 2010 08:33:54 -0400 (EDT) From: John Baldwin To: threads@freebsd.org Date: Mon, 28 Jun 2010 08:33:54 -0400 User-Agent: KMail/1.12.1 (FreeBSD/7.3-CBSD-20100217; KDE/4.3.1; amd64; ; ) MIME-Version: 1.0 Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <201006280833.54224.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.0.1 (bigwig.baldwin.cx); Mon, 28 Jun 2010 08:33:54 -0400 (EDT) X-Virus-Scanned: clamav-milter 0.95.1 at bigwig.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-2.6 required=4.2 tests=AWL,BAYES_00 autolearn=ham version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on bigwig.baldwin.cx Cc: kib@freebsd.org Subject: SIGPIPE and threads X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jun 2010 12:33:56 -0000 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