Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright (c) 1998-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Standard_ErrorHandler.hxx>
// During [sig]setjmp()/[sig]longjmp() K_SETJMP is non zero (try)
// So if there is an abort request and if K_SETJMP is non zero, the abort
// request will be ignored. If the abort request do a raise during a setjmp
// or a longjmp, there will be a "terminating SEGV" impossible to handle.
// The top of the Errors Stack
static thread_local Standard_ErrorHandler* Top = nullptr;
Standard_ErrorHandler::Standard_ErrorHandler()
{
myPrevious = Top;
Top = this;
}
//=================================================================================================
void Standard_ErrorHandler::Destroy()
{
Unlink();
}
//=================================================================================================
void Standard_ErrorHandler::Unlink()
{
// Unlink handlers that were created after this one (shouldn't happen in normal usage)
while (Top != nullptr && Top != this)
{
Top->Unlink();
}
if (Top == this)
{
Top = myPrevious;
}
myPrevious = nullptr;
// unlink and destroy all registered callbacks
void* aPtr = myCallbackPtr;
myCallbackPtr = nullptr;
while (aPtr)
{
Standard_ErrorHandler::Callback* aCallback = (Standard_ErrorHandler::Callback*)aPtr;
aPtr = aCallback->myNext;
// Call destructor explicitly, as we know that it will not be called automatically
aCallback->DestroyCallback();
}
}
//=================================================================================================
bool Standard_ErrorHandler::IsInTryBlock()
{
Standard_ErrorHandler* anActive = FindHandler();
return anActive != nullptr;
}
//=================================================================================================
void Standard_ErrorHandler::Raise()
{
if (std::holds_alternative<std::monostate>(myCaughtError))
{
std::cerr << "*** Abort *** an exception handler was called, but no exception object is set."
<< '\n';
exit(1);
}
// Visit the variant and throw the appropriate exception type
std::visit(
[](auto&& theException) {
using T = std::decay_t<decltype(theException)>;
if constexpr (!std::is_same_v<T, std::monostate>)
{
throw theException;
}
},
myCaughtError);
}
//=================================================================================================
Standard_ErrorHandler* Standard_ErrorHandler::FindHandler()
{
return Top;
}
#if defined(OCC_CONVERT_SIGNALS)
Standard_ErrorHandler::Callback::Callback() = default;
Standard_ErrorHandler::Callback::~Callback()
{
UnregisterCallback();
}
void Standard_ErrorHandler::Callback::RegisterCallback()
{
if (myHandler)
{
return; // already registered
}
// find current active exception handler
Standard_ErrorHandler* aHandler = Standard_ErrorHandler::FindHandler();
// if found, add this callback object first to the list
if (aHandler)
{
myHandler = aHandler;
myNext = aHandler->myCallbackPtr;
if (myNext)
{
((Standard_ErrorHandler::Callback*)myNext)->myPrev = this;
}
aHandler->myCallbackPtr = this;
}
}
void Standard_ErrorHandler::Callback::UnregisterCallback()
{
if (!myHandler)
{
return;
}
if (myNext)
{
((Standard_ErrorHandler::Callback*)myNext)->myPrev = myPrev;
}
if (myPrev)
{
((Standard_ErrorHandler::Callback*)myPrev)->myNext = myNext;
}
else if (((Standard_ErrorHandler*)myHandler)->myCallbackPtr == this)
{
((Standard_ErrorHandler*)myHandler)->myCallbackPtr = (Standard_ErrorHandler::Callback*)myNext;
}
myHandler = myNext = myPrev = nullptr;
}
#endif