You may have noticed that your algorithm functions all return a code
(typically StatusCode
). You may have also noticed that we wrap some
functions inside ANA_CHECK()
inside this tutorial. Both of these
are part of the error handling inside ATLAS code. The short summary
is that if you call a function that returns a status code you should
wrap it inside ANA_CHECK()
and return a status code yourself. The
details follow below.
Within ATLAS we have defined multiple classes for status codes
(StatusCode
, EL::StatusCode
, xAOD::TReturnCode
,
CP::CorrectionCode
, CP::SystematicCode
) which all work mostly the
same. If in doubt which type of status code to return StatusCode
is
typically a safe choice. Generally status codes have two or three
possible values (though they have may different names):
SUCCESS
: no error occurred. The function did all it promised to do.FAILURE
: an error occurred. By and large we should not assume we
can continue at this point, and the best strategy is to print an
error message saying what we are doing and return. Generally any
function that returns FAILURE
should also print an error message,
even if it is only reporting that a function it called failed. That
way it is a lot easier for the user to understand at what point the
code failed.RECOVERABLE
: an error occurred but we may be able to proceed (with
caution). This is only supported for some status codes, and it
indicates that we ran into some situation that the code couldn’t
handle, but we can still proceed, e.g. we tried to calibrate an
object that is in a phase space region for which there are no
calibration constants. If a function returns RECOVERABLE
it
should print out a warning message (even if it is just reporting
that a function it called failed). Whether it is a good idea to
proceed in these situations is a matter of debate (and somewhat
situational).If a function returns a status code you are required to check it.
Depending on the type of status code and the settings for your job it
may simply abort right then and there, print a warning message at the
end of the job (see below), or do nothing. Since the default thing to
do is to print an error message on failure and return failure, we
provided the ANA_CHECK()
macro which does it for you. In effect if
you have a line like
ANA_CHECK (evtStore()->retrieve (eventInfo, "EventInfo"));
which is equivalent to doing something like
if (!evtStore()->retrieve (eventInfo, "EventInfo").isSuccess()) {
ANA_MSG_ERROR (...);
return StatusCode::FAILURE;
}
It is perfectly fine not to use ANA_CHECK()
and just write the
if-statements manually (e.g. to customize the error message), but by
and large the ANA_CHECK macro results in more compact and readable
code.
Sometimes your function will return something other than a
StatusCode
, e.g. a EL::StatusCode
. To accommodate that, you can
change the return type for ANA_CHECK
by adding this line at the
beginning of the function:
ANA_CHECK_SET_TYPE (EL::StatusCode);
This tells ANA_CHECK()
what type of status code to return. The
default is StatusCode
, so if your function returns anything else you
need to specify it in this way.
Special note: You can use ANA_CHECK()
inside your main()
program
as well if you specify:
int main ()
{
using namespace asg::msgUserCode;
ANA_CHECK_SET_TYPE (int);
...
}
This will then return a non-zero value on error (like main()
should). Be warned that if you leave out ANA_CHECK_SET_TYPE (int);
it will still compile, but return zero on error (which it shouldn’t).
As a bug that is hard to catch, as it only occurs when another error
occurs.
For some status codes not checking them will by default result in a warning message at the end of the program like this:
Warning in <xAOD::TReturnCode>:
Warning in <xAOD::TReturnCode>: Unchecked return codes encountered during the job
Warning in <xAOD::TReturnCode>: Number of unchecked successes: 502
If you actually want to track down where you forgot to check the status code that is not particularly helpful. So it is recommended instead to change the configuration so that instead unchecked status codes become hard errors at the point where you forgot to check them:
#ifdef ROOTCORE
#include <xAODRootAccess/tools/TReturnCode.h>
#include <AsgTools/StatusCode.h>
#endif
#include <PATInterfaces/CorrectionCode.h>
#include <PATInterfaces/SystematicCode.h>
...
#ifdef ROOTCORE
xAOD::TReturnCode::enableFailure();
StatusCode::enableFailure();
#endif
CP::SystematicCode::enableFailure();
CP::CorrectionCode::enableFailure();
...
Sometimes you simply can not return a status code, e.g. because you are in a constructor which can not have a return type. For those cases you can do the check via:
ANA_CHECK_THROW (...);
Note that by and large this is strongly discouraged, and status codes should be used wherever possible. It is not that there is anything wrong with exceptions, but simply that using the same mechanism everywhere is a definite plus, particularly when it comes to error handling.
If you look at Athena code you will find that they use ATH_CHECK()
instead of ANA_CHECK
. There are a couple of differences between the
two:
ANA_CHECK
uses ANA_MSG_*
, while ATH_CHECK uses
ATH_MSG_*`. So
all the comments on the
differences between the two apply to the check macros as well.ANA_CHECK
can handle all kinds of status codes as well as boolean
and pointer types for its argument. ATH_CHECK
can only handle
StatusCode
itself.ANA_CHECK
e.g. to
return a EL::StatusCode
. ATH_CHECK
will always return a
StatusCode
.This can probably be summarized as saying that if you develop an
Athena component and all you’ll ever see is a StatusCode
then
ATH_CHECK
is probably the better choice, but in all other situations
you should use ANA_CHECK
.