| 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;
+}