Library: discontinue setting error flag from Exceptions (see #1341)

While seemingly subtle, this is a ''deep change.''
Up to now, the project attempted to maintain two mutually disjoint
systems of error reporting: C-style error flags and C++ exceptions.
Most notably, an attempt was made to keep both error states synced.

During the recent integration efforts, this increasingly turned out
as an obstacle and source for insidious problems (like deadlocks).


As a resolve, hereby the relation of both systems is **clarified**:
 * C-style error flags shall only be set and used by C code henceforth
 * C++ exceptions can (optionally) be thrown by retrieving the C-style error code
 * but the opposite is now ''discontinued'' : Exceptions ''do not set'' the error flag anymore
This commit is contained in:
Fischlurch 2023-10-01 20:11:45 +02:00
parent fdd8e2d595
commit 9cb0a9b680
7 changed files with 47 additions and 61 deletions

View file

@ -213,6 +213,8 @@ namespace lib {
catch (lumiera::Error & ex) catch (lumiera::Error & ex)
{ {
WARN (progress, "Exception while closing AllocationCluster: %s", ex.what()); WARN (progress, "Exception while closing AllocationCluster: %s", ex.what());
const char* errID = lumiera_error();
TRACE (debugging, "Error flag was: %s", errID);
} }
catch (...) catch (...)
{ {

View file

@ -96,16 +96,13 @@ namespace lumiera {
/** @note we set the C-style errorstate as a side effect */
Error::Error (string description, lumiera_err const id) noexcept Error::Error (string description, lumiera_err const id) noexcept
: std::exception{} : std::exception{}
, id_{id} , id_{id}
, msg_{error::default_usermsg (this)} , msg_{error::default_usermsg (this)}
, desc_{description} , desc_{description}
, cause_{} , cause_{}
{ { }
lumiera_error_set (this->id_, description.c_str());
}
Error::Error (std::exception const& cause, Error::Error (std::exception const& cause,
@ -117,7 +114,6 @@ namespace lumiera {
, cause_{extractCauseMsg(cause)} , cause_{extractCauseMsg(cause)}
{ {
string detailInfo{description + (isnil(cause_)? "" : " | cause = "+cause_)}; string detailInfo{description + (isnil(cause_)? "" : " | cause = "+cause_)};
lumiera_error_set (this->id_, detailInfo.c_str());
} }

View file

@ -242,7 +242,7 @@ namespace lumiera {
{ {
throw error::Flag( error::detailInfo() throw error::Flag( error::detailInfo()
, errorFlag); , errorFlag);
} } //causes the error state to be set } }
/** Check the lumiera error state and throw a specific exception /** Check the lumiera error state and throw a specific exception
* in case a non-cleared errorflag is detected. No-op else. * in case a non-cleared errorflag is detected. No-op else.

View file

@ -154,10 +154,12 @@ namespace stage {
} }
catch(...) catch(...)
{ {
if (!lumiera_error_peek()) const char* errID = lumiera_error(); // clear C-style error flag
LUMIERA_ERROR_SET (stage, STATE, "unexpected error when starting the GUI thread"); WARN (stage, "Unexpected error while starting the GUI thread.");
if (errID)
TRACE (stage, "Error flag was: %s", errID);
return false; return false;
} // note: lumiera_error state remains set }
} }
} // namespace stage } // namespace stage

View file

@ -2,7 +2,7 @@ TESTING "Exception handling and diagnostics" ./test-suite --group=common
TEST "ExceptionError_test" ExceptionError_test <<END TEST "Exceptions and Error flags" ExceptionError_test <<END
out: caught: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(don't panic\)...the answer is: 42 out: caught: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(don't panic\)...the answer is: 42
out: caught lumiera::Error: LUMIERA_ERROR_DERIVED:convoluted exception out: caught lumiera::Error: LUMIERA_ERROR_DERIVED:convoluted exception
out: caught error::Logic: LUMIERA_ERROR_FATAL:floundered \(test-2\). out: caught error::Logic: LUMIERA_ERROR_FATAL:floundered \(test-2\).
@ -16,7 +16,6 @@ out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external ser
out: 2nd intermediate handler caught: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::Config out: 2nd intermediate handler caught: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::Config
out: caught error::Invalid: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\)\. out: caught error::Invalid: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\)\.
out: caught lumiera::Error: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\. out: caught lumiera::Error: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
out: caught error::Logic: LUMIERA_ERROR_LOGIC:internal logic broken \(the big bang\). -- caused by: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
return: 0 return: 0
END END

View file

@ -67,12 +67,10 @@ namespace lumiera {
class ExceptionError_test : public Test class ExceptionError_test : public Test
{ {
typedef ExceptionError_test test; typedef ExceptionError_test test;
virtual void run (Arg arg)
virtual void
run (Arg)
{ {
if (0 < arg.size() and arg[1]=="terminate")
terminateUnknown();
catcher (&test::throwSpecial, ""); catcher (&test::throwSpecial, "");
catcher (&test::throwDerived, "test-1"); catcher (&test::throwDerived, "test-1");
catcher (&test::throwFatal, "test-2"); catcher (&test::throwFatal, "test-2");
@ -84,7 +82,6 @@ namespace lumiera {
catcher (&test::nestedThrower, "test-7"); catcher (&test::nestedThrower, "test-7");
catcher (&test::doubleNestedTh,"test-8"); catcher (&test::doubleNestedTh,"test-8");
checkErrorIntegration();
checkErrorFlagPropagation(); checkErrorFlagPropagation();
checkRootCauseChaining(); checkRootCauseChaining();
} }
@ -134,31 +131,7 @@ namespace lumiera {
} }
/** @test by constructing an lumiera::Error object, void detectErrorflag (string) { throwOnError(); }
* the corresponding lumiera_error state is set automatically
*/
void checkErrorIntegration()
{
lumiera_error ();
CHECK (not lumiera_error());
Error err1;
Error err2("boo",LERR_(DERIVED));
CHECK (err1.getID () == lumiera_error ()); // (we didn't clear the first one!)
Error err3("boooo",LERR_(DERIVED));
CHECK (err3.getID () == lumiera_error ());
SpecificError err4;
CHECK (err4.getID () == LERR_(LIFE_AND_UNIVERSE));
CHECK (err4.getID () == lumiera_error ());
CHECK (not lumiera_error());
}
void detectErrorflag (string) { throwOnError(); }
void detectErrorflagChained (string msg) { maybeThrow<error::Logic> (msg); }
/** @test verify throwing of Exceptions /** @test verify throwing of Exceptions
@ -169,12 +142,9 @@ namespace lumiera {
lumiera_error_set(LERR_(LIFE_AND_UNIVERSE), "what is the answer?"); lumiera_error_set(LERR_(LIFE_AND_UNIVERSE), "what is the answer?");
CHECK (lumiera_error_peek()); CHECK (lumiera_error_peek());
catcher (&test::detectErrorflag, ""); catcher (&test::detectErrorflag);
CHECK (LERR_(LIFE_AND_UNIVERSE) == lumiera_error_peek()); CHECK (not lumiera_error_peek());
}// yet translating that into an exception also clears the error flag
catcher (&test::detectErrorflagChained, "the big bang");
CHECK (LERR_(LIFE_AND_UNIVERSE) == lumiera_error());
}
/** @test the chaining of lumiera::Exception objects /** @test the chaining of lumiera::Exception objects
@ -200,18 +170,6 @@ namespace lumiera {
} }
/** @test terminate the Application by throwing an undeclared exception.
* this should result in the global unknown() handler to be called,
* so usually it will terminate the test run.
* @note inside error.hpp, an initialisation hook has been installed into
* AppState, causing our own unknown() handler to be installed and
* invoked, which gives additional diagnostics.*/
void terminateUnknown () noexcept
{
throw Error{"Catch the hedgehog..."};
}
/** a very specific Exception class /** a very specific Exception class
* local to this scope and with * local to this scope and with
* additional behaviour. * additional behaviour.
@ -238,7 +196,7 @@ namespace lumiera {
/** helper: provides a bunch of catch-clauses and /** helper: provides a bunch of catch-clauses and
* runs the given member functions within * runs the given member functions within
*/ */
void catcher (void (ExceptionError_test::*funky)(string), string context) void catcher (void (ExceptionError_test::*funky)(string), string context ="")
{ {
try try
{ {

View file

@ -57360,6 +57360,33 @@
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
</node> </node>
</node> </node>
<node CREATED="1696123512914" ID="ID_1907944246" MODIFIED="1696123517031" TEXT="Fehlerbehandlung">
<node CREATED="1696123519551" ID="ID_1260806652" MODIFIED="1696123525010" TEXT="Status-quo">
<node CREATED="1696123526614" ID="ID_494414016" MODIFIED="1696123536532" TEXT="zwei konkurrierende Systeme"/>
<node CREATED="1696123537225" ID="ID_1573590963" MODIFIED="1696123548249" TEXT="Versuch, sie miteinander zu verbinden"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696109905830" ID="ID_1320347721" MODIFIED="1696123617052" TEXT="konzeptioneller Rahmen nicht klar">
<arrowlink COLOR="#fdcfce" DESTINATION="ID_853481552" ENDARROW="Default" ENDINCLINATION="-959;56;" ID="Arrow_ID_1749710199" STARTARROW="None" STARTINCLINATION="-1130;86;"/>
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1696123584407" ID="ID_100243936" MODIFIED="1696123592153" TEXT="was soll die Fehlerbehandlung leisten?"/>
<node CREATED="1696123593053" ID="ID_1989612078" MODIFIED="1696123604000" TEXT="wann darf man die Applikation einfach stoppen"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1696123633856" ID="ID_938884061" MODIFIED="1696123679262" TEXT="weiterentwickeln">
<icon BUILTIN="pencil"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1696123685033" ID="ID_1288168258" MODIFIED="1696123908702" TEXT="10/2023 : C-Fehlerflag wird zweitrangig">
<linktarget COLOR="#743762" DESTINATION="ID_1288168258" ENDARROW="Default" ENDINCLINATION="-1572;111;" ID="Arrow_ID_1929499179" SOURCE="ID_693954886" STARTARROW="None" STARTINCLINATION="-1669;-68;"/>
<icon BUILTIN="yes"/>
<node CREATED="1696123727542" ID="ID_1991627324" MODIFIED="1696123743073" TEXT="bidirektionale Verbindung aufgeben"/>
<node CREATED="1696123744977" ID="ID_383359061" MODIFIED="1696123762047" TEXT="C-Fehlerflag soll nur noch aus C-Code gesetzt werden">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696123916050" ID="ID_336075850" MODIFIED="1696123953390" TEXT="kein automatisches Setzen mehr beim Erzeugen einer Exception">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node> </node>
<node CREATED="1667336713909" ID="ID_259014029" MODIFIED="1667336726184" TEXT="Framework"> <node CREATED="1667336713909" ID="ID_259014029" MODIFIED="1667336726184" TEXT="Framework">
<font NAME="SansSerif" SIZE="14"/> <font NAME="SansSerif" SIZE="14"/>
@ -80746,6 +80773,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1696109856041" ID="ID_130019164" MODIFIED="1696110849648" TEXT="Fazit"> <node CREATED="1696109856041" ID="ID_130019164" MODIFIED="1696110849648" TEXT="Fazit">
<icon BUILTIN="forward"/> <icon BUILTIN="forward"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1696109861199" ID="ID_693954886" MODIFIED="1696119872703" TEXT="Entscheidung die Kopplung von C-Flag und Exceptions betreffend"> <node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1696109861199" ID="ID_693954886" MODIFIED="1696119872703" TEXT="Entscheidung die Kopplung von C-Flag und Exceptions betreffend">
<arrowlink COLOR="#743762" DESTINATION="ID_1288168258" ENDARROW="Default" ENDINCLINATION="-1572;111;" ID="Arrow_ID_1929499179" STARTARROW="None" STARTINCLINATION="-1669;-68;"/>
<linktarget COLOR="#734d4b" DESTINATION="ID_693954886" ENDARROW="Default" ENDINCLINATION="61;-139;" ID="Arrow_ID_921866413" SOURCE="ID_1910682637" STARTARROW="None" STARTINCLINATION="-390;17;"/> <linktarget COLOR="#734d4b" DESTINATION="ID_693954886" ENDARROW="Default" ENDINCLINATION="61;-139;" ID="Arrow_ID_921866413" SOURCE="ID_1910682637" STARTARROW="None" STARTINCLINATION="-390;17;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/> <font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
@ -92193,6 +92221,7 @@ class Something
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696109921291" ID="ID_853481552" LINK="https://issues.lumiera.org/ticket/1341" MODIFIED="1696110190077" TEXT="#110 und #1341 Clarify Error handling scheme"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1696109921291" ID="ID_853481552" LINK="https://issues.lumiera.org/ticket/1341" MODIFIED="1696110190077" TEXT="#110 und #1341 Clarify Error handling scheme">
<linktarget COLOR="#fdcfce" DESTINATION="ID_853481552" ENDARROW="Default" ENDINCLINATION="-959;56;" ID="Arrow_ID_275745687" SOURCE="ID_1712639748" STARTARROW="None" STARTINCLINATION="-1085;66;"/> <linktarget COLOR="#fdcfce" DESTINATION="ID_853481552" ENDARROW="Default" ENDINCLINATION="-959;56;" ID="Arrow_ID_275745687" SOURCE="ID_1712639748" STARTARROW="None" STARTINCLINATION="-1085;66;"/>
<linktarget COLOR="#fdcfce" DESTINATION="ID_853481552" ENDARROW="Default" ENDINCLINATION="-959;56;" ID="Arrow_ID_1749710199" SOURCE="ID_1320347721" STARTARROW="None" STARTINCLINATION="-1130;86;"/>
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="flag-yellow"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1694440562933" ID="ID_1529688085" LINK="https://issues.lumiera.org/ticket/1338" MODIFIED="1694795034628" TEXT="#1338 Non-standard Play-processing"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1694440562933" ID="ID_1529688085" LINK="https://issues.lumiera.org/ticket/1338" MODIFIED="1694795034628" TEXT="#1338 Non-standard Play-processing">