/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ /* * Copyright (C) 2004 University of Chicago. * See COPYRIGHT notice in top-level directory. */ #include #include #include "mpioimpl.h" #include "adio_extern.h" /* MPICH error handling implementation */ /* FIXME: These external prototypes should be included from mpich/src/include/mpiext.h */ int MPIR_Err_create_code_valist(int, int, const char [], int, int, const char [], const char [], va_list ); int MPIR_Err_is_fatal(int); void MPIR_Get_file_error_routine( MPI_Errhandler, void (**)(MPI_File *, int *, ...), int * ); int MPIR_File_call_cxx_errhandler( MPI_File *, int *, void (*)(MPI_File *, int *, ... ) ); typedef int (* MPIR_Err_get_class_string_func_t)(int error, char *str, int length); void MPIR_Err_get_string( int, char *, int, MPIR_Err_get_class_string_func_t ); struct MPID_Comm; int MPID_Abort(struct MPID_Comm *comm, int mpi_errno, int exit_code, const char *error_msg); int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[], int line, int error_class, const char generic_msg[], const char specific_msg[], ... ) { va_list Argp; int error_code; va_start(Argp, specific_msg); error_code = MPIR_Err_create_code_valist(lastcode, fatal, fcname, line, error_class, generic_msg, specific_msg, Argp); va_end(Argp); return error_code; } int MPIO_Err_return_file(MPI_File mpi_fh, int error_code) { MPI_Errhandler e; void (*c_errhandler)(MPI_File *, int *, ... ); int kind; /* Error handler kind (see below) */ char error_msg[4096]; int len; /* If the file pointer is not valid, we use the handler on MPI_FILE_NULL (MPI-2, section 9.7). For now, this code assumes that MPI_FILE_NULL has the default handler (return). FIXME. See below - the set error handler uses ADIOI_DFLT_ERR_HANDLER; */ /* First, get the handler and the corresponding function */ if (mpi_fh == MPI_FILE_NULL) { e = ADIOI_DFLT_ERR_HANDLER; } else { ADIO_File fh; fh = MPIO_File_resolve(mpi_fh); e = fh->err_handler; } /* Actually, e is just the value provide by the MPICH routines file_set_errhandler. This is actually a *pointer* to the errhandler structure. We don't know that, so we ask the MPICH code to translate this object into an error handler. kind = 0: errors are fatal kind = 1: errors return kind = 2: errors call function */ if (e == MPI_ERRORS_RETURN || e == MPIR_ERRORS_THROW_EXCEPTIONS || !e) { /* FIXME: This is a hack in case no error handler was set */ kind = 1; c_errhandler = 0; } else { MPIR_Get_file_error_routine( e, &c_errhandler, &kind ); } /* --BEGIN ERROR HANDLING-- */ if (MPIR_Err_is_fatal(error_code) || kind == 0) { ADIOI_Snprintf(error_msg, 4096, "I/O error: "); len = (int)strlen(error_msg); MPIR_Err_get_string(error_code, &error_msg[len], 4096-len, NULL); MPID_Abort(NULL, MPI_SUCCESS, error_code, error_msg); } /* --END ERROR HANDLING-- */ else if (kind == 2) { (*c_errhandler)( &mpi_fh, &error_code, 0 ); } else if (kind == 3) { MPIR_File_call_cxx_errhandler( &mpi_fh, &error_code, c_errhandler ); } /* kind == 1 just returns */ return error_code; } int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code) { /* note: MPI calls inside the MPICH implementation are prefixed * with an "N", indicating a nested call. */ MPI_Comm_call_errhandler(mpi_comm, error_code); return error_code; }