diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 26094fc62e7..c54007d8f38 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,7 @@ +2001-01-26 Andrew Haley + + (INIT_FPE): Use a direct system call to set the handler. + 2001-01-27 Richard Henderson * configure.host (alpha*-*) [libgcj_flags]: Add -mieee. diff --git a/libjava/include/i386-signal.h b/libjava/include/i386-signal.h index 599edc940ad..de2e39cdbc2 100644 --- a/libjava/include/i386-signal.h +++ b/libjava/include/i386-signal.h @@ -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 +#include #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 */