vmError_posix.cpp revision 9593:ca793dd85e06
1/*
2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "runtime/arguments.hpp"
27#include "runtime/os.hpp"
28#include "runtime/thread.hpp"
29#include "utilities/vmError.hpp"
30
31#include <sys/types.h>
32#include <sys/wait.h>
33#include <signal.h>
34
35#ifdef TARGET_OS_FAMILY_linux
36#include <sys/syscall.h>
37#include <unistd.h>
38#endif
39#ifdef TARGET_OS_FAMILY_solaris
40#include <thread.h>
41#endif
42#ifdef TARGET_OS_FAMILY_aix
43#include <unistd.h>
44#endif
45#ifdef TARGET_OS_FAMILY_bsd
46#include <sys/syscall.h>
47#include <unistd.h>
48#endif
49
50
51// handle all synchronous program error signals which may happen during error
52// reporting. They must be unblocked, caught, handled.
53
54static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
55static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
56
57// Space for our "saved" signal flags and handlers
58static int resettedSigflags[NUM_SIGNALS];
59static address resettedSighandler[NUM_SIGNALS];
60
61static void save_signal(int idx, int sig)
62{
63  struct sigaction sa;
64  sigaction(sig, NULL, &sa);
65  resettedSigflags[idx]   = sa.sa_flags;
66  resettedSighandler[idx] = (sa.sa_flags & SA_SIGINFO)
67                              ? CAST_FROM_FN_PTR(address, sa.sa_sigaction)
68                              : CAST_FROM_FN_PTR(address, sa.sa_handler);
69}
70
71int VMError::get_resetted_sigflags(int sig) {
72  for (int i = 0; i < NUM_SIGNALS; i++) {
73    if (SIGNALS[i] == sig) {
74      return resettedSigflags[i];
75    }
76  }
77  return -1;
78}
79
80address VMError::get_resetted_sighandler(int sig) {
81  for (int i = 0; i < NUM_SIGNALS; i++) {
82    if (SIGNALS[i] == sig) {
83      return resettedSighandler[i];
84    }
85  }
86  return NULL;
87}
88
89static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
90  // unmask current signal
91  sigset_t newset;
92  sigemptyset(&newset);
93  sigaddset(&newset, sig);
94  // also unmask other synchronous signals
95  for (int i = 0; i < NUM_SIGNALS; i++) {
96    sigaddset(&newset, SIGNALS[i]);
97  }
98  os::Posix::unblock_thread_signal_mask(&newset);
99
100  // support safefetch faults in error handling
101  ucontext_t* const uc = (ucontext_t*) ucVoid;
102  address const pc = uc ? os::Posix::ucontext_get_pc(uc) : NULL;
103
104  if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
105    os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
106    return;
107  }
108
109  VMError::report_and_die(NULL, sig, pc, info, ucVoid);
110}
111
112void VMError::reset_signal_handlers() {
113  // install signal handlers for all synchronous program error signals
114  sigset_t newset;
115  sigemptyset(&newset);
116
117  for (int i = 0; i < NUM_SIGNALS; i++) {
118    save_signal(i, SIGNALS[i]);
119    os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
120    sigaddset(&newset, SIGNALS[i]);
121  }
122  os::Posix::unblock_thread_signal_mask(&newset);
123
124}
125