From Newsgroup: comp.lang.misc
Janis Papanagnou <
janis_papanagnou+ng@hotmail.com> writes:
On 17.09.2025 18:39, Andy Walker wrote:
> I think the root problem is that there are too many ways a pipe
> can fail,
What different ways (that are worthwhile to be reported) are you
thinking about here?
I can't tell what anybody is thinking about anything here, and I have no
idea about how your Algol runtime might actually be implemented, but
perhaps the following story about SIGPIPE and its history might prove
helpful:
SIGPIPE is not just signalled when you write to a pipe with no reader, it
is also signalled when you write to a network connection that has been
shut down.
This is arguably a botch on the part of the folks that added networking
support to Unix. Network sockets and pipes behave similarly in a lot of situations, so somebody thought that it would be natural to re-use
SIGPIPE for the case of writing to a broken network connection.
Unfortunately the default action for SIGPIPE, which is to silently
terminate the process, isn't suitable for network programming where
network connections get broken all the time. (If I'm doing some
transaction to a remote database, should my process _silently_ exit when
the remote server crashes? Probably not!)
So on Unix, if you are a C programmer writing a program that expects to
talk over the network in any way, you must either (a) install your own
handler for SIGPIPE, or (b) set SIGPIPE to be ignored, and then check for
the EPIPE error after every call to to the write() system call. Since
you already have to check for _other_ errors after every call to write(),
most people choose (b). (Also, writing signal handlers is tricky.)
So what are you supposed to do if you are writing the runtime support for
some programming language such as Algol (or alternatively Python)? Well
a lot of the libraries that your users will want to use will be making
network connections, so those libraries will need a consistent answer
about how SIGPIPE handling is configured. Your best choice (IMHO), as
the runtime author, is to alter the Unix default and set SIGPIPE to be
ignored. Then each library can handle EPIPE errors as it sees fit. That
is what the Python runtime does, and what I expect the Algol runtime does
as well. (It might not, but this is certainly the most straightforward
way to go.)
Now what is a Python (or Algol) programmer using such a runtime supposed
to do if they are writing a program that wants to behave well as part of
a shell pipeline? In my own experience when writing tools in Python, I
have found there are two ways to go:
Sometimes I know that I won't be using any libraries that will need to
access the network. In that case I just reconfigure the Python runtime
back to the default Unix SIGPIPE behavior by initially calling
signal(SIGPIPE, SIG_DFL) myself. Of course, if I do this, there is a
danger that I will overlook some library that sometimes uses the network.
The alternative is to leave SIGPIPE as the runtime configured it, and
check for EPIPE every time I write to standard output. In Python that
means finding the right places to set up try/except blocks to handle BrokenPipeError exceptions. This is usually not that hard. Perhaps I
just define, and consistently use, a utility like:
def output(msg):
try:
return sys.stdout.write(msg)
except BrokenPipeError:
sys.exit(os.EX_OK)
You might think that a Python BrokenPipeError exception is just the
direct manifestation of an underlying Unix SIGPIPE signal, but that is
_not_ the case. A BrokenPipeError exception is only raised by the Python runtime when a call to the write() system call returns an EPIPE error
code. So in fact you can't get a BrokenPipeError unless SIGPIPE is
actually being ignored! Again, I expect that the Algol runtime is doing something similar.
--
Alan Bawden
--- Synchronet 3.21a-Linux NewsLink 1.2