SIGPIPE in the GHC runtime

Brian Bloniarz brian.bloniarz at gmail.com
Wed Aug 18 17:56:23 EDT 2010


On 08/18/2010 04:55 PM, Donn Cave wrote:
> Quoth Brian Bloniarz <brian.bloniarz at gmail.com>,
> 
>> IMHO the simplest fix is the patch below: simply
>> avoid SIG_IGN, instead install a handler which does nothing.
>> This way, an exec() restores the handler to SIG_DFL. I've
>> included a testcase too.
> 
> I don't know enough to make a case for or against this, but the
> side effects are different:  whether the handler does anything
> or not, it will interrupt some system calls.  Since there are
> already may be a regular barrage of SIGALRMs from the GHC runtime,
> maybe one more such interruption can't hurt anything ...  but
> note that we recently heard from someone in Australia with a
> problem on OpenSolaris where evidently these SIGALRMs were in
> fact interrupting hGetContents from a pipe, and no one seemed
> to have any notion why.

Shouldn't enabling SA_RESTART be enough to restart the syscall?
I don't know all the Unices enough to guarantee that it'd be 
transparent, but I hope it should be. I see the SIGALRM
code uses SA_RESTART too, though judging by the #ifdefs in
Itimer.c, SA_RESTART must not be available everywhere.

Note that unlike SIGALRM, the SIGPIPE will be sent to the thread
which caused it (i.e. the caller of write()), not any other thread.
So any possible damage would be limited to the calling thread.

> At any rate, the affected system calls would set EAGAIN, possibly
> including the write(2) that's supposed to set EPIPE (though
> I think that would be an unusual implementation.)

I just tested linux in this scenario, it gives EPIPE as I'd expect.
Linux's SA_RESTART has been reliable in my limited experience. Do
you have an OpenSolaris install to test by any chance? The code is
below.

#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int count = 0;
void handler(int sig)
{
    ++count;
}

int main()
{
    int fd[2];
    struct sigaction act;

    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_RESTART;
    sigaction(SIGPIPE, &act, NULL);

    pipe(fd);
    close(fd[0]);
    int arg = 0;
    int e = write(fd[1], &arg, sizeof(arg));

    printf("count:%d, ret:%d, errno:%d was_epipe:%d\n", count, e, errno, errno == EPIPE);
    return 0;
}


More information about the Glasgow-haskell-users mailing list