The problem with SIGPIPE is that it is a crock to begin with. SIGPIPE is in
the Unix design because sleazy C programs frequently do not check their error
return codes on write operations, so they don't realise it when the pipe to
which they are writing is bogus because the process reading from the other end
of the pipe died. So Unix not only returns an error code when this happens
(which is likely to be cheerfully ignored by the C program), but as a special
case, it also sends the writer the SIGPIPE signal, which by default guns your
process down.
Scsh turns this all this mess off, because it *always* checks the return
values from system calls for error returns, and raises an exception when this
happens. The default exception handler guns your program down, unless you are
running in "interactive" read-eval-print-loop mode, in which case you get a
breakpoint.
Alan Bawden pointed out a problem with scsh's treatment of SIGPIPE: if
we (fork and then) exec some sleazy C program from scsh, it will inherit
scsh's treatment of SIGPIPE -- i.e., it will ignore SIGPIPE. But it needs
SIGPIPE to have its default meaning, because it's a sleazy C program that
is prone to fouling its own nest.
So I have done the following. Scsh no longer sets SIGPIPE's handler to
SIG_IGN (ignore the signal). Rather, it sets the handler to a C function
that does nothing. This is fine for scsh, and it means that when you
exec() another program the handler is reset to the default value, so you
get the classic kill-me-I'm-a-loser semantics for programs that need it.
I.e., C programs.
Everyone's happy.
-Olin
|