/* src/vm/signal.c - machine independent signal functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: signal.c 8370 2007-08-20 21:44:10Z twisti $
-
*/
#include "config.h"
#include <assert.h>
-#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
/* If we compile with -ansi on darwin, <sys/types.h> is not
included. So let's do it here. */
# include <sys/types.h>
+# include <sys/utsname.h>
#endif
#include "arch.h"
-#include "mm/memory.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/threads-common.h"
-#else
-# include "threads/none/threads.h"
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/memory.h"
#endif
-#include "toolbox/logging.h"
+#include "threads/thread.hpp"
+#include "threads/threadlist.hpp"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/method.hpp"
+#include "vm/options.h"
#include "vm/signallocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/patcher-common.h"
-
-#include "vmcore/options.h"
+#include "vm/vm.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
#if !defined(__CYGWIN__)
sigset_t mask;
+ TRACESUBSYSTEMINITIALIZATION("signal_init");
+
#if defined(__LINUX__) && defined(ENABLE_THREADS)
/* XXX Remove for exact-GC. */
if (threads_pthreads_implementation_nptl) {
this thread. */
if (sigemptyset(&mask) != 0)
- vm_abort("signal_init: sigemptyset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigemptyset failed");
-#if !defined(WITH_CLASSPATH_SUN)
+#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
/* Let OpenJDK handle SIGINT itself. */
if (sigaddset(&mask, SIGINT) != 0)
- vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigaddset failed");
#endif
#if !defined(__FREEBSD__)
if (sigaddset(&mask, SIGQUIT) != 0)
- vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigaddset failed");
#endif
if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
- vm_abort("signal_init: sigprocmask failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigprocmask failed");
#if defined(__LINUX__) && defined(ENABLE_THREADS)
/* XXX Remove for exact-GC. */
SA_NODEFER | SA_SIGINFO);
# endif
-# if defined(__ARM__) || defined(__S390__)
+# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
/* XXX use better defines for that (in arch.h) */
/* SIGILL handler */
# if defined(ENABLE_INTRP)
}
# endif
-#endif /* !defined(ENABLE_INTRP) */
+
+#if defined(__DARWIN__)
+ do {
+ struct utsname name;
+ kern_return_t kr;
+
+ /* Check if we're on 10.4 (Tiger/8.x) or earlier */
+ if (uname(&name) != 0)
+ break;
+
+ /* Make sure the string is large enough */
+ /* Check the major number (ascii comparison) */
+ /* Verify that we're not looking at '10.' by checking for a trailing period. */
+ if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.')
+ break;
+
+ /* Reset CrashReporter's task signal handler */
+ kr = task_set_exception_ports(mach_task_self(),
+ EXC_MASK_BAD_ACCESS
+# if defined(__I386__)
+ | EXC_MASK_BAD_INSTRUCTION
+#endif
+ , MACH_PORT_NULL,
+ EXCEPTION_STATE_IDENTITY,
+ MACHINE_THREAD_STATE);
+
+ assert(kr == KERN_SUCCESS);
+ } while (false);
+#endif
+#endif /* !defined(ENABLE_JIT) */
#if defined(ENABLE_THREADS)
/* SIGHUP handler for threads_thread_interrupt */
- signal_register_signal(SIGHUP, (functionptr) signal_handler_sighup, 0);
+ signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0);
+#endif
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+ /* SIGUSR1 handler for the exact GC to suspend threads */
+
+ signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1,
+ SA_SIGINFO);
#endif
#if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING)
function = (void (*)(int, siginfo_t *, void *)) handler;
if (sigemptyset(&act.sa_mask) != 0)
- vm_abort("signal_register_signal: sigemptyset failed: %s",
- strerror(errno));
+ vm_abort_errno("signal_register_signal: sigemptyset failed");
act.sa_sigaction = function;
act.sa_flags = flags;
if (sigaction(signum, &act, NULL) != 0)
- vm_abort("signal_register_signal: sigaction failed: %s",
- strerror(errno));
-}
-
-
-/* signal_handle ***************************************************************
-
- Handles the signal caught by a signal handler and calls the correct
- function.
-
-*******************************************************************************/
-
-void *signal_handle(void *xpc, int type, intptr_t val)
-{
- void *p;
- int32_t index;
- java_object_t *o;
-
- switch (type) {
- case EXCEPTION_HARDWARE_NULLPOINTER:
- p = exceptions_new_nullpointerexception();
- break;
-
- case EXCEPTION_HARDWARE_ARITHMETIC:
- p = exceptions_new_arithmeticexception();
- break;
-
- case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
- index = (s4) val;
- p = exceptions_new_arrayindexoutofboundsexception(index);
- break;
-
- case EXCEPTION_HARDWARE_CLASSCAST:
- o = (java_object_t *) val;
- p = exceptions_new_classcastexception(o);
- break;
-
- case EXCEPTION_HARDWARE_EXCEPTION:
- p = exceptions_fillinstacktrace();
- break;
-
- case EXCEPTION_HARDWARE_PATCHER:
-#if defined(ENABLE_REPLACEMENT)
- if (replace_me_wrapper(xpc)) {
- p = NULL;
- break;
- }
-#endif
- p = patcher_handler(xpc);
- break;
-
- default:
- /* Let's try to get a backtrace. */
-
- codegen_get_pv_from_pc(xpc);
-
- /* If that does not work, print more debug info. */
-
- log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
-
-#if SIZEOF_VOID_P == 8
- log_println("PC=0x%016lx", xpc);
-#else
- log_println("PC=0x%08x", xpc);
-#endif
-
-#if defined(ENABLE_DISASSEMBLER)
- log_println("machine instruction at PC:");
- disassinstr(xpc);
-#endif
-
- vm_abort("Exiting...");
-
- /* keep compiler happy */
-
- p = NULL;
- }
-
- return p;
+ vm_abort_errno("signal_register_signal: sigaction failed");
}
threadobject *t;
sigset_t mask;
int sig;
+ int result;
t = THREADOBJECT;
if (sigemptyset(&mask) != 0)
- vm_abort("signal_thread: sigemptyset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigemptyset failed");
-#if !defined(WITH_CLASSPATH_SUN)
+#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
/* Let OpenJDK handle SIGINT itself. */
if (sigaddset(&mask, SIGINT) != 0)
- vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigaddset failed");
#endif
#if !defined(__FREEBSD__)
if (sigaddset(&mask, SIGQUIT) != 0)
- vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigaddset failed");
#endif
for (;;) {
/* just wait for a signal */
#if defined(ENABLE_THREADS)
- threads_thread_state_waiting(t);
+ thread_set_state_waiting(t);
#endif
- /* XXX We don't check for an error here, although the man-page
- states sigwait does not return an error (which is wrong!),
- but it seems to make problems with Boehm-GC. We should
- revisit this code with our new exact-GC. */
+ // sigwait can return EINTR (unlike what the Linux man-page
+ // says).
+ do {
+ result = sigwait(&mask, &sig);
+ } while (result == EINTR);
-/* if (sigwait(&mask, &sig) != 0) */
-/* vm_abort("signal_thread: sigwait failed: %s", strerror(errno)); */
- (void) sigwait(&mask, &sig);
+ if (result != 0)
+ vm_abort_errnum(result, "signal_thread: sigwait failed");
#if defined(ENABLE_THREADS)
- threads_thread_state_runnable(t);
+ thread_set_state_runnable(t);
#endif
/* Handle the signal. */
case SIGINT:
/* exit the vm properly */
- vm_exit(0);
+ vm_exit(1);
break;
case SIGQUIT:
/* print a thread dump */
#if defined(ENABLE_THREADS)
- threads_dump();
+ ThreadList_dump_threads();
#endif
#if defined(ENABLE_STATISTICS)
statistics_print_memory_usage();
#endif
break;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ default: {
+ // For OpenJDK we dispatch all unknown signals to Java.
+ methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void);
+ (void) vm_call_method(m, NULL, sig);
+
+ if (exceptions_get_exception()) {
+ log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig);
+ exceptions_print_stacktrace();
+ vm_abort("signal_thread_handler: Aborting...");
+ }
+ break;
+ }
+#else
+ default:
+ vm_abort("signal_thread_handler: Unknown signal %d", sig);
+#endif
}
}