Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Jun 2002 02:07:30 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Alfred Perlstein <bright@mu.org>
Cc:        Michael Smith <msmith@mass.dis.org>, Giorgos Keramidas <keramida@ceid.upatras.gr>, Mario Sergio Fujikawa Ferreira <lioux@freebsd.org>, Garance A Drosihn <drosih@rpi.edu>, FreeBSD-arch@freebsd.org, msmith@freebsd.org
Subject:   Re: Adding SO_NOSIGPIPE to -STABLE/-CURRENT
Message-ID:  <3D0DA6D2.39A8C06F@mindspring.com>
References:  <3D0D904D.4752ADD4@mindspring.com> <200206170747.g5H7l3uJ001188@mass.dis.org> <20020617081320.GG67925@elvis.mu.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Alfred Perlstein wrote:

[ ... ]

Excuse me.  Are you in the same discussion I'm in?

Please *read* Mario's patch; specifically:

--- sys/kern/sys_generic.c.orig Mon Feb 25 19:22:18 2002
+++ sys/kern/sys_generic.c      Mon Feb 25 19:22:55 2002
@@ -409,7 +409,8 @@
                if (auio.uio_resid != cnt && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
                        error = 0;
-               if (error == EPIPE)
+               /* The socket layer handles SIGPIPE */
+               if (error == EPIPE && fp->f_type != DTYPE_SOCKET)
                        psignal(p, SIGPIPE);
        }
        cnt -= auio.uio_resid;

Turns off *all* socket-related SIGPIPE as a result of write(2)
and writev(2).

The other part of the patch:

--- sys/kern/uipc_syscalls.c.orig       Mon Feb 25 19:59:54 2002
+++ sys/kern/uipc_syscalls.c    Mon Feb 25 20:01:48 2002
@@ -586,7 +586,8 @@
                if (auio.uio_resid != len && (error == ERESTART ||
                    error == EINTR || error == EWOULDBLOCK))
                        error = 0;
-               if (error == EPIPE)
+               /* Generation of SIGPIPE can be controlled per socket */
+               if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE))
                        psignal(p, SIGPIPE);
        }
        if (error == 0)

Is *only* effective in the send(2), sendto(2), and sendmsg(2)
cases.

In other words, it turns the SIGPIPE off in a code path, makes
it switchable in a second code path, and thereafter provides no
mechanism whereby the SISGPIPE may be turned back on in the first
code path.

The /socket/ is not available in the write path, the /descriptor/
is; to convert it from a /descriptor/ to a /socket/, you would
have to do a lot of tests and dereferencing (nominally OK, since
it's an already expensive error path, but hard to do without
dragging in most of the socket headers into kern/sys_generic.c).

Therefore, my *initial* post in this thread suggested that, if it
be done at all, it be done as a /descriptor/ option, via fcntl,
rather than as a /socket/ option, via setsockopt().  I was not
aware that people has used up all the available fcntl() commands.


Unless you fix the CLEVERLY HIDDEN BREAKAGE it introduces in
dofilewrite() on sockets in sys_generic.c, I think it's a BAD IDEA
to commit the patch.


I *also* think that if this option is set on a listening socket,
that, if it is implemented in this way, it should be inheritted
by each accepted socket.  If the bad idea must go forward, it
should at least be implemented correctly.

The obvious reasoning for this is that there is not an fd available
on which to set the option for the new connection until after the
accept(2) is called to accept the connection.  Since the *entire*
point of this patch *must* be to save the system call to check to
see if a descriptor is writeable, OR to save the two system calls
that disabling and reenabling the SIGPIPE around a write to close
the tiny check-then-write race window, saving additional system
calls on each socket opened to set the option is also good.


Looking at it from a general standpoint, I'd *still* like to see
some code that people are going to be running on FreeBSD that
won't run without it.


IF the option is committed because of the "compatability" argument,
I'd like to see it named the same thing as at least one other OS,
to avoid "#ifdef FreeBSD"; if that's not going to happen, then you
might as well put better code in the #ifdef FreeBSD", instead.


If I seem to think that this promotes signal semantics that I think
ought to be determined by the system, well, here's Mario's original
rationale for the change in the first place:

|         For those that might find it useful, here go a
| simple scenario not easily reproduceable without SO_NOSIGPIPE:
| multi-threaded client, some threads want to handle SIGPIPE,
| others not.

...in other words, to control the threads signal semantics more
closely than is normally permitted by the POSIX definition of
signals.


If I sound like I think this is a slippery slope -- I DO.  I can
see *at least* wanting to so the same for any signal that could
result from a "write" that has a default of "terminate process".

I could also see wanting to set the same for SIGURG -- in case
the user establishes a SIGURG handler outside the context of
the library and/or threaded application under discussion.  It
is *not* just "terminate process" signal actions that you have
to worry about, it's also any signal whose default action is
"discard signal", and which might have been overridden by the
user.


-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D0DA6D2.39A8C06F>