tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Adding an option to avoid SIGPIPE for all file descriptors



Hello,

In most programs the delivery of SIGPIPE (typically when one side
of a socket or pipe closes and the other side tries to write) is
annoying to handle, and the only solution to avoid it is to have
the main program do signal(SIGPIPE, SIG_IGN), so the the system
calls set errno = EPIPE instead. It would be nice if the default
was the other way around (you needed to ask for SIGPIPE to get it,
the same way you ask for SIGIO), but it is too late to do this now.

If you are a library writer who is dealing with pipes or sockets
you are at the mercy of the main program as to how this is going
to be handled. If you are a threaded program, the situation is even
more complicated. Setting the signal handler is an all or nothing
solution and other OS's have come up with many solutions for this.

Namely setsockopt SO_NOSIGPIPE (FreeBSD/MacOSX),
fcntl(F_SETNOSIGPIPE/F_GETNOSIGPIPE) (MacOSX).  This has led to
even more complexity (what happens if the socket is closed on
SO_NOSIGPIPE? SO_NP_EXTENSIONS? ugh!). What I propose to do, and
the patch here implements it, is to handle the EPIPE disposition
at the file flags (regardless if the file descriptor is a socket or
not) and send SIGPIPE only if the flag O_NOSIGPIPE is clear. This
is actually simpler and less intrusive to implement (because it
does not special-case sockets, and the signal delivery is still
centralized for all file descriptors), plus it handles all current
and future file descriptor types or drivers that can return EPIPE.

Comments?

christos

Index: lib/libc/sys/dup.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/dup.2,v
retrieving revision 1.27
diff -u -p -u -r1.27 dup.2
--- lib/libc/sys/dup.2  22 Jul 2011 11:02:39 -0000      1.27
+++ lib/libc/sys/dup.2  24 Jan 2012 01:48:28 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)dup.2      8.1 (Berkeley) 6/4/93
 .\"
-.Dd July 16, 2011
+.Dd January 23, 2012
 .Dt DUP 2
 .Os
 .Sh NAME
@@ -118,6 +118,11 @@ Set the
 property.
 .It Dv O_NONBLOCK
 Sets non-blocking I/O.
+.It Dv O_NOSIGPIPE
+Return
+.Er EPIPE
+instead of raising
+.Dv SIGPIPE .
 .El
 .Sh RETURN VALUES
 The value \-1 is returned if an error occurs in either call.
Index: lib/libc/sys/fcntl.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/fcntl.2,v
retrieving revision 1.39
diff -u -p -u -r1.39 fcntl.2
--- lib/libc/sys/fcntl.2        27 Jun 2011 08:21:08 -0000      1.39
+++ lib/libc/sys/fcntl.2        24 Jan 2012 01:48:28 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)fcntl.2    8.2 (Berkeley) 1/12/94
 .\"
-.Dd June 25, 2011
+.Dd January 23, 2012
 .Dt FCNTL 2
 .Os
 .Sh NAME
@@ -146,6 +146,14 @@ Close all file descriptors greater than 
 .Ar fd .
 .It Dv F_MAXFD
 Return the maximum file descriptor number currently open by the process.
+.It Dv F_GETNOSIGPIPE
+Return if the
+.Dv O_NOSIGPIPE
+flag is set in the file descriptor.
+.It Dv F_SETNOSIGPIPE
+Set or clear the
+.Dv O_NOSIGPIPE
+in the file descriptor.
 .El
 .Pp
 The flags for the
Index: lib/libc/sys/getsockopt.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/getsockopt.2,v
retrieving revision 1.34
diff -u -p -u -r1.34 getsockopt.2
--- lib/libc/sys/getsockopt.2   29 Jun 2009 08:38:07 -0000      1.34
+++ lib/libc/sys/getsockopt.2   24 Jan 2012 01:48:29 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)getsockopt.2       8.4 (Berkeley) 5/2/95
 .\"
-.Dd June 28, 2009
+.Dd January 23, 2012
 .Dt GETSOCKOPT 2
 .Os
 .Sh NAME
@@ -167,6 +167,10 @@ and set with
 .It Dv SO_RCVTIMEO Ta "set timeout value for input"
 .It Dv SO_TIMESTAMP Ta "enables reception of a timestamp with datagrams"
 .It Dv SO_ACCEPTFILTER Ta "set accept filter on listening socket"
+.It Dv SO_NOSIGPIPE Ta
+controls generation of
+.Dv SIGPIPE
+for the socket
 .It Dv SO_TYPE Ta "get the type of the socket (get only)"
 .It Dv SO_ERROR Ta "get and clear error on the socket (get only)"
 .El
Index: lib/libc/sys/kqueue.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/kqueue.2,v
retrieving revision 1.31
diff -u -p -u -r1.31 kqueue.2
--- lib/libc/sys/kqueue.2       26 Jun 2011 16:42:41 -0000      1.31
+++ lib/libc/sys/kqueue.2       24 Jan 2012 01:48:29 -0000
@@ -32,7 +32,7 @@
 .\"
 .\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.22 2001/06/27 19:55:57 dd Exp $
 .\"
-.Dd June 24, 2011
+.Dd January 23, 2012
 .Dt KQUEUE 2
 .Os
 .Sh NAME
@@ -92,6 +92,11 @@ on the returned file descriptor:
 Set the close on exec property.
 .It Dv O_NONBLOCK
 Sets non-blocking I/O.
+.It Dv O_NOSIGPIPE
+Return
+.Er EPIPE
+instead of raising
+.Dv SIGPIPE .
 .El
 The queue is not inherited by a child created with
 .Xr fork 2 .
Index: lib/libc/sys/open.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/open.2,v
retrieving revision 1.50
diff -u -p -u -r1.50 open.2
--- lib/libc/sys/open.2 20 Apr 2011 19:57:58 -0000      1.50
+++ lib/libc/sys/open.2 24 Jan 2012 01:48:29 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)open.2     8.2 (Berkeley) 11/16/93
 .\"
-.Dd April 20, 2011
+.Dd January 23, 2012
 .Dt OPEN 2
 .Os
 .Sh NAME
@@ -99,6 +99,11 @@ Set the
 on
 .Xr exec 3
 flag.
+.It Dv O_NOSIGPIPE
+Return
+.Er EPIPE
+instead of raising
+.Dv SIGPIPE .
 .It Dv O_DSYNC
 If set, write operations will be performed according to synchronized
 I/O data integrity completion:
Index: lib/libc/sys/pipe.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/pipe.2,v
retrieving revision 1.27
diff -u -p -u -r1.27 pipe.2
--- lib/libc/sys/pipe.2 22 Jul 2011 11:02:39 -0000      1.27
+++ lib/libc/sys/pipe.2 24 Jan 2012 01:48:29 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)pipe.2     8.1 (Berkeley) 6/4/93
 .\"
-.Dd July 15, 2011
+.Dd January 23, 2012
 .Dt PIPE 2
 .Os
 .Sh NAME
@@ -97,6 +97,11 @@ Set the
 property.
 .It Dv O_NONBLOCK
 Sets non-blocking I/O.
+.It Dv O_NOSIGPIPE
+Return
+.Er EPIPE
+instead of raising
+.Dv SIGPIPE .
 .El
 .Sh RETURN VALUES
 On successful creation of the pipe, zero is returned.
Index: lib/libc/sys/socket.2
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/socket.2,v
retrieving revision 1.37
diff -u -p -u -r1.37 socket.2
--- lib/libc/sys/socket.2       26 Jun 2011 16:42:41 -0000      1.37
+++ lib/libc/sys/socket.2       24 Jan 2012 01:48:29 -0000
@@ -86,6 +86,11 @@ The following flags are valid:
 Set the close on exec property.
 .It Dv SOCK_NONBLOCK
 Sets non-blocking I/O.
+.It Dv SOCK_NOSIGPIPE
+Return
+.Er EPIPE
+instead of raising
+.Dv SIGPIPE .
 .El
 .Pp
 A
