SIGPIPE and threads
Kostik Belousov
kostikbel at gmail.com
Mon Jun 28 14:05:44 UTC 2010
On Mon, Jun 28, 2010 at 08:33:54AM -0400, John Baldwin wrote:
> 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:
I think the patch is right, but, as you note, having a dedicated
function that wraps automatic ksi initialization and tdsignal()
call would be even better.
>
> 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-threads/attachments/20100628/2f40ac01/attachment-0001.pgp
More information about the freebsd-threads
mailing list