diff --git a/api/bag.cpp b/api/bag.cpp index 66ec97b61b..bc97bf5a43 100644 --- a/api/bag.cpp +++ b/api/bag.cpp @@ -19,6 +19,8 @@ #include "bag_vrrefinements.h" #include "bag_vrrefinementsdescriptor.h" #include "bag_vrtrackinglist.h" +#include +#include #ifdef _MSC_VER #pragma warning(push) @@ -32,14 +34,13 @@ #include #include #include +#include "signal_hook.h" #ifdef _MSC_VER #pragma warning(pop) #endif -namespace { - //! Convert a BAG::CompoundDataType (C++) into a BagCompoundDataType (C). /*! \param field @@ -111,8 +112,6 @@ BAG::CompoundDataType getValue( } } -} // namespace - //! Open the specified BAG. /*! \param handle @@ -134,6 +133,8 @@ BagError bagFileOpen( BAG_OPEN_MODE accessMode, const char* fileName) { + auto bag_hook = BagAbortHook(); + if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -169,6 +170,7 @@ BagError bagFileOpen( BagError bagFileClose( BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -204,6 +206,7 @@ BagError bagCreateFromFile( const char* fileName, const char* metadataFile) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -257,6 +260,7 @@ BagError bagCreateFromBuffer( uint8_t* metadataBuffer, uint32_t metadataBufferSize) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -303,6 +307,7 @@ BagError bagCreateLayer( BagHandle* handle, BAG_LAYER_TYPE type) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -344,6 +349,7 @@ BagError bagGetGridDimensions( uint32_t* rows, uint32_t* cols) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -378,6 +384,7 @@ BagError bagGetSpacing( double* rowSpacing, double* columnSpacing) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -421,6 +428,7 @@ BagError bagGetGeoCover( double* urx, double* ury) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -461,6 +469,7 @@ BagError bagGetMinMaxSimple( float* minValue, float* maxValue) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -498,6 +507,7 @@ BagError bagSetMinMaxSimple( float minValue, float maxValue) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -530,6 +540,7 @@ BagError bagGetNumLayers( BagHandle* handle, uint32_t* numLayers) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -566,6 +577,7 @@ bool bagContainsLayer( const char* layerName, BagError* bagError) { + auto bag_hook = BagAbortHook(); if (!handle) { *bagError = BAG_INVALID_BAG_HANDLE; @@ -628,6 +640,7 @@ BagError bagRead( double* x, double* y) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -697,6 +710,7 @@ BagError bagWrite( const char* layerName, const uint8_t* data) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -743,6 +757,7 @@ BagError bagGetErrorString( BagError code, uint8_t** error) { + auto bag_hook = BagAbortHook(); constexpr int MAX_STR = 255; constexpr int RANK = 2; @@ -981,6 +996,7 @@ BagError bagComputePostion( double* x, double* y) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1019,6 +1035,7 @@ BagError bagComputeIndex( uint32_t* row, uint32_t* col) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1059,6 +1076,7 @@ uint8_t* bagAllocateBuffer( const char* layerName, BagError* bagError) { + auto bag_hook = BagAbortHook(); if (!handle) return {}; @@ -1095,6 +1113,7 @@ uint8_t* bagAllocateBuffer( */ uint8_t* bagAllocate(uint32_t numBytes) { + auto bag_hook = BagAbortHook(); return new uint8_t[numBytes]; } @@ -1105,6 +1124,7 @@ uint8_t* bagAllocate(uint32_t numBytes) */ void bagFree(uint8_t* buffer) { + auto bag_hook = BagAbortHook(); delete[] buffer; } @@ -1130,6 +1150,7 @@ BagError bagReadCorrectorVerticalDatum( uint8_t corrector, uint8_t* datum) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1193,6 +1214,7 @@ BagError bagWriteCorrectorVerticalDatum( uint8_t corrector, const uint8_t* inDatum) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1272,6 +1294,7 @@ BagError bagReadCorrectedLayer( BAG_LAYER_TYPE type, float** data) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1339,6 +1362,7 @@ BagError bagReadCorrectedRegion( BAG_LAYER_TYPE type, float** data) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1388,6 +1412,7 @@ BagError bagReadCorrectedRow( BAG_LAYER_TYPE type, float** data) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1445,6 +1470,7 @@ BagError bagReadCorrectedNode( BAG_LAYER_TYPE type, float** data) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1484,6 +1510,7 @@ BagError bagGetNumSurfaceCorrectors( BagHandle* handle, uint8_t* numCorrectors) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1522,6 +1549,7 @@ BagError bagGetSurfaceCorrectionTopography( BagHandle* handle, BAG_SURFACE_CORRECTION_TOPOGRAPHY* type) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1563,6 +1591,7 @@ BagError bagCreateCorrectorLayer( uint8_t numCorrectors, BAG_SURFACE_CORRECTION_TOPOGRAPHY topography) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1598,6 +1627,7 @@ BagError bagWriteCorrectorDefinition( BagHandle* handle, BagVerticalCorrectorDef* def) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1646,6 +1676,7 @@ BagError bagReadCorrectorDefinition( BagHandle* handle, BagVerticalCorrectorDef* def) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1686,6 +1717,7 @@ BagError bagTrackingListLength( BagHandle* handle, uint32_t* length) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1724,6 +1756,7 @@ BagError bagReadTrackingListNode( BagTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1773,6 +1806,7 @@ BagError bagReadTrackingListCode( BagTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1822,6 +1856,7 @@ BagError bagReadTrackingListSeries( BagTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1864,6 +1899,7 @@ BagError bagWriteTrackingListItem( BagHandle* handle, BagTrackingItem* item) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1898,6 +1934,7 @@ BagError bagWriteTrackingListItem( */ BagError bagSortTrackingListByNode(BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1934,6 +1971,7 @@ BagError bagSortTrackingListByNode(BagHandle* handle) */ BagError bagSortTrackingListBySeries(BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -1970,6 +2008,7 @@ BagError bagSortTrackingListBySeries(BagHandle* handle) */ BagError bagSortTrackingListByCode(BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2006,6 +2045,7 @@ BagError bagSortTrackingListByCode(BagHandle* handle) */ const BagMetadata* bagGetMetaData(BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return nullptr; @@ -2023,6 +2063,7 @@ const BagMetadata* bagGetMetaData(BagHandle* handle) */ BagError bagSetHomeFolder(const char* metadataFolder) { + auto bag_hook = BagAbortHook(); if (!metadataFolder) return BAG_INVALID_FUNCTION_ARGUMENT; @@ -2063,6 +2104,7 @@ BagError bagCreateGeorefMetadataLayer( const FieldDefinition* definition, uint32_t numFields) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2116,7 +2158,10 @@ BagError bagCreateGeorefMetadataLayer( BAG_EXTERNAL BagError bagCreateMetadataProfileGeorefMetadataLayer(BagHandle* handle, BAG_DATA_TYPE indexType, GEOREF_METADATA_PROFILE profile, - const char* layerName) { + + const char* layerName) { + + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2169,6 +2214,7 @@ BagError bagGetGeorefMetadataLayerDefinition( FieldDefinition** definition, uint32_t* numFields) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2224,6 +2270,7 @@ BagError bagGetGeorefMetadataLayerRecords( uint32_t* numRecords, uint32_t* numFields) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2305,6 +2352,7 @@ BagError bagGetGeorefMetadataLayerValueByName( const char* fieldName, BagCompoundDataType* value) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2367,6 +2415,7 @@ BagError bagGetGeorefMetadataLayerValueByIndex( uint32_t fieldIndex, BagCompoundDataType* value) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2425,6 +2474,7 @@ BagError bagGetGeorefMetadataLayerFieldIndex( const char* fieldName, uint32_t* fieldIndex) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2472,6 +2522,7 @@ BagError bagGetGeorefMetadataLayerFieldName( uint32_t fieldIndex, const char** fieldName) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2522,6 +2573,7 @@ BagError bagAddGeorefMetadataLayerRecord( uint32_t numFields, uint32_t* recordIndex) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2587,6 +2639,7 @@ BagError bagAddGeorefMetadataLayerRecords( uint32_t numRecords, uint32_t numFields) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2660,6 +2713,7 @@ BagError bagGeorefMetadataLayerSetValueByName( const char* fieldName, const BagCompoundDataType* value) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2724,6 +2778,7 @@ BagError bagGeorefMetadataLayerSetValueByIndex( uint32_t fieldIndex, const BagCompoundDataType* value) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2779,6 +2834,7 @@ BagError bagCreateVRLayers( BagHandle* handle, bool makeNode) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2829,6 +2885,7 @@ BagError bagVRMetadataGetMinDimensions( uint32_t* minX, uint32_t* minY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2871,6 +2928,7 @@ BagError bagVRMetadataGetMaxDimensions( uint32_t* maxX, uint32_t* maxY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2913,6 +2971,7 @@ BagError bagVRMetadataGetMinResolution( float* minX, float* minY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2955,6 +3014,7 @@ BagError bagVRMetadataGetMaxResolution( float* maxX, float* maxY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -2994,6 +3054,7 @@ BagError bagVRMetadataSetMinDimensions( uint32_t minX, uint32_t minY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3047,6 +3108,7 @@ BagError bagVRMetadataSetMaxDimensions( uint32_t maxX, uint32_t maxY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3100,6 +3162,7 @@ BagError bagVRMetadataSetMinResolution( float minX, float minY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3153,6 +3216,7 @@ BagError bagVRMetadataSetMaxResolution( float maxX, float maxY) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3209,6 +3273,7 @@ BagError bagVRNodeGetMinMaxHypStrength( float* minHypStr, float* maxHypStr) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3250,6 +3315,7 @@ BagError bagVRNodeGetMinMaxNumHypotheses( uint32_t* minNumHyp, uint32_t* maxNumHyp) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3291,6 +3357,7 @@ BagError bagVRNodeGetMinMaxNSamples( uint32_t* minNSamples, uint32_t* maxNSamples) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3330,6 +3397,7 @@ BagError bagVRNodeSetMinMaxHypStrength( float minHypStr, float maxHypStr) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3383,6 +3451,7 @@ BagError bagVRNodeSetMinMaxNumHypotheses( uint32_t minNumHyp, uint32_t maxNumHyp) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3436,6 +3505,7 @@ BagError bagVRNodeSetMinMaxNSamples( uint32_t minNSamples, uint32_t maxNSamples) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3492,6 +3562,7 @@ BAG_EXTERNAL BagError bagVRRefinementGetMinMaxDepth( float* minDepth, float* maxDepth) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3533,6 +3604,7 @@ BAG_EXTERNAL BagError bagVRRefinementGetMinMaxUncertainty( float* minUncert, float* maxUncert) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3572,6 +3644,7 @@ BAG_EXTERNAL BagError bagVRRefinementSetMinMaxDepth( float minDepth, float maxDepth) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3625,6 +3698,7 @@ BAG_EXTERNAL BagError bagVRRefinementSetMinMaxUncertainty( float minUncert, float maxUncert) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3677,6 +3751,7 @@ BagError bagVRTrackingListLength( BagHandle* handle, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3719,6 +3794,7 @@ BagError bagReadVRTrackingListNode( BagVRTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3773,6 +3849,7 @@ BagError bagReadVRTrackingListSubNode( BagVRTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3824,6 +3901,7 @@ BagError bagReadVRTrackingListCode( BagVRTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3875,6 +3953,7 @@ BagError bagReadVRTrackingListSeries( BagVRTrackingItem** items, uint32_t* numItems) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3919,6 +3998,7 @@ BagError bagWriteVRTrackingListItem( BagHandle* handle, BagVRTrackingItem* item) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -3964,6 +4044,7 @@ BagError bagWriteVRTrackingListItem( BagError bagSortVRTrackingListByNode( BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -4011,6 +4092,7 @@ BagError bagSortVRTrackingListByNode( BagError bagSortVRTrackingListBySubNode( BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -4058,6 +4140,7 @@ BagError bagSortVRTrackingListBySubNode( BagError bagSortVRTrackingListBySeries( BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; @@ -4105,6 +4188,7 @@ BagError bagSortVRTrackingListBySeries( BagError bagSortVRTrackingListByCode( BagHandle* handle) { + auto bag_hook = BagAbortHook(); if (!handle) return BAG_INVALID_BAG_HANDLE; diff --git a/api/bag_dataset.cpp b/api/bag_dataset.cpp index 02f332d900..9efe6239c9 100644 --- a/api/bag_dataset.cpp +++ b/api/bag_dataset.cpp @@ -276,6 +276,17 @@ std::shared_ptr Dataset::open( { std::cerr << "\nUnable to open BAG file: " << fileName << " due to error: " << fileExcept.getCDetailMsg(); return nullptr; + } catch (H5::GroupIException &groupExcept) { + std::cerr << "\nAn group exception occurred opening the dataset. Error was in " + << groupExcept.getFuncName() + << ". A detailed message follows:" + << std::endl << groupExcept.getDetailMsg() << std::endl; + } catch (H5::Exception &otherException) + { + std::cerr << "\nAn unknown exception occurred opening the dataset. Error was in " + << otherException.getFuncName() + << ". A detailed message follows:" + << std::endl << otherException.getDetailMsg() << std::endl; } return pDataset; diff --git a/api/signal_hook.h b/api/signal_hook.h new file mode 100644 index 0000000000..f2376d585b --- /dev/null +++ b/api/signal_hook.h @@ -0,0 +1,202 @@ +#ifndef BAG_SIGNAL_HOOK +#define BAG_SIGNAL_HOOK + +#include +#include +#include + +// from https://man7.org/linux/man-pages/man2/sigaction.2.html +// and https://man7.org/linux/man-pages/man7/feature_test_macros.7.html +#ifdef _POSIX_C_SOURCE + +#include +#include +#include +#include +#include +#include + +#define HOOK_HANDLERS_COUNT 255 +#define HOOK_CLEANUP_FUNCTIONS_COUNT 50 + +static void (*cleanup_functions[HOOK_CLEANUP_FUNCTIONS_COUNT])(int); +static int cleanup_functions_count = 0; + +// Returns 0 on success, 1 if too many functions have been set +// This is not thread safe, only call it from a single thread +int add_cleanup_function(void (*f)(int)) { + if (cleanup_functions_count >= HOOK_CLEANUP_FUNCTIONS_COUNT) { + return 1; + } + + cleanup_functions[cleanup_functions_count] = f; + cleanup_functions_count++; + + return 0; +} + + +static void bag_handler(int signal); + +struct BagAbortHook; + +static BagAbortHook* current_hook; + +static int bag_string_length(const char* string) { + int length = 0; + while(true) { + if (string[length] == 0) { + break; + } + length++; + } + + return length; +} + +struct BagAbortHook { + BagAbortHook* previous; + struct sigaction old_handlers[HOOK_HANDLERS_COUNT]; + + // returns after done printing the exit message + void print_error_msg(int signal) { + // if the handlers are the same, don't call "bag handler" twice + char* signal_name; + + #define TERM_STRING "a critical error occurred within BAG or a dependency (probably libxml or HDF5), exiting to prevent corruption or unexpected behavior. The signal that caused this error was: " + + // I can't figure out how to tell if sigabbrev_np exists so I'll + // just print the ones it probably is + const char* signal_abbrev = ""; + + if(signal == SIGSEGV) { + signal_abbrev = "SIGSEGV"; + } else if(signal == SIGABRT) { + signal_abbrev = "SIGABRT"; + } else if(signal == SIGFPE) { + signal_abbrev = "SIGFPE"; + } else if(signal == SIGKILL) { + signal_abbrev = "SIGKILL"; + } else if(signal == SIGILL) { + signal_abbrev = "SIGILL"; + } else if(signal == SIGBUS) { + signal_abbrev = "SIGBUS"; + } + + // I think this works, it seems to? write needs a file descriptor + int stderr_fd = stderr->_fileno; + + // strlen is not async signal safe, so it can't be used here, but bag_string_length works instead + write(stderr_fd, TERM_STRING, bag_string_length(TERM_STRING)); + write(stderr_fd, signal_abbrev, bag_string_length(signal_abbrev)); + write(stderr_fd, "\n", 1); + } + + void call_cleanup_functions(int signal) { + for(int i = 0; i < cleanup_functions_count; i++) { + cleanup_functions[i](signal); + } + } + + void call_previous_handler(int signal) { + if (this->old_handlers[signal].sa_handler != nullptr && this->old_handlers[signal].sa_handler != bag_handler) { + this->old_handlers[signal].sa_handler(signal); + } + } + + void handle(int signal) { + this->print_error_msg(signal); + + // if anyone set a cleanup function, call those + this->call_cleanup_functions(signal); + + // if there was a handler before this, that isn't the BAG handler, + // call that one + this->call_previous_handler(signal); + + // if nothing has exited in the previous handlers, exit here + _exit(-1); + } + + std::array handled_signals() { + return { SIGABRT, SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGKILL }; + } + + BagAbortHook() { + // set these all to null so that when restoring them + // we know which ones were added + for (int i = 0; i < HOOK_HANDLERS_COUNT; i++) { + this->old_handlers[i].sa_handler = nullptr; + } + + struct sigaction old_action; + for (auto sn : this->handled_signals()) { + struct sigaction new_action; + new_action.sa_flags = 0; + new_action.sa_handler = bag_handler; + + // I was going to use https://en.cppreference.com/w/c/program/signal here + // but I needed to get what the old action was so that I could + // put the original handler back + // https://linux.die.net/man/2/sigaction seems to give me what it used to be + // in old action, but I'm not sure if I need to do anything special with the + // other things in the sigaction struct? + // + // Actually, I think it does support it but apparently signal is + // pretty outdated: https://stackoverflow.com/questions/231912/what-is-the-difference-between-sigaction-and-signal + auto r = sigaction(sn, &new_action, &old_action); + + this->old_handlers[sn] = old_action; + } + this->previous = current_hook; + current_hook = this; + } + + ~BagAbortHook() { + // reset the handlers back to what they were + for (auto sn : this->handled_signals()) { + struct sigaction old_action = this->old_handlers[sn]; + sigaction(sn, &old_action, nullptr); + } + + current_hook = this->previous; + } +}; + +static void bag_handler(int signal) { + if (current_hook) { + current_hook->handle(signal); + } else { + // something broke I think? + // I don't know if there's a way to deal with this + // so I'll just exit here + _exit(-2); + } +} + +#else // this isn't linux with sigaction, so make a BagAbortHook that does nothing + +static bool bag_warning_printed = false; + +static void print_disabled_warning() { + if (!bag_warning_printed) { + bag_warning_printed = true; + std::cout << "WARNING: BagAbortHook and add_cleanup_function are disabled because _POSIX_C_SOURCE does not say that sigaction is available" << std::endl; + } +} + +int add_cleanup_function(void (*)(int)) { + print_disabled_warning(); + return 0; +} + + +struct BagAbortHook { + BagAbortHook() { + print_disabled_warning(); + } +}; + +#endif + +#endif diff --git a/examples/driver.cpp b/examples/driver.cpp index 0160a8ed31..1260b121b8 100644 --- a/examples/driver.cpp +++ b/examples/driver.cpp @@ -1,7 +1,8 @@ + +#include #include #include #include -#include #include #include #include @@ -40,4 +41,4 @@ int main(int argc, char** argv)//argv, which is an array of pointers to strings //strcpy(filename_cstr, filename.c_str()); LLVMFuzzerTestOneInputByFile(filename.c_str()); -} \ No newline at end of file +} diff --git a/tests/test_signal_hook.cpp b/tests/test_signal_hook.cpp new file mode 100644 index 0000000000..579172ee7f --- /dev/null +++ b/tests/test_signal_hook.cpp @@ -0,0 +1,34 @@ +#include "../api/signal_hook.h" +#include +#include +#include +#include + +void cleanuper(int signal) { + std::cout << "cleanuper" << std::endl; +} + +void existing_handler(int signal) { + std::cout << "existing handler" << std::endl; +} + +int main(int argc, char** argv) { + signal(SIGSEGV, existing_handler); + + BagAbortHook hook; + + add_cleanup_function(cleanuper); + + std::cout << "signal going to happen" << std::endl; + + // this causes the segfault, but not sure if compiler might do something else? + // this is just a test, so could maybe make it do sigabrt instead? + volatile int* p = nullptr; + + int v = *p; + + + std::cout << "v is:" << v << std::endl; + + std::cout << "this shouldn't print" << std::endl; +}