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