Index: sys/sys/fcntl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/fcntl.h,v
retrieving revision 1.41
diff -u -p -u -r1.41 fcntl.h
--- sys/sys/fcntl.h     9 Aug 2011 04:19:17 -0000       1.41
+++ sys/sys/fcntl.h     24 Jan 2012 01:48:30 -0000
@@ -117,6 +117,9 @@
 #if defined(_INCOMPLETE_XOPEN_C063) || defined(_KERNEL)
 #define        O_SEARCH        0x00800000      /* skip search permission 
checks */
 #endif
+#if defined(_NETBSD_SOURCE)
+#define        O_NOSIGPIPE     0x01000000      /* don't deliver sigpipe */
+#endif
 
 #ifdef _KERNEL
 /* convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE */
@@ -127,7 +130,7 @@
 #define        O_MASK          
(O_ACCMODE|O_NONBLOCK|O_APPEND|O_SHLOCK|O_EXLOCK|\
                         O_ASYNC|O_SYNC|O_CREAT|O_TRUNC|O_EXCL|O_DSYNC|\
                         O_RSYNC|O_NOCTTY|O_ALT_IO|O_NOFOLLOW|O_DIRECT|\
-                        O_DIRECTORY|O_CLOEXEC)
+                        O_DIRECTORY|O_CLOEXEC|O_NOSIGPIPE)
 
 #define        FMARK           0x00001000      /* mark during gc() */
 #define        FDEFER          0x00002000      /* defer for next gc pass */
@@ -155,6 +158,7 @@
 #define        O_NDELAY        O_NONBLOCK      /* compat */
 #endif
 #if defined(_KERNEL)
+#define        FNOSIGPIPE      O_NOSIGPIPE     /* kernel */
 #define        FNONBLOCK       O_NONBLOCK      /* kernel */
 #define        FFSYNC          O_SYNC          /* kernel */
 #define        FDSYNC          O_DSYNC         /* kernel */
@@ -185,6 +189,8 @@
 #define        F_CLOSEM        10              /* close all fds >= to the one 
given */
 #define        F_MAXFD         11              /* return the max open fd */
 #define        F_DUPFD_CLOEXEC 12              /* close on exec duplicated fd 
*/
+#define        F_GETNOSIGPIPE  13              /* get SIGPIPE disposition */
+#define        F_SETNOSIGPIPE  14              /* set SIGPIPE disposition */
 #endif
 
 /* file descriptor flags (F_GETFD, F_SETFD) */
Index: sys/sys/filedesc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/filedesc.h,v
retrieving revision 1.61
diff -u -p -u -r1.61 filedesc.h
--- sys/sys/filedesc.h  26 Jun 2011 16:43:12 -0000      1.61
+++ sys/sys/filedesc.h  24 Jan 2012 01:48:30 -0000
@@ -200,6 +200,7 @@ file_t      *fd_getfile2(proc_t *, unsigned);
 void   fd_putfile(unsigned);
 int    fd_getvnode(unsigned, file_t **);
 int    fd_getsock(unsigned, struct socket **);
+int    fd_getsock1(unsigned, struct socket **, file_t **);
 void   fd_putvnode(unsigned);
 void   fd_putsock(unsigned);
 int    fd_close(unsigned);
Index: sys/sys/socket.h
===================================================================
RCS file: /cvsroot/src/sys/sys/socket.h,v
retrieving revision 1.104
diff -u -p -u -r1.104 socket.h
--- sys/sys/socket.h    20 Jan 2012 14:08:07 -0000      1.104
+++ sys/sys/socket.h    24 Jan 2012 01:48:30 -0000
@@ -110,6 +110,7 @@ typedef     _BSD_SSIZE_T_   ssize_t;
 
 #define        SOCK_CLOEXEC    0x10000000      /* set close on exec on socket 
*/
 #define        SOCK_NONBLOCK   0x20000000      /* set non blocking i/o socket 
