]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2001-01-26 Andrew Haley <aph@redhat.com>
authorAndrew Haley <aph@redhat.com>
Tue, 30 Jan 2001 21:00:22 +0000 (21:00 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Tue, 30 Jan 2001 21:00:22 +0000 (21:00 +0000)
        (INIT_FPE): Use a direct system call to set the handler.

From-SVN: r39354

libjava/ChangeLog
libjava/include/i386-signal.h

index 26094fc62e7b1e56b54aa6d8e1abdc3db7aa6619..c54007d8f3878e21ac95b0b3490ed5a95fb1b4c7 100644 (file)
@@ -1,3 +1,7 @@
+2001-01-26  Andrew Haley  <aph@redhat.com>
+
+       (INIT_FPE): Use a direct system call to set the handler.
+       
 2001-01-27  Richard Henderson  <rth@redhat.com>
 
        * configure.host (alpha*-*) [libgcj_flags]: Add -mieee.
index 599edc940ad7cf1ed84f624152819094531fc0f3..de2e39cdbc237a88d9936d9afa00ccda941590a1 100644 (file)
@@ -1,6 +1,6 @@
 // i386-signal.h - Catch runtime signals and turn them into exceptions.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -17,6 +17,7 @@ details.  */
 #define JAVA_SIGNAL_H 1
 
 #include <signal.h>
+#include <sys/syscall.h>
 
 #define HANDLE_SEGV 1
 #define HANDLE_FPE 1
@@ -140,9 +141,22 @@ do                                                         \
     act.sa_handler = catch_fpe;                                        \
     sigemptyset (&act.sa_mask);                                        \
     act.sa_flags = 0;                                          \
-    __sigaction (SIGFPE, &act, NULL);                          \
+    syscall (SYS_sigaction, SIGFPE, &act, NULL);               \
   }                                                            \
 while (0)  
 
+/* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
+ * instead of the standard sigaction().  This is necessary because of
+ * the shenanigans above where we increment the PC saved in the
+ * context and then return.  This trick will only work when we are
+ * called _directly_ by the kernel, because linuxthreads wraps signal
+ * handlers and its wrappers do not copy the sigcontext struct back
+ * when returning from a signal handler.  If we return from our divide
+ * handler to a linuxthreads wrapper, we will lose the PC adjustment
+ * we made and return to the faulting instruction again.  Using
+ * syscall(SYS_sigaction) causes our handler to be called directly by
+ * the kernel, bypassing any wrappers.  This is a kludge, and a future
+ * version of this handler will do something better.  */
+
 #endif /* JAVA_SIGNAL_H */