Stefan Kaltenbrunner <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers