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