*/
+#define        SOCK_NOSIGPIPE  0x40000000      /* don't send sigpipe */
 #define        SOCK_FLAGS_MASK 0xf0000000      /* flags mask */
 
 /*
@@ -126,6 +127,7 @@ typedef     _BSD_SSIZE_T_   ssize_t;
 #define        SO_OOBINLINE    0x0100          /* leave received OOB data in 
line */
 #define        SO_REUSEPORT    0x0200          /* allow local address & port 
reuse */
 /*     SO_OTIMESTAMP   0x0400          */
+#define        SO_NOSIGPIPE    0x0800          /* no SIGPIPE from EPIPE */
 #define        SO_ACCEPTFILTER 0x1000          /* there is an accept filter */
 #define        SO_TIMESTAMP    0x2000          /* timestamp received dgram 
traffic */
 
Index: sys/kern/kern_descrip.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_descrip.c,v
retrieving revision 1.217
diff -u -p -u -r1.217 kern_descrip.c
--- sys/kern/kern_descrip.c     25 Sep 2011 13:40:37 -0000      1.217
+++ sys/kern/kern_descrip.c     24 Jan 2012 01:48:31 -0000
@@ -500,22 +500,27 @@ fd_getvnode(unsigned fd, file_t **fpp)
  * to a socket.
  */
 int
