Stefan Kaltenbrunner <ste...@kaltenbrunner.cc> writes:
> On 04/03/2013 12:59 AM, Tom Lane wrote:
>> BTW, on further thought it seems like maybe this is an OpenBSD bug,
>> at least in part: what is evidently happening is that the temporary
>> blockage of SIGINT during the handler persists even after we've
>> longjmp'd back to the main loop.  But we're using sigsetjmp(..., 1)
>> to establish that longjmp handler --- so why isn't the original signal
>> mask reinstalled when we return to the main loop?
>> 
>> If (your version of) OpenBSD is getting this wrong, it'd explain why
>> we've not seen similar behavior elsewhere.

> hmm trolling the openbsd cvs history brings up this:
> http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/sparc64/sparc64/machdep.c?r1=1.143;sortby=date#rev1.143

That's about alternate signal stacks, which we're not using.

I put together a simple test program (attached) and tried it on
spoonbill, and it says that the signal *does* get unblocked when control
returns to the sigsetjmp(...,1).  So now I'm really confused.  Somehow
the results we're getting in a full-fledged backend do not match up with
the results gotten by this test program ... but why?

                        regards, tom lane

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <setjmp.h>

typedef void (*pqsigfunc) (int signo);

sigjmp_buf *PG_exception_stack;

static void
printmask(const char *labl)
{
        sigset_t sigs;
        int i;

        printf("masked signals at %s: ", labl);
        if (sigprocmask(SIG_SETMASK, NULL, &sigs) == 0)
        {
                for (i = 1; i <= 32; i++)
                {
//                      if (sigs.sigset[0] & sigmask(i))
                        if (sigs & sigmask(i))
                                printf("%d, ", i);
                }
        }
        else
                printf("failed!");
        printf("\n");
        fflush(stdout);
}

static void
sigint_handler(int signo)
{
        printmask("sigint_handler");
        siglongjmp(*PG_exception_stack, 1);
        abort();
}

static pqsigfunc
pqsignal(int signo, pqsigfunc func)
{
        struct sigaction act,
                                oact;

        act.sa_handler = func;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        if (signo != SIGALRM)
                act.sa_flags |= SA_RESTART;
#ifdef SA_NOCLDSTOP
        if (signo == SIGCHLD)
                act.sa_flags |= SA_NOCLDSTOP;
#endif
        if (sigaction(signo, &act, &oact) < 0)
                return SIG_ERR;
        return oact.sa_handler;
}

void
intermediate_func(int level)
{
        do {
                sigjmp_buf *save_exception_stack = PG_exception_stack;
                sigjmp_buf local_sigjmp_buf;

                if (sigsetjmp(local_sigjmp_buf, 0) == 0)
                {
                        PG_exception_stack = &local_sigjmp_buf;

                        if (level > 0)
                                intermediate_func(level - 1);
                        else
                        {
                                kill(getpid(), SIGINT);
                                sleep(1);
                                abort();
                        }
                }
                else
                {
                        PG_exception_stack = save_exception_stack;

                        printmask("inner longjmp catcher");
                        siglongjmp(*PG_exception_stack, 1);
                        abort();
                }
                PG_exception_stack = save_exception_stack;
        } while (0);
}

int
main(int argc, char **argv)
{
        sigjmp_buf      outer_sigjmp_buf;

        printmask("startup");
        pqsignal(SIGINT, sigint_handler);

        if (sigsetjmp(outer_sigjmp_buf, 1) != 0)
        {
                printmask("outer longjmp catcher");
                return 0;
        }
        PG_exception_stack = &outer_sigjmp_buf;

        intermediate_func(2);

        printmask("unexpected exit");
        return 0;
}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to