Changeset 261538 in webkit
- Timestamp:
- May 11, 2020, 7:10:05 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r261504 r261538 1 2020-05-11 Mark Lam <mark.lam@apple.com> 2 3 Introduce WTF::Config and put Signal.cpp's init-once globals in it. 4 https://bugs.webkit.org/show_bug.cgi?id=211729 5 <rdar://problem/62938878> 6 7 Reviewed by Keith Miller and Saam Barati. 8 9 1. Initialize VMTraps' signals early now that we'll be freezing signals at the end 10 of the first VM initialization. 11 12 2. Move the !initializeThreadingHasBeenCalled RELEASE_ASSERT in initializeThreading() 13 to the bottom of the function. This way, we'll also catch bugs which may cause 14 us to jump into the middle of the function. 15 16 Added a compilerFence there to ensure that the RELEASE_ASSERT is only executed 17 after all initialization is done. This guarantees that it will only be executed 18 at the end. 19 20 3. Call WTF::Config::permanentlyFreeze() from JSC::Config::permanentlyFreeze() 21 for obvious reasons: freezing one should freeze the other. 22 23 * runtime/InitializeThreading.cpp: 24 (JSC::initializeThreading): 25 * runtime/JSCConfig.cpp: 26 (JSC::Config::permanentlyFreeze): 27 * runtime/VMTraps.cpp: 28 (JSC::VMTraps::initializeSignals): 29 * runtime/VMTraps.h: 30 1 31 2020-05-11 Keith Miller <keith_miller@apple.com> 2 32 -
trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp
r260165 r261538 1 1 /* 2 * Copyright (C) 2008-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2008-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 45 45 #include "StructureIDTable.h" 46 46 #include "SuperSampler.h" 47 #include "VMTraps.h" 47 48 #include "WasmCalleeRegistry.h" 48 49 #include "WasmCapabilities.h" … … 65 66 66 67 std::call_once(initializeThreadingOnceFlag, []{ 67 RELEASE_ASSERT(!g_jscConfig.initializeThreadingHasBeenCalled);68 g_jscConfig.initializeThreadingHasBeenCalled = true;69 70 68 WTF::initializeThreading(); 71 69 Options::initialize(); … … 106 104 WTF::startMachExceptionHandlerThread(); 107 105 #endif 106 VMTraps::initializeSignals(); 107 108 WTF::compilerFence(); 109 RELEASE_ASSERT(!g_jscConfig.initializeThreadingHasBeenCalled); 110 g_jscConfig.initializeThreadingHasBeenCalled = true; 108 111 }); 109 112 } -
trunk/Source/JavaScriptCore/runtime/JSCConfig.cpp
r260913 r261538 30 30 #include <wtf/ResourceUsage.h> 31 31 #include <wtf/StdLibExtras.h> 32 #include <wtf/WTFConfig.h> 32 33 33 34 #if OS(DARWIN) … … 55 56 void Config::permanentlyFreeze() 56 57 { 58 WTF::Config::permanentlyFreeze(); 59 57 60 static Lock configLock; 58 61 auto locker = holdLock(configLock); -
trunk/Source/JavaScriptCore/runtime/VMTraps.cpp
r260415 r261538 1 1 /* 2 * Copyright (C) 2017-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2017-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 199 199 : Base(locker, vm.traps().m_lock, vm.traps().m_condition.copyRef()) 200 200 , m_vm(vm) 201 { } 202 203 static void initializeSignals() 201 204 { 202 205 static std::once_flag once; … … 294 297 295 298 #endif // ENABLE(SIGNAL_BASED_VM_TRAPS) 299 300 void VMTraps::initializeSignals() 301 { 302 #if ENABLE(SIGNAL_BASED_VM_TRAPS) 303 if (!Options::usePollingTraps()) 304 SignalSender::initializeSignals(); 305 #endif 306 } 296 307 297 308 void VMTraps::willDestroyVM() -
trunk/Source/JavaScriptCore/runtime/VMTraps.h
r253613 r261538 1 1 /* 2 * Copyright (C) 2017-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2017-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 99 99 VMTraps(); 100 100 101 static void initializeSignals(); 102 101 103 void willDestroyVM(); 102 104 -
trunk/Source/WTF/ChangeLog
r261537 r261538 1 2020-05-11 Mark Lam <mark.lam@apple.com> 2 3 Introduce WTF::Config and put Signal.cpp's init-once globals in it. 4 https://bugs.webkit.org/show_bug.cgi?id=211729 5 <rdar://problem/62938878> 6 7 Reviewed by Keith Miller and Saam Barati. 8 9 1. Added WTF::Config for storing globals that effectively serve as constants i.e 10 we'll be initializing them before or during the first VM instantiation, but 11 should not have any reason to modify them later. The WTF::Config will be frozen 12 (along with JSC::Config) at the end of instantiating the first VM instance. 13 14 2. Added a Config::AssertNotFrozenScope RAII object to ensure that initialization 15 operations that should only be called at initialization time, will not be 16 called once the Config has been frozen. 17 18 3. Moved most of Signal.cpp's globals into WTF::Config. The only globals (or 19 statics) not moved are ones that cannot be moved because they require a 20 non-trivial default constructor (once_flag), or need to be modifiable 21 at runtime (e.g. Lock). 22 23 Instead of freezing the once_flag, we sanity check the call_once block with 24 the Config::AssertNotFrozenScope. 25 26 4. SignalHandler records are now allocated from arrays of SignalHandlerMemory in 27 the WTF::Config. The number of signal handlers we will ever install is always 28 finite. Hence, there's no reason to use a dynamic data structure like the 29 LocklessBag to hold it. 30 31 We introduce a SignalHandlers struct to manage these arrays (and all the other 32 Signal.cpp globals that we want to move to the WTF::Config). Amongst other 33 things, SignalHandlers provides the abstractions for: 34 35 a. allocating memory for the SignalHandler instances. See SignalHandlers::alloc(). 36 b. iterating SignalHandler instances. See SignalHandlers::forEachHandler(). 37 38 To maintain the synchronization properties of the LocklessBag, 39 SignalHandlers::alloc() uses a mutex. In practice, this mutex will never be 40 contended on because all signal handlers are now installed at initialization 41 time before any concurrency comes into play. 42 43 5. We now initialize activeThreads() eagerly via initializeThreading. In 44 production configurations, this does not matter because signal handler 45 installations will always trigger its initialization. However, in debugging 46 configurations, we may end up disabling the use of all signal handlers. As a 47 result, we need to do this eager initialization to ensure that it is done 48 before we freeze the WTF::Config. 49 50 * WTF.xcodeproj/project.pbxproj: 51 * wtf/CMakeLists.txt: 52 * wtf/Threading.cpp: 53 (WTF::initializeThreading): 54 * wtf/WTFConfig.cpp: Added. 55 (WTF::Config::disableFreezingForTesting): 56 (WTF::Config::permanentlyFreeze): 57 * wtf/WTFConfig.h: Added. 58 (WTF::Config::configureForTesting): 59 (WTF::Config::AssertNotFrozenScope::~AssertNotFrozenScope): 60 * wtf/threads/Signals.cpp: 61 (WTF::SignalHandlers::alloc): 62 (WTF::SignalHandlers::forEachHandler const): 63 (WTF::startMachExceptionHandlerThread): 64 (WTF::handleSignalsWithMach): 65 (WTF::setExceptionPorts): 66 (WTF::activeThreads): 67 (WTF::installSignalHandler): 68 (WTF::jscSignalHandler): 69 (WTF::SignalHandlers::initialize): 70 * wtf/threads/Signals.h: 71 1 72 2020-05-11 David Kilzer <ddkilzer@apple.com> 2 73 -
trunk/Source/WTF/WTF.xcodeproj/project.pbxproj
r261179 r261538 183 183 E4A0AD3D1A96253C00536DF6 /* WorkQueueCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A0AD3C1A96253C00536DF6 /* WorkQueueCocoa.cpp */; }; 184 184 EB61EDC72409CCC1001EFE36 /* SystemTracingCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB61EDC62409CCC0001EFE36 /* SystemTracingCocoa.cpp */; }; 185 FE032AD22463E43B0012D7C7 /* WTFConfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE032AD02463E43B0012D7C7 /* WTFConfig.cpp */; }; 185 186 FE05FAFF1FE5007500093230 /* WTFAssertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAFE1FE5007500093230 /* WTFAssertions.cpp */; }; 186 187 FE1E2C3B2240C06600F6B729 /* PtrTag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1E2C392240C05400F6B729 /* PtrTag.cpp */; }; … … 739 740 EF7D6CD59D8642A8A0DA86AD /* StackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackTrace.h; sourceTree = "<group>"; }; 740 741 F72BBDB107FA424886178B9E /* SymbolImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolImpl.cpp; sourceTree = "<group>"; }; 742 FE032AD02463E43B0012D7C7 /* WTFConfig.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WTFConfig.cpp; sourceTree = "<group>"; }; 743 FE032AD12463E43B0012D7C7 /* WTFConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFConfig.h; sourceTree = "<group>"; }; 741 744 FE05FAE61FDB214300093230 /* DumbPtrTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumbPtrTraits.h; sourceTree = "<group>"; }; 742 745 FE05FAFE1FE5007500093230 /* WTFAssertions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WTFAssertions.cpp; sourceTree = "<group>"; }; … … 1305 1308 E4A0AD381A96245500536DF6 /* WorkQueue.h */, 1306 1309 FE05FAFE1FE5007500093230 /* WTFAssertions.cpp */, 1310 FE032AD02463E43B0012D7C7 /* WTFConfig.cpp */, 1311 FE032AD12463E43B0012D7C7 /* WTFConfig.h */, 1307 1312 A36E16F7216FF828008DD87E /* WTFSemaphore.h */, 1308 1313 ); … … 1762 1767 7AFEC6B11EB22B5900DADE36 /* UUID.cpp in Sources */, 1763 1768 E3149A39228BB43500BFA6C7 /* Vector.cpp in Sources */, 1769 FE032AD22463E43B0012D7C7 /* WTFConfig.cpp in Sources */, 1764 1770 0F66B2921DC97BAB004A1D3F /* WallTime.cpp in Sources */, 1765 1771 1FA47C8A152502DA00568D1B /* WebCoreThread.cpp in Sources */, -
trunk/Source/WTF/wtf/CMakeLists.txt
r261179 r261538 285 285 VectorHash.h 286 286 VectorTraits.h 287 WTFConfig.h 287 288 WTFSemaphore.h 288 289 WallTime.h … … 446 447 Vector.cpp 447 448 WTFAssertions.cpp 449 WTFConfig.cpp 448 450 WallTime.cpp 449 451 WordLock.cpp -
trunk/Source/WTF/wtf/Threading.cpp
r261328 r261538 37 37 #include <wtf/ThreadMessage.h> 38 38 #include <wtf/ThreadingPrimitives.h> 39 #include <wtf/WTFConfig.h> 39 40 #include <wtf/text/AtomStringTable.h> 40 41 #include <wtf/text/StringView.h> 42 #include <wtf/threads/Signals.h> 41 43 42 44 #if HAVE(QOS_CLASSES) … … 361 363 static std::once_flag onceKey; 362 364 std::call_once(onceKey, [] { 365 Config::AssertNotFrozenScope assertScope; 363 366 initializeRandomNumberGenerator(); 364 367 #if !HAVE(FAST_TLS) && !OS(WINDOWS) … … 367 370 initializeDates(); 368 371 Thread::initializePlatformThreading(); 372 #if USE(PTHREADS) && HAVE(MACHINE_CONTEXT) 373 SignalHandlers::initialize(); 374 #endif 369 375 }); 370 376 } -
trunk/Source/WTF/wtf/threads/Signals.cpp
r260165 r261538 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 52 52 #include <wtf/ThreadMessage.h> 53 53 #include <wtf/Threading.h> 54 54 #include <wtf/WTFConfig.h> 55 55 56 56 namespace WTF { 57 57 58 59 static LazyNeverDestroyed<LocklessBag<SignalHandler>> handlers[static_cast<size_t>(Signal::NumberOfSignals)] = { }; 60 static std::once_flag initializeOnceFlags[static_cast<size_t>(Signal::NumberOfSignals)]; 61 static struct sigaction oldActions[static_cast<size_t>(Signal::NumberOfSignals)]; 58 void SignalHandlers::add(Signal signal, SignalHandler&& handler) 59 { 60 Config::AssertNotFrozenScope assertScope; 61 static Lock lock; 62 auto locker = holdLock(lock); 63 64 size_t signalIndex = static_cast<size_t>(signal); 65 size_t nextFree = numberOfHandlers[signalIndex]; 66 RELEASE_ASSERT(nextFree < maxNumberOfHandlers); 67 SignalHandlerMemory* memory = &handlers[signalIndex][nextFree]; 68 new (memory) SignalHandler(WTFMove(handler)); 69 70 // We deliberately do not want to increment the count until after we've 71 // fully initialized the memory. This way, forEachHandler() won't see a 72 // partially initialized handler. 73 storeStoreFence(); 74 numberOfHandlers[signalIndex]++; 75 loadLoadFence(); 76 } 77 78 template<typename Func> 79 inline void SignalHandlers::forEachHandler(Signal signal, const Func& func) const 80 { 81 size_t signalIndex = static_cast<size_t>(signal); 82 size_t handlerIndex = numberOfHandlers[signalIndex]; 83 while (handlerIndex--) { 84 auto* memory = const_cast<SignalHandlerMemory*>(&handlers[signalIndex][handlerIndex]); 85 const SignalHandler& handler = *bitwise_cast<SignalHandler*>(memory); 86 func(handler); 87 } 88 } 62 89 63 90 #if HAVE(MACH_EXCEPTIONS) … … 67 94 // http://www.cs.cmu.edu/afs/cs/project/mach/public/doc/unpublished/mig.ps 68 95 69 static mach_port_t exceptionPort;70 96 static constexpr size_t maxMessageSize = 1 * KB; 71 97 … … 74 100 static std::once_flag once; 75 101 std::call_once(once, [] { 76 kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exceptionPort); 102 Config::AssertNotFrozenScope assertScope; 103 SignalHandlers& handlers = g_wtfConfig.signalHandlers; 104 kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &handlers.exceptionPort); 77 105 RELEASE_ASSERT(kr == KERN_SUCCESS); 78 kr = mach_port_insert_right(mach_task_self(), exceptionPort,exceptionPort, MACH_MSG_TYPE_MAKE_SEND);106 kr = mach_port_insert_right(mach_task_self(), handlers.exceptionPort, handlers.exceptionPort, MACH_MSG_TYPE_MAKE_SEND); 79 107 RELEASE_ASSERT(kr == KERN_SUCCESS); 80 108 81 109 dispatch_source_t source = dispatch_source_create( 82 DISPATCH_SOURCE_TYPE_MACH_RECV, exceptionPort, 0, DISPATCH_TARGET_QUEUE_DEFAULT);110 DISPATCH_SOURCE_TYPE_MACH_RECV, handlers.exceptionPort, 0, DISPATCH_TARGET_QUEUE_DEFAULT); 83 111 RELEASE_ASSERT(source); 84 112 … … 87 115 88 116 kern_return_t kr = mach_msg_server_once( 89 mach_exc_server, maxMessageSize, exceptionPort, MACH_MSG_TIMEOUT_NONE);117 mach_exc_server, maxMessageSize, handlers.exceptionPort, MACH_MSG_TIMEOUT_NONE); 90 118 RELEASE_ASSERT(kr == KERN_SUCCESS); 91 119 }); … … 146 174 mach_msg_type_number_t* outStateCount) 147 175 { 148 RELEASE_ASSERT(port == exceptionPort); 176 SignalHandlers& handlers = g_wtfConfig.signalHandlers; 177 RELEASE_ASSERT(port == handlers.exceptionPort); 149 178 // If we wanted to distinguish between SIGBUS and SIGSEGV for EXC_BAD_ACCESS on Darwin we could do: 150 179 // if (exceptionData[0] == KERN_INVALID_ADDRESS) … … 179 208 180 209 bool didHandle = false; 181 handlers [static_cast<size_t>(signal)]->iterate([&] (const SignalHandler& handler) {210 handlers.forEachHandler(signal, [&] (const SignalHandler& handler) { 182 211 SignalAction handlerResult = handler(signal, info, registers); 183 212 didHandle |= handlerResult == SignalAction::Handled; … … 189 218 } 190 219 191 }; 192 193 static bool useMach { false }; 220 }; // extern "C" 221 194 222 void handleSignalsWithMach() 195 223 { 196 useMach = true; 197 } 198 199 200 exception_mask_t activeExceptions { 0 }; 224 Config::AssertNotFrozenScope assertScope; 225 g_wtfConfig.signalHandlers.useMach = true; 226 } 201 227 202 228 inline void setExceptionPorts(const AbstractLocker& threadGroupLocker, Thread& thread) 203 229 { 204 230 UNUSED_PARAM(threadGroupLocker); 205 kern_return_t result = thread_set_exception_ports(thread.machThread(), activeExceptions, exceptionPort, EXCEPTION_STATE | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE); 231 SignalHandlers& handlers = g_wtfConfig.signalHandlers; 232 kern_return_t result = thread_set_exception_ports(thread.machThread(), handlers.activeExceptions, handlers.exceptionPort, EXCEPTION_STATE | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE); 206 233 if (result != KERN_SUCCESS) { 207 234 dataLogLn("thread set port failed due to ", mach_error_string(result)); … … 215 242 static ThreadGroup* activeThreadsPtr = nullptr; 216 243 std::call_once(initializeKey, [&] { 244 Config::AssertNotFrozenScope assertScope; 217 245 static NeverDestroyed<std::shared_ptr<ThreadGroup>> activeThreads { ThreadGroup::create() }; 218 246 activeThreadsPtr = activeThreads.get().get(); … … 243 271 void installSignalHandler(Signal signal, SignalHandler&& handler) 244 272 { 273 Config::AssertNotFrozenScope assertScope; 274 SignalHandlers& handlers = g_wtfConfig.signalHandlers; 245 275 ASSERT(signal < Signal::Unknown); 246 276 #if HAVE(MACH_EXCEPTIONS) 247 ASSERT(! useMach || signal != Signal::Usr);248 249 if ( useMach)277 ASSERT(!handlers.useMach || signal != Signal::Usr); 278 279 if (handlers.useMach) 250 280 startMachExceptionHandlerThread(); 251 281 #endif 252 282 283 static std::once_flag initializeOnceFlags[static_cast<size_t>(Signal::NumberOfSignals)]; 253 284 std::call_once(initializeOnceFlags[static_cast<size_t>(signal)], [&] { 254 handlers[static_cast<size_t>(signal)].construct(); 255 285 Config::AssertNotFrozenScope assertScope; 286 #if HAVE(MACH_EXCEPTIONS) 287 bool useMach = handlers.useMach; 288 #endif 256 289 if (!useMach) { 257 290 struct sigaction action; … … 264 297 action.sa_flags = SA_SIGINFO; 265 298 auto systemSignals = toSystemSignal(signal); 266 result = sigaction(std::get<0>(systemSignals), &action, & oldActions[offsetForSystemSignal(std::get<0>(systemSignals))]);299 result = sigaction(std::get<0>(systemSignals), &action, &handlers.oldActions[offsetForSystemSignal(std::get<0>(systemSignals))]); 267 300 if (std::get<1>(systemSignals)) 268 result |= sigaction(*std::get<1>(systemSignals), &action, & oldActions[offsetForSystemSignal(*std::get<1>(systemSignals))]);301 result |= sigaction(*std::get<1>(systemSignals), &action, &handlers.oldActions[offsetForSystemSignal(*std::get<1>(systemSignals))]); 269 302 RELEASE_ASSERT(!result); 270 303 } 271 272 }); 273 274 handlers[static_cast<size_t>(signal)]->add(WTFMove(handler)); 304 }); 305 306 handlers.add(signal, WTFMove(handler)); 275 307 276 308 #if HAVE(MACH_EXCEPTIONS) 277 309 auto locker = holdLock(activeThreads().getLock()); 278 if ( useMach) {279 activeExceptions |= toMachMask(signal);310 if (handlers.useMach) { 311 handlers.activeExceptions |= toMachMask(signal); 280 312 281 313 for (auto& thread : activeThreads().threads(locker)) … … 288 320 { 289 321 Signal signal = fromSystemSignal(sig); 322 SignalHandlers& handlers = g_wtfConfig.signalHandlers; 290 323 291 324 auto restoreDefault = [&] { … … 300 333 // This shouldn't happen but we might as well be careful. 301 334 if (signal == Signal::Unknown) { 302 dataLogLn("We somehow got called for an unknown signal ", sig, ", h alp.");335 dataLogLn("We somehow got called for an unknown signal ", sig, ", help."); 303 336 restoreDefault(); 304 337 return; … … 313 346 bool didHandle = false; 314 347 bool restoreDefaultHandler = false; 315 handlers [static_cast<size_t>(signal)]->iterate([&] (const SignalHandler& handler) {348 handlers.forEachHandler(signal, [&] (const SignalHandler& handler) { 316 349 switch (handler(signal, sigInfo, registers)) { 317 350 case SignalAction::Handled: … … 332 365 333 366 unsigned oldActionIndex = static_cast<size_t>(signal) + (sig == SIGBUS); 334 struct sigaction& oldAction = oldActions[static_cast<size_t>(oldActionIndex)];367 struct sigaction& oldAction = handlers.oldActions[static_cast<size_t>(oldActionIndex)]; 335 368 if (signal == Signal::Usr) { 336 369 if (oldAction.sa_sigaction) … … 350 383 } 351 384 385 void SignalHandlers::initialize() 386 { 387 #if HAVE(MACH_EXCEPTIONS) 388 // In production configurations, this does not matter because signal handler 389 // installations will always trigger this initialization. However, in debugging 390 // configurations, we may end up disabling the use of all signal handlers but 391 // we still need this to be initialized. Hence, we need to initialize it 392 // eagerly to ensure that it is done before we freeze the WTF::Config. 393 activeThreads(); 394 #endif 395 } 396 352 397 } // namespace WTF 353 398 -
trunk/Source/WTF/wtf/threads/Signals.h
r260165 r261538 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 31 31 #include <tuple> 32 32 #include <wtf/Function.h> 33 #include <wtf/Lock.h> 33 34 #include <wtf/Optional.h> 34 35 #include <wtf/PlatformRegisters.h> 36 37 #if HAVE(MACH_EXCEPTIONS) 38 #include <mach/exception_types.h> 39 #endif 35 40 36 41 namespace WTF { … … 83 88 84 89 using SignalHandler = Function<SignalAction(Signal, SigInfo&, PlatformRegisters&)>; 90 using SignalHandlerMemory = std::aligned_storage<sizeof(SignalHandler), std::alignment_of<SignalHandler>::value>::type; 85 91 86 // Call this method whenever you want to install a signal handler. It's ok to call this function lazily. 92 struct SignalHandlers { 93 static void initialize(); 94 95 void add(Signal, SignalHandler&&); 96 template<typename Func> 97 void forEachHandler(Signal, const Func&) const; 98 99 static constexpr size_t numberOfSignals = static_cast<size_t>(Signal::NumberOfSignals); 100 static constexpr size_t maxNumberOfHandlers = 2; 101 102 static_assert(numberOfSignals < std::numeric_limits<uint8_t>::max()); 103 104 #if HAVE(MACH_EXCEPTIONS) 105 mach_port_t exceptionPort; 106 exception_mask_t activeExceptions; 107 bool useMach; 108 #endif 109 uint8_t numberOfHandlers[numberOfSignals]; 110 SignalHandlerMemory handlers[numberOfSignals][maxNumberOfHandlers]; 111 struct sigaction oldActions[numberOfSignals]; 112 }; 113 114 // Call this method whenever you want to install a signal handler. This function needs to be called 115 // before g_wtfConfig is frozen. After the g_wtfConfig is frozen, no additional signal handlers may 116 // be installed. Any attempt to do so will trigger a crash. 87 117 // Note: Your signal handler will be called every time the handler for the desired signal is called. 88 118 // Thus it is your responsibility to discern if the signal fired was yours. 89 // This function is currentlya one way street i.e. once installed, a signal handler cannot be uninstalled.119 // This function is a one way street i.e. once installed, a signal handler cannot be uninstalled. 90 120 WTF_EXPORT_PRIVATE void installSignalHandler(Signal, SignalHandler&&); 91 121
Note:
See TracChangeset
for help on using the changeset viewer.