-fd_getsock(unsigned fd, struct socket **sop)
+fd_getsock1(unsigned fd, struct socket **sop, file_t **fp)
 {
-       file_t *fp;
-
-       fp = fd_getfile(fd);
-       if (__predict_false(fp == NULL)) {
+       *fp = fd_getfile(fd);
+       if (__predict_false(*fp == NULL)) {
                return EBADF;
        }
-       if (__predict_false(fp->f_type != DTYPE_SOCKET)) {
+       if (__predict_false((*fp)->f_type != DTYPE_SOCKET)) {
                fd_putfile(fd);
                return ENOTSOCK;
        }
-       *sop = fp->f_data;
+       *sop = (*fp)->f_data;
        return 0;
 }
 
+int
+fd_getsock(unsigned fd, struct socket **sop)
+{
+       file_t *fp;
+       return fd_getsock1(fd, sop, &fp);
+}
+
 /*
  * Look up the file structure corresponding to a file descriptor
  * and return it with a reference held on the file, not the
Index: sys/kern/kern_event.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_event.c,v
retrieving revision 1.74
diff -u -p -u -r1.74 kern_event.c
--- sys/kern/kern_event.c       17 Nov 2011 22:41:55 -0000      1.74
+++ sys/kern/kern_event.c       24 Jan 2012 01:48:32 -0000
@@ -725,7 +725,7 @@ kqueue1(struct lwp *l, int flags, regist
 
        if ((error = fd_allocfile(&fp, &fd)) != 0)
                return error;
-       fp->f_flag = FREAD | FWRITE | (flags & FNONBLOCK);
+       fp->f_flag = FREAD | FWRITE | (flags & (FNONBLOCK|FNOSIGPIPE));
        fp->f_type = DTYPE_KQUEUE;
        fp->f_ops = &kqueueops;
        kq = kmem_zalloc(sizeof(*kq), KM_SLEEP);
Index: sys/kern/sys_descrip.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_descrip.c,v
retrieving revision 1.23
diff -u -p -u -r1.23 sys_descrip.c
--- sys/kern/sys_descrip.c      31 Oct 2011 21:31:29 -0000      1.23
+++ sys/kern/sys_descrip.c      24 Jan 2012 01:48:34 -0000
@@ -403,6 +403,18 @@ sys_fcntl(struct lwp *l, const struct sy
                    ((long)SCARG(uap, arg) & FD_CLOEXEC) != 0);
                break;
 
+       case F_GETNOSIGPIPE:
+               *retval = (fp->f_flag & FNOSIGPIPE) != 0;
+               break;
+
+       case F_SETNOSIGPIPE:
+               if (SCARG(uap, arg))
+                       fp->f_flag |= FNOSIGPIPE;
+               else
+                       fp->f_flag &= ~FNOSIGPIPE;
+               *retval = 0;
+               break;
+
        case F_GETFL:
                *retval = OFLAGS(fp->f_flag);
                break;
Index: sys/kern/sys_generic.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_generic.c,v
retrieving revision 1.127
diff -u -p -u -r1.127 sys_generic.c
--- sys/kern/sys_generic.c      27 Jul 2011 14:35:34 -0000      1.127
+++ sys/kern/sys_generic.c      24 Jan 2012 01:48:34 -0000
@@ -357,7 +357,7 @@ dofilewrite(int fd, struct file *fp, con
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
                        error = 0;
-               if (error == EPIPE) {
+               if (error == EPIPE && !(fp->f_flag & FNOSIGPIPE)) {
                        mutex_enter(proc_lock);
                        psignal(curproc, SIGPIPE);
                        mutex_exit(proc_lock);
@@ -484,7 +484,7 @@ do_filewritev(int fd, const struct iovec
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
                        error = 0;
-               if (error == EPIPE) {
+               if (error == EPIPE && !(fp->f_flag & FNOSIGPIPE)) {
                        mutex_enter(proc_lock);
                        psignal(curproc, SIGPIPE);
                        mutex_exit(proc_lock);
Index: sys/kern/sys_pipe.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_pipe.c,v
retrieving revision 1.134
diff -u -p -u -r1.134 sys_pipe.c
--- sys/kern/sys_pipe.c 20 Oct 2011 18:18:21 -0000      1.134
+++ sys/kern/sys_pipe.c 24 Jan 2012 01:48:35 -0000
@@ -251,7 +251,7 @@ pipe1(struct lwp *l, register_t *retval,
        int fd, error;
        proc_t *p;
 
-       if (flags & ~(O_CLOEXEC|O_NONBLOCK))
+       if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
                return EINVAL;
        p = curproc;
        rpipe = wpipe = NULL;
Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cvsroot/src/sys/kern/uipc_socket.c,v
retrieving revision 1.206
diff -u -p -u -r1.206 uipc_socket.c
--- sys/kern/uipc_socket.c      20 Dec 2011 23:56:28 -0000      1.206
+++ sys/kern/uipc_socket.c      24 Jan 2012 01:48:36 -0000
@@ -589,7 +589,8 @@ fsocreate(int domain, struct socket **so
        if ((error = fd_allocfile(&fp, &fd)) != 0)
                return error;
        fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
-       fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0);
+       fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
+           ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
        fp->f_type = DTYPE_SOCKET;
        fp->f_ops = &socketops;
        error = socreate(domain, &so, type, protocol, l, NULL);
@@ -1719,6 +1720,7 @@ sosetopt1(struct socket *so, const struc
        case SO_REUSEPORT:
        case SO_OOBINLINE:
        case SO_TIMESTAMP:
+       case SO_NOSIGPIPE:
 #ifdef SO_OTIMESTAMP
        case SO_OTIMESTAMP:
 #endif
@@ -1919,6 +1921,7 @@ sogetopt1(struct socket *so, struct sock
        case SO_BROADCAST:
        case SO_OOBINLINE:
        case SO_TIMESTAMP:
+       case SO_NOSIGPIPE:
 #ifdef SO_OTIMESTAMP
        case SO_OTIMESTAMP:
 #endif
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.150
diff -u -p -u -r1.150 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c    21 Dec 2011 15:26:57 -0000      1.150
+++ sys/kern/uipc_syscalls.c    24 Jan 2012 01:48:36 -0000
@@ -229,7 +229,8 @@ do_sys_accept(struct lwp *l, int sock, s
                panic("accept");
        fp2->f_type = DTYPE_SOCKET;
        fp2->f_flag = (fp->f_flag & ~clrflags) |
-           ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0); 
+           ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
+           ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
        fp2->f_ops = &socketops;
        fp2->f_data = so2;
        error = soaccept(so2, nam);
@@ -407,7 +408,6 @@ makesocket(struct lwp *l, file_t **fp, i
 {
        int error;
        struct socket *so;
-       int fnonblock = (flags & SOCK_NONBLOCK) ? FNONBLOCK : 0; 
 
        if ((error = socreate(domain, &so, type, proto, l, soo)) != 0)
                return error;
@@ -417,7 +417,9 @@ makesocket(struct lwp *l, file_t **fp, i
                return error;
        }
        fd_set_exclose(l, *fd, (flags & SOCK_CLOEXEC) != 0);
-       (*fp)->f_flag = FREAD|FWRITE|fnonblock;
+       (*fp)->f_flag = FREAD|FWRITE|
+           ((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
+           ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
        (*fp)->f_type = DTYPE_SOCKET;
        (*fp)->f_ops = &socketops;
        (*fp)->f_data = so;
@@ -533,6 +535,7 @@ do_sys_sendmsg(struct lwp *l, int s, str
        struct iovec    aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
        struct mbuf     *to, *control;
        struct socket   *so;
+       file_t          *fp;
        struct uio      auio;
        size_t          len, iovsz;
        int             i, error;
@@ -606,7 +609,7 @@ do_sys_sendmsg(struct lwp *l, int s, str
                memcpy(ktriov, auio.uio_iov, iovsz);
        }
 
-       if ((error = fd_getsock(s, &so)) != 0)
+       if ((error = fd_getsock1(s, &so, &fp)) != 0)
                goto bad;
 
        if (mp->msg_name)
@@ -625,7 +628,8 @@ do_sys_sendmsg(struct lwp *l, int s, str
                if (auio.uio_resid != len && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
                        error = 0;
-               if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) {
+               if (error == EPIPE && (fp->f_flag & FNOSIGPIPE) == 0 &&
+                   (flags & MSG_NOSIGNAL) == 0) {
                        mutex_enter(proc_lock);
                        psignal(l->l_proc, SIGPIPE);
                        mutex_exit(proc_lock);
@@ -946,6 +950,7 @@ sys_setsockopt(struct lwp *l, const stru
        } */
        struct sockopt  sopt;
        struct socket   *so;
+       file_t          *fp;
        int             error;
        unsigned int    len;
 
@@ -956,7 +961,7 @@ sys_setsockopt(struct lwp *l, const stru
        if (len > MCLBYTES)
                return (EINVAL);
 
-       if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
+       if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
                return (error);
 
        sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);
@@ -968,6 +973,10 @@ sys_setsockopt(struct lwp *l, const stru
        }
 
        error = sosetopt(so, &sopt);
+       if (so->so_options & SO_NOSIGPIPE)
+               fp->f_flag |= FNOSIGPIPE;
+       else
+               fp->f_flag &= ~FNOSIGPIPE;
 
  out:
        sockopt_destroy(&sopt);
@@ -988,6 +997,7 @@ sys_getsockopt(struct lwp *l, const stru
        } */
        struct sockopt  sopt;
        struct socket   *so;
+       file_t          *fp;
        unsigned int    valsize, len;
        int             error;
 
@@ -998,11 +1008,15 @@ sys_getsockopt(struct lwp *l, const stru
        } else
                valsize = 0;
 
-       if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
+       if ((error = fd_getsock1(SCARG(uap, s), &so, &fp)) != 0)
                return (error);
 
        sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);
 
+       if (fp->f_flag & FNOSIGPIPE)
+               so->so_options |= SO_NOSIGPIPE;
+       else
+               so->so_options &= ~SO_NOSIGPIPE;
        error = sogetopt(so, &sopt);
        if (error)
                goto out;
@@ -1034,7 +1048,7 @@ pipe1(struct lwp *l, register_t *retval,
        int             fd, error;
        proc_t          *p;
 
-       if (flags & ~(O_CLOEXEC|O_NONBLOCK))
+       if (flags & ~(O_CLOEXEC|O_NONBLOCK|O_NOSIGPIPE))
                return EINVAL;
        p = curproc;
        if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL)) != 0)


Home | Main Index | Thread Index | Old Index