4 ms·
This (signal) is the de-facto communication mechanism to notify a program that an unexpected event just occurred (typically, a SEGV). This mechanism needs to in
by xroche 10y ago
This (signal) is the de-facto communication mechanism to notify a program that an unexpected event just occurred (typically, a SEGV). This mechanism needs to interrupt the normal program flow (because you can not restart an invalid access most of the time), possibly interrupting a C-library call (such as malloc, reason why malloc is not async-signal-safe generally). What would you do instead ? On Windows systems, there is a built-in "__try / __except" mechanism ("structured exception handling", SEH), which provides exception-like catch in plain C with proprietary extension to C. This is probably not such a better method.
- trentnelson 10y ago> This is probably not such a better method. It actually really, really is. At least from a technical perspective on x64. Having language-level lexical scoping of system-level exceptions is incredibly useful and once you've grokked how NT's trap handler, PE .xdata sections, prologues and epilogues all work in concert, signals just seem barbaric. Here's an example trapping an access violation: // // Prefault the page. // TRY_MAPPED_MEMORY_OP { TraceStore->Rtl->PrefaultPages(PrefaultMemoryMap->NextAddress, 1); } CATCH_EXCEPTION_ACCESS_VIOLATION { // // This will happen if servicing the prefault off-core has taken longer // for the originating core (the one that submitted the prefault work) // to consume the entire memory map, then *another* memory map, which // will retire the memory map backing this prefault address, which // results in the address being invalidated, which results in an access // violation when we try and read/prefault it from the thread pool. // TraceStore->Stats->AccessViolationsEncounteredDuringAsyncPrefault++; } Or an alignment fault: FORCEINLINE VOID StoreXmm( _In_ XMMWORD *Destination, _In_ XMMWORD Source ) { TRY_SSE42_ALIGNED { _mm_store_si128(Destination, Source); } CATCH_EXCEPTION_ACCESS_VIOLATION { _mm_storeu_si128(Destination, Source); } } Or an illegal instruction: FORCEINLINE VOID StoreYmmFallbackXmm( _In_ PYMMWORD Destination, _In_ PXMMWORD Destination128Low, _In_ PXMMWORD Destination128High, _In_ YMMWORD Source, _In_ XMMWORD Source128Low, _In_ XMMWORD Source128High ) { TRY_AVX { TRY_AVX_ALIGNED { _mm256_store_si256(Destination, Source); } CATCH_EXCEPTION_ILLEGAL_INSTRUCTION { Store2Xmm( Destination128Low, Destination128High, Source128Low, Source128High ); } } CATCH_EXCEPTION_ACCESS_VIOLATION { _mm256_storeu_si256(Destination, Source); } Or a page fault that has occurred against a memory map backed file (because, say, the underlying network drive has been disconnected): TRY_MAPPED_MEMORY_OP { // // Copy the caller's address range structure over. // __movsq((PDWORD64)NewAddressRange, (PDWORD64)AddressRange, sizeof(*NewAddressRange) >> 3); // // If there's an existing address range set, update its ValidTo // timestamp. // if (TraceStore->AddressRange) { TraceStore->AddressRange->Timestamp.ValidTo.QuadPart = ( Timestamp.QuadPart ); } // // Update the trace store's address range pointer. // TraceStore->AddressRange = NewAddressRange; } CATCH_STATUS_IN_PAGE_ERROR { // // We'll leak the address range we just allocated here, but a copy // failure is indicative of much bigger issues (drive full, network // map disappearing) than leaking ~32 bytes, so we don't attempt to // roll back the allocation. // return FALSE; } Relevant macro definitions: #define TRY_AVX __try #define TRY_AVX_ALIGNED __try #define TRY_AVX_UNALIGNED __try #define TRY_SSE42 __try #define TRY_SSE42_ALIGNED __try #define TRY_SSE42_UNALIGNED __try #define TRY_MAPPED_MEMORY_OP __try #define CATCH_EXCEPTION_ILLEGAL_INSTRUCTION __except( \ GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ? \ EXCEPTION_EXECUTE_HANDLER : \ EXCEPTION_CONTINUE_SEARCH \ ) #define CATCH_EXCEPTION_ACCESS_VIOLATION __except( \ GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? \ EXCEPTION_EXECUTE_HANDLER : \ EXCEPTION_CONTINUE_SEARCH \ ) #define CATCH_STATUS_IN_PAGE_ERROR __except( \ GetExceptionCode() == STATUS_IN_PAGE_ERROR ? \ EXCEPTION_EXECUTE_HANDLER : \ EXCEPTION_CONTINUE_SEARCH \ )