Bill Allombert on Wed, 02 Nov 2005 18:08:33 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: GP handling of SIGINT (Linux) |
On Mon, May 16, 2005 at 11:01:02AM +0200, Bill Allombert wrote: > On Mon, Apr 18, 2005 at 01:33:23PM +0200, Jeroen Demeyer wrote: > > After reading carefully the glibc documentation and the code, it looks > like the code was made for System V, and should also work on BSD but > not on Linux... > > 1) gp_sighandler start by doing > (void)os_signal(sig,gp_sighandler); > > This is a SYSV idiom: SYSV reset the signal handler to SIG_DFL when > calling the handler, so this line reinstate the gphandler. > > BSD and POSIX instead does not change the handler, but block the signal > (see sigprocmask). However BSD longjmp will restore the set of blocked > signals, so will unblock it, but not Linux longjmp, you have to use > sigsetjmp/siglongjmp (which are slower). (POSIX itself allows both > behaviour). > > One solution is to use sigsetjmp/siglongjmp and this seems to fix the > problem, but I don't think this is the best solution because sigsetjmp > is slower than setjmp. I think it is cleaner to use sigaction to set up > the signal handling to behave the way we like. > > > A very ugly hack around this is to change this default. I have done > > this in attached patch. I can only say it fixes my problem, but it > > could very well break things. The behaviour is also likely to be > > OS-dependent. > > I am not sure it is a "very ugly hack". I think you are very close > to a correct fix to the problem. signal(2) is deprecated in favour > sigaction anyway. Indeed, here a patch that add support for sigaction when available. This avoid portability problems of signal(). This patch is strongly based on your patch, Jeroen, thanks a lot! Cheers, Bill.
Index: config/get_libc =================================================================== RCS file: /home/cvs/pari/config/get_libc,v retrieving revision 1.8 diff -u -r1.8 get_libc --- config/get_libc 6 Jun 2005 13:55:10 -0000 1.8 +++ config/get_libc 2 Nov 2005 16:14:05 -0000 @@ -13,7 +13,7 @@ *cygwin*) list='times ftime';; # getrusage based timer always returns 0 *) list='getrusage times ftime';; esac; . ./look -list='sigsetmask sigrelse'; . ./look +list='sigaction sigsetmask sigrelse'; . ./look list=TIOCGWINSZ; . ./look list=getrlimit; . ./look list='stat opendir'; . ./look Index: config/paricfg.h.SH =================================================================== RCS file: /home/cvs/pari/config/paricfg.h.SH,v retrieving revision 1.24 diff -u -r1.24 paricfg.h.SH --- config/paricfg.h.SH 6 Jun 2005 13:55:10 -0000 1.24 +++ config/paricfg.h.SH 2 Nov 2005 16:14:05 -0000 @@ -160,6 +160,10 @@ esac;; esac +case $has_sigaction in +yes) echo '#define HAS_SIGACTION' >> $file;; +esac + case "$has_sigrelse" in yes) echo '#define USE_SIGRELSE 1' >> $file;; *) case "$has_sigsetmask" in Index: src/language/es.c =================================================================== RCS file: /home/cvs/pari/src/language/es.c,v retrieving revision 1.206 diff -u -r1.206 es.c --- src/language/es.c 29 Oct 2005 13:59:26 -0000 1.206 +++ src/language/es.c 2 Nov 2005 16:14:05 -0000 @@ -2809,11 +2809,21 @@ close(fd); #endif } +typedef void (*pari_sighandler_t)(int); -void -(*os_signal(int sig, void (*f)(int)))(int) +pari_sighandler_t +os_signal(int sig, pari_sighandler_t f) { -#ifdef WINCE +#ifdef HAS_SIGACTION + struct sigaction sa, oldsa; + + sa.sa_handler = f; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NODEFER; + + if (sigaction(sig, &sa, &oldsa)) return NULL; + return oldsa.sa_handler; +#elif defined(WINCE) return SIG_IGN; #else return signal(sig,f); Index: src/language/init.c =================================================================== RCS file: /home/cvs/pari/src/language/init.c,v retrieving revision 1.274 diff -u -r1.274 init.c --- src/language/init.c 29 Oct 2005 13:40:01 -0000 1.274 +++ src/language/init.c 2 Nov 2005 16:14:05 -0000 @@ -312,7 +312,10 @@ pari_sighandler(int sig) { char *msg; +#ifndef HAS_SIGACTION + /*SYSV reset the signal handler in the handler*/ (void)os_signal(sig,pari_sighandler); +#endif switch(sig) { #ifdef SIGBREAK --- /dev/null Sat Mar 1 19:52:54 2003 +++ config/has_sigaction.c Wed Nov 2 16:59:16 2005 @@ -0,0 +1,12 @@ +#include <signal.h> +main() +{ + struct sigaction sa, oldsa; + + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NODEFER; + + (void)(sigaction(SIGINT, &sa, &oldsa)); + return 0; +}