Error Handling
Contents
Error Handling
The following classes are all defined within namespace HIPP::MPI.
Class ErrMPI: the Exception Handler
-
class ErrMPI : public HIPP::ErrType<HIPP::ErrAppMPI, HIPP::ErrClassDefault>
ErrMPIis the exception which is thrown when an internal call of Standard MPI API failed.You may capture it with property exception declaration in the
catchclause. This exception is eventually rooted atstd::exception, so you may usestd::exceptiondeclaration to capture all exceptions.-
typedef ErrType<ErrAppMPI, ErrClassDefault> err_type_t
-
type err_type_t::ErrType
-
virtual const char *what() const noexcept override
-
virtual string whats() const override
These two functions report the detail of the exception instance.
what()only roughly indicates the error at application level, butwhats()returns more detailed information, including the info associated with thrown error number.
-
static size_t errmsg_maxsize() noexcept
-
static errno_t last_errno() noexcept
-
static errno_t last_usederrno()
Defined by MPI Standard, the max length an original MPI error string (including the space for
'\0'), the implementation- defined last error number (inclusive), and the last error number if user-defined error class/number is added.The MPI Standard does not require the error number to be dense. That is, not all error number below
last_usederrorno()is valid.
-
template<typename ...Args>
static void check(errno_t e, Args&&... args) -
template<typename ...Args>
static void throw_(errno_t e, Args&&... args) -
template<typename ...Args>
static void print_err(Args&&... args) -
template<typename ...Args>
static void abort(errno_t e, Args&&... args) Convinient function for detect, report errors and throw exceptions. These function all print the detail location of the error, as well as the information provided by the caller through
args. The prints can be turned on/off by methodsErrMPI::err_cntl_flag()with arguments 1/0.check()examine the reuturned value of a MPI Standard call. Ifeis a number that indicates an error, it prints args intocerr, and throw anErrMPIexception with error numbere.throw()does not perform examine, just prints args and throw.print_err()does nothing but print args.abort()always prints and always abort the program. By default, only the un-recoverable error callsabort()in the high-level interface. An error when destructing a MPI internal object is usually considered un-recoverable, and causes the high-level interface abort the program.
Examples:
Exception handling is an important part for any well-developped application. A typical exception handling process in C++ is to catch the exception, check its info/status, perform actions to recover. If the exception is too severe to be handled, just rethrow it or abort the whole program. The following code sample illustrates this process:
int *out_buff = nullptr; // A must-fail operation, read from 0-address. int dest = 1, tag = 0; try{ comm.send(dest, tag, out_buff, 1, "int"); }catch( HIPP::ErrAppMPI &e ){ // catch the exception // Now you handle the error. Here we just print its content and rethrow it. auto error_number = e.get_errno(); HIPP::MPI::ErrMPI::print_err( emFLPFB, "rank ", comm.rank(), ", out buff ", out_buff, ", error no ", error_number, '\n'); cout << e.whats() << endl; throw; }
where we send a message starting at a protected address, to the rank-1 process in the communicator
comm. This call fails on most modern platforms, which throws an exception of typeErrMPIthrown. Here we catch it by exception declaration of one of its parent classHIPP::ErrAppMPI. We can get the error number byErrMPI::get_errno()method and use it to handle the error, or get the detail error information byErrMPI::whats()method. Here we just print some information usingErrMPI::print_err(), and print the exception detail output byErrMPI::whats(), and rethrow the exception, which eventually aborts the program. Note that TheemFLPFBis a useful preprocess-macro which gives the file, line number and function signature.The output is like the following, where we see the error stack is printed: the first block is printed by the internal intermediate HIPP API call, the second is by the user, and the third is returned by
whats()which depends on your MPI Standard implementation behind the HIPP high-level API.[ file ] /path/to/include/mpi/mpi_raw_comm.h [ line ] 208 [ function ] void HIPP::MPI::_Comm::send(const void*, int, MPI_Datatype, int, int) const [ file ] /path/to/example.cpp [ line ] 19 [ function ] int main(int, const char**) rank 0, out buff 0, error no 4 Application: MPI | Class: default | Type: Invalid buffer pointer, error stack: MPI_Send(174): MPI_Send(buf=(nil), count=1, MPI_INT, dest=1, tag=0, MPI_COMM_WORLD) failed MPI_Send(119): Null buffer pointer
-
typedef ErrType<ErrAppMPI, ErrClassDefault> err_type_t