kern/76426: Linux ABI doesn't support MSG_NOSIGNAL

Steven Harltand killing at multiplay.co.uk
Tue Jan 18 11:00:44 PST 2005


>Number:         76426
>Category:       kern
>Synopsis:       Linux ABI doesn't support MSG_NOSIGNAL
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jan 18 19:00:43 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Steven Hartland
>Release:        FreeBSD 5.2.1-RELEASE-p13 i386
>Organization:
Multiplay UK
>Environment:
System: FreeBSD dev1.multiplay.co.uk 5.2.1-RELEASE-p13 FreeBSD 5.2.1-RELEASE-p13 #0: Tue Jan 18 11:07:10 GMT 2005 root at dev1.multiplay.co.uk:/usr/src/sys/i386/compile/MPUK_SINGLE_200HZ i386


>Description:
	The linux ABI doesnt support MSG_NOSIGNAL it just gets lost in linux_send.
	The attached patch temporatly set SO_NOSIGPIPE on the socket fixing this issue.
	Im not 100% sure this is the best way of doing it but it works.
>How-To-Repeat:
	Set the MSG_NOSIGNAL on a long running send and close the reciever. SIGPIPE
	should be ignored but its not currently, causing the sender to exit if not
	caught manually.
>Fix:
	Apply the following patch:
--- linux_socket.c.orig	Tue Jan 18 10:41:32 2005
+++ linux_socket.c	Tue Jan 18 11:02:37 2005
@@ -869,5 +869,48 @@
 	bsd_args.len = linux_args.len;
 	bsd_args.flags = linux_args.flags;
-	return (osend(td, &bsd_args));
+	if ( linux_args.flags & LINUX_MSG_NOSIGNAL )
+	{
+		/* requested to ignore pipe so set SO_NOSIGPIPE temporarily */
+		int ret_send, ret_opt;
+		struct setsockopt_args /* {
+			int s;
+			int level;
+			int name;
+			caddr_t val;
+			int valsize;  
+		} */ bsd_setsockopt_args;
+		caddr_t sg;
+        int *nosigpipe;
+
+        sg = stackgap_init();
+        nosigpipe = (int *)stackgap_alloc(&sg, sizeof(*nosigpipe));
+        *nosigpipe = 1;
+        bsd_setsockopt_args.s = linux_args.s;
+        bsd_setsockopt_args.level = SOL_SOCKET;
+        bsd_setsockopt_args.name = SO_NOSIGPIPE;
+        bsd_setsockopt_args.val = (caddr_t)nosigpipe;
+        bsd_setsockopt_args.valsize = sizeof(*nosigpipe);
+        ret_opt = setsockopt(td, &bsd_setsockopt_args);
+		if ( -1 == ret_opt )
+		{
+			return ret_opt;
+		}
+
+		ret_send = (osend(td, &bsd_args));
+		/* must clear the option */
+        *nosigpipe = 1;
+        bsd_setsockopt_args.val = (caddr_t)nosigpipe;
+        ret_opt = setsockopt(td, &bsd_setsockopt_args);
+		if ( -1 == ret_send || -1 == ret_opt )
+		{
+			return -1;
+		}
+
+		return ret_send;
+	}
+	else
+	{
+		return (osend(td, &bsd_args));
+	}
 }

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list