Changeset 215620 in webkit for trunk/Source/JavaScriptCore/runtime/VMTraps.cpp
- Timestamp:
- Apr 21, 2017, 11:35:42 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/VMTraps.cpp
r215522 r215620 41 41 #include "Watchdog.h" 42 42 #include <wtf/ProcessID.h> 43 44 #if OS(DARWIN) 45 #include <signal.h> 46 #endif 43 #include <wtf/ThreadMessage.h> 44 #include <wtf/threads/Signals.h> 47 45 48 46 namespace JSC { … … 54 52 55 53 #if ENABLE(SIGNAL_BASED_VM_TRAPS) 56 57 struct sigaction originalSigusr1Action;58 struct sigaction originalSigtrapAction;59 54 60 55 struct SignalContext { … … 133 128 } 134 129 135 static void handleSigusr1(int signalNumber, siginfo_t* info, void* uap) 136 { 137 SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext); 138 auto activeVMAndStackBounds = findActiveVMAndStackBounds(context); 139 if (activeVMAndStackBounds) { 130 static void installSignalHandler() 131 { 132 installSignalHandler(Signal::Trap, [] (int, siginfo_t*, void* uap) -> SignalAction { 133 SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext); 134 135 if (!isJITPC(context.trapPC)) 136 return SignalAction::NotHandled; 137 138 // FIXME: This currently eats all traps including jit asserts we should make sure this 139 // always works. https://bugs.webkit.org/show_bug.cgi?id=171039 140 auto activeVMAndStackBounds = findActiveVMAndStackBounds(context); 141 if (!activeVMAndStackBounds) 142 return SignalAction::Handled; // Let the SignalSender try again later. 143 140 144 VM* vm = activeVMAndStackBounds.value().vm; 141 145 if (vm) { 142 StackBounds stackBounds = activeVMAndStackBounds.value().stackBounds;143 146 VMTraps& traps = vm->traps(); 144 if (traps.needTrapHandling()) 145 traps.tryInstallTrapBreakpoints(context, stackBounds); 146 } 147 } 148 149 auto originalAction = originalSigusr1Action.sa_sigaction; 150 if (originalAction) 151 originalAction(signalNumber, info, uap); 152 } 153 154 static void handleSigtrap(int signalNumber, siginfo_t* info, void* uap) 155 { 156 SignalContext context(static_cast<ucontext_t*>(uap)->uc_mcontext); 157 auto activeVMAndStackBounds = findActiveVMAndStackBounds(context); 158 if (!activeVMAndStackBounds) 159 return; // Let the SignalSender try again later. 160 161 VM* vm = activeVMAndStackBounds.value().vm; 162 if (vm) { 163 VMTraps& traps = vm->traps(); 164 if (!traps.needTrapHandling()) 165 return; // The polling code beat us to handling the trap already. 166 167 auto expectedSuccess = traps.tryJettisonCodeBlocksOnStack(context); 168 if (!expectedSuccess) 169 return; // Let the SignalSender try again later. 170 if (expectedSuccess.value()) 171 return; // We've success jettison the codeBlocks. 172 } 173 174 // If we get here, then this SIGTRAP is not due to a VMTrap. Let's do the default action. 175 auto originalAction = originalSigtrapAction.sa_sigaction; 176 if (originalAction) { 177 // It is always safe to just invoke the original handler using the sa_sigaction form 178 // without checking for the SA_SIGINFO flag. If the original handler is of the 179 // sa_handler form, it will just ignore the 2nd and 3rd arguments since sa_handler is a 180 // subset of sa_sigaction. This is what the man pages says the OS does anyway. 181 originalAction(signalNumber, info, uap); 182 } 183 184 // Pre-emptively restore the default handler but we may roll it back below. 185 struct sigaction currentAction; 186 struct sigaction defaultAction; 187 defaultAction.sa_handler = SIG_DFL; 188 sigfillset(&defaultAction.sa_mask); 189 defaultAction.sa_flags = 0; 190 sigaction(SIGTRAP, &defaultAction, ¤tAction); 191 192 if (currentAction.sa_sigaction != handleSigtrap) { 193 // This means that there's a client handler installed after us. This also means 194 // that the client handler thinks it was able to recover from the SIGTRAP, and 195 // did not uninstall itself. We can't argue with this because the signal isn't 196 // known to be from a VMTraps signal. Hence, restore the client handler 197 // and keep going. 198 sigaction(SIGTRAP, ¤tAction, nullptr); 199 } 200 } 201 202 static void installSignalHandlers() 203 { 204 typedef void (* SigactionHandler)(int, siginfo_t *, void *); 205 struct sigaction action; 206 207 action.sa_sigaction = reinterpret_cast<SigactionHandler>(handleSigusr1); 208 sigfillset(&action.sa_mask); 209 action.sa_flags = SA_SIGINFO; 210 sigaction(SIGUSR1, &action, &originalSigusr1Action); 211 212 action.sa_sigaction = reinterpret_cast<SigactionHandler>(handleSigtrap); 213 sigfillset(&action.sa_mask); 214 action.sa_flags = SA_SIGINFO; 215 sigaction(SIGTRAP, &action, &originalSigtrapAction); 147 if (!traps.needTrapHandling()) 148 return SignalAction::Handled; // The polling code beat us to handling the trap already. 149 150 auto expectedSuccess = traps.tryJettisonCodeBlocksOnStack(context); 151 if (!expectedSuccess) 152 return SignalAction::Handled; // Let the SignalSender try again later. 153 if (expectedSuccess.value()) 154 return SignalAction::Handled; // We've success jettison the codeBlocks. 155 } 156 157 return SignalAction::Handled; 158 }); 216 159 } 217 160 … … 401 344 static std::once_flag once; 402 345 std::call_once(once, [] { 403 installSignalHandler s();346 installSignalHandler(); 404 347 }); 405 348 } … … 461 404 auto optionalOwnerThread = vm.ownerThread(); 462 405 if (optionalOwnerThread) { 463 optionalOwnerThread.value()->signal(SIGUSR1); 406 sendMessage(*optionalOwnerThread.value().get(), [] (siginfo_t*, ucontext_t* ucontext) -> void { 407 SignalContext context(ucontext->uc_mcontext); 408 auto activeVMAndStackBounds = findActiveVMAndStackBounds(context); 409 if (activeVMAndStackBounds) { 410 VM* vm = activeVMAndStackBounds.value().vm; 411 if (vm) { 412 StackBounds stackBounds = activeVMAndStackBounds.value().stackBounds; 413 VMTraps& traps = vm->traps(); 414 if (traps.needTrapHandling()) 415 traps.tryInstallTrapBreakpoints(context, stackBounds); 416 } 417 } 418 }); 464 419 break; 465 420 }
Note:
See TracChangeset
for help on using the changeset viewer.