📄 errutil.c
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//* * * (C) 2001 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. *//* style: allow:fprintf:4 sig:0 *//* stdarg is required to handle the variable argument lists for MPIR_Err_create_code */#include <stdarg.h>/* Define USE_ERR_CODE_VALIST to get the prototype for the valist version of MPIR_Err_create_code in mpiimpl.h */#define USE_ERR_CODE_VALIST#include "mpiimpl.h"#include "errcodes.h"/* defmsg is generated automatically from the source files and contains all of the error messages */#include "defmsg.h" /* stdio is needed for vsprintf and vsnprintf */#include <stdio.h>static int convertErrcodeToIndexes( int errcode, int *ring_idx, int *ring_id, int *generic_idx );static const char *get_class_msg( int error_class );/* FIXME: The following comment was the original description and was never changed to match massive changes in the code and associated data structures*//* * Instance-specific error messages are stored in a ring. * Messages are written into the error_ring; the corresponding entry in * error_ring_seq is used to keep a sort of "checkvalue" to ensure that the * error code that points at this message is in fact for this particular * message. This is used to handle the unlikely but possible situation where * so many error messages are generated that the ring is overlapped. * * The message arrays are preallocated to ensure that there is space for these * messages when an error occurs. One variation would be to allow these * to be dynamically allocated, but it is probably better to either preallocate * these or turn off all error message generation (which will eliminate these * arrays). * * One possible alternative is to use the message ring *only* for instance * messages and use the predefined messages in-place for the generic * messages. This approach is used to provide uniform handling of all * error messages. */#if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL#define MAX_ERROR_RING ERROR_SPECIFIC_INDEX_SIZE#define MAX_FCNAME_LEN 63typedef struct MPIR_Err_msg{ /* identifier used to check for validity of instance-specific messages; consists of the class, generic index and hash of the specific message */ int id; /* The previous error code that caused this error to be generated; this allows errors to be chained together */ int prev_error; /* function name and line number where the error occurred */ char fcname[MAX_FCNAME_LEN+1]; /* actual error message */ char msg[MPI_MAX_ERROR_STRING+1]; int use_user_error_code; int user_error_code;}MPIR_Err_msg_t;static MPIR_Err_msg_t ErrorRing[MAX_ERROR_RING];static volatile unsigned int error_ring_loc = 0;#if !defined(MPICH_SINGLE_THREADED)static MPID_Thread_lock_t error_ring_mutex;#define error_ring_mutex_create() MPID_Thread_mutex_create(&error_ring_mutex)#define error_ring_mutex_destroy() MPID_Thread_mutex_create(&error_ring_mutex)#define error_ring_mutex_lock() MPID_Thread_mutex_lock(&error_ring_mutex)#define error_ring_mutex_unlock() MPID_Thread_mutex_unlock(&error_ring_mutex)#else#define error_ring_mutex_create()#define error_ring_mutex_destroy()#define error_ring_mutex_lock()#define error_ring_mutex_unlock()#endif#endif /* (MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL) *//* turn this flag on until we debug and release mpich2 */int MPIR_Err_print_stack_flag = TRUE;static int MPIR_Err_abort_on_error = FALSE;static int MPIR_Err_chop_error_stack = FALSE;static int MPIR_Err_chop_width = 80;void MPIR_Err_init( void ){# if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL { char *env; int n; error_ring_mutex_create(); /* FIXME: Use a more general parameter mechanism */ /* FIXME: Don't cut and paste code like this; instead, use a routine to ensure uniform handling (not just here but anywhere that any of these values is allowed for on/off) */ env = getenv("MPICH_ABORT_ON_ERROR"); if (env) { if (strcmp(env, "1") == 0 || strcmp(env, "on") == 0 || strcmp(env, "yes") == 0) { MPIR_Err_abort_on_error = TRUE; } if (strcmp(env, "0") == 0 || strcmp(env, "off") == 0 || strcmp(env, "no") == 0) { MPIR_Err_abort_on_error = FALSE; } } env = getenv("MPICH_PRINT_ERROR_STACK"); if (env) { if (strcmp(env, "1") == 0 || strcmp(env, "on") == 0 || strcmp(env, "yes") == 0) { MPIR_Err_print_stack_flag = TRUE; } if (strcmp(env, "0") == 0 || strcmp(env, "off") == 0 || strcmp(env, "no") == 0) { MPIR_Err_print_stack_flag = FALSE; } } env = getenv("MPICH_CHOP_ERROR_STACK"); if (env) {#ifdef HAVE_WINDOWS_H HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (hConsole != INVALID_HANDLE_VALUE) { CONSOLE_SCREEN_BUFFER_INFO info; if (GetConsoleScreenBufferInfo(hConsole, &info)) { MPIR_Err_chop_width = info.dwMaximumWindowSize.X; } }#endif /* FIXME: atoi will not signal an error */ n = atoi(env); if (n > 0) { MPIR_Err_chop_error_stack = TRUE; MPIR_Err_chop_width = n; } else if (n == 0) { if (*env == '\0') { MPIR_Err_chop_error_stack = TRUE; } else { MPIR_Err_chop_error_stack = FALSE; } } else { MPIR_Err_chop_error_stack = TRUE; } } }# endif}/* Special error handler to call if we are not yet initialized */void MPIR_Err_preinit( void ){ MPIU_Error_printf("Error encountered before initializing MPICH\n"); exit(1);}/* * This is the routine that is invoked by most MPI routines to * report an error */int MPIR_Err_return_comm( MPID_Comm *comm_ptr, const char fcname[], int errcode ){ const int error_class = ERROR_GET_CLASS(errcode); char error_msg[4096]; int len; if (error_class > MPICH_ERR_LAST_CLASS) { if (errcode & ~ERROR_CLASS_MASK) { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. The error stack follows:\n", error_class, fcname); MPIR_Err_print_stack(stderr, errcode); } else { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. No error stack is available.\n", error_class, fcname); } errcode = (errcode & ~ERROR_CLASS_MASK) | MPI_ERR_UNKNOWN; } /* First, check the nesting level */ if (MPIR_Nest_value()) return errcode; if (!comm_ptr || comm_ptr->errhandler == NULL) { /* Try to replace with the default handler, which is the one on MPI_COMM_WORLD. This gives us correct behavior for the case where the error handler on MPI_COMM_WORLD has been changed. */ if (MPIR_Process.comm_world) { comm_ptr = MPIR_Process.comm_world; } } if (MPIR_Err_is_fatal(errcode) || comm_ptr == NULL || comm_ptr->errhandler == NULL || comm_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) { MPIU_Snprintf(error_msg, 4096, "Fatal error in %s: ", fcname); len = (int)strlen(error_msg); MPIR_Err_get_string(errcode, &error_msg[len], 4096-len, NULL); MPID_Abort(comm_ptr, MPI_SUCCESS, 13, error_msg); } /* If the last error in the stack is a user function error, return that error instead of the corresponding mpi error code? */# if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL { error_ring_mutex_lock(); { if (errcode != MPI_SUCCESS) { int ring_idx; int ring_id; int generic_idx; if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id, &generic_idx ) != 0) { MPIU_Error_printf( "Invalid error code (%d) (error ring index %d invalid)\n", errcode, ring_idx ); } else { /* Can we get a more specific error message */ if (generic_idx >= 0 && ErrorRing[ring_idx].id == ring_id && ErrorRing[ring_idx].use_user_error_code) { errcode = ErrorRing[ring_idx].user_error_code; } } } } error_ring_mutex_unlock(); }# endif if (comm_ptr->errhandler->handle == MPI_ERRORS_RETURN) { return errcode; } else { /* The user error handler may make calls to MPI routines, so the * nesting counter must be incremented before the handler is called */ MPIR_Nest_incr(); /* We pass a final 0 (for a null pointer) to these routines because MPICH-1 expected that */ switch (comm_ptr->errhandler->language) { case MPID_LANG_C:#ifdef HAVE_CXX_BINDING case MPID_LANG_CXX:#endif (*comm_ptr->errhandler->errfn.C_Comm_Handler_function)( &comm_ptr->handle, &errcode, 0 ); break;#ifdef HAVE_FORTRAN_BINDING case MPID_LANG_FORTRAN90: case MPID_LANG_FORTRAN: (*comm_ptr->errhandler->errfn.F77_Handler_function)( (MPI_Fint *)&comm_ptr->handle, &errcode, 0 ); break;#endif } MPIR_Nest_decr(); } return errcode;}/* * MPI routines that detect errors on window objects use this to report errors */int MPIR_Err_return_win( MPID_Win *win_ptr, const char fcname[], int errcode ){ const int error_class = ERROR_GET_CLASS(errcode); char error_msg[4096]; int len; if (win_ptr == NULL || win_ptr->errhandler == NULL) return MPIR_Err_return_comm(NULL, fcname, errcode); if (error_class > MPICH_ERR_LAST_CLASS) { if (errcode & ~ERROR_CLASS_MASK) { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. The error stack follows:\n", error_class, fcname); MPIR_Err_print_stack(stderr, errcode); } else { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. No error stack is available.\n", error_class, fcname); } errcode = (errcode & ~ERROR_CLASS_MASK) | MPI_ERR_UNKNOWN; } /* First, check the nesting level */ if (MPIR_Nest_value()) return errcode; if (MPIR_Err_is_fatal(errcode) || win_ptr == NULL || win_ptr->errhandler == NULL || win_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) { MPIU_Snprintf(error_msg, 4096, "Fatal error in %s: ", fcname); len = (int)strlen(error_msg); MPIR_Err_get_string(errcode, &error_msg[len], 4096-len, NULL); MPID_Abort(NULL, MPI_SUCCESS, 13, error_msg); } /* If the last error in the stack is a user function error, return that error instead of the corresponding mpi error code? */# if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL { error_ring_mutex_lock(); { if (errcode != MPI_SUCCESS) { int ring_idx; int ring_id; int generic_idx; if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id, &generic_idx ) != 0) { MPIU_Error_printf( "Invalid error code (%d) (error ring index %d invalid)\n", errcode, ring_idx ); } else { if (generic_idx >= 0 && ErrorRing[ring_idx].id == ring_id && ErrorRing[ring_idx].use_user_error_code) { errcode = ErrorRing[ring_idx].user_error_code; } } } } error_ring_mutex_unlock(); }# endif if (win_ptr->errhandler->handle == MPI_ERRORS_RETURN) { return errcode; } else { /* Now, invoke the error handler for the window */ /* The user error handler may make calls to MPI routines, so the * nesting counter must be incremented before the handler is called */ MPIR_Nest_incr(); /* We pass a final 0 (for a null pointer) to these routines because MPICH-1 expected that */ switch (win_ptr->errhandler->language) { case MPID_LANG_C:#ifdef HAVE_CXX_BINDING case MPID_LANG_CXX:#endif (*win_ptr->errhandler->errfn.C_Win_Handler_function)( &win_ptr->handle, &errcode, 0 ); break;#ifdef HAVE_FORTRAN_BINDING case MPID_LANG_FORTRAN90: case MPID_LANG_FORTRAN: (*win_ptr->errhandler->errfn.F77_Handler_function)( (MPI_Fint *)&win_ptr->handle, &errcode, 0 ); break;#endif } MPIR_Nest_decr(); } return errcode;}/* * MPI routines that detect errors on files use this to report errors */#if 0int MPIR_Err_return_file( MPID_File *file_ptr, const char fcname[], int errcode ){ const int error_class = ERROR_GET_CLASS(errcode); char error_msg[4096]; int len; if (file_ptr == NULL || file_ptr->errhandler == NULL) return MPIR_Err_return_comm(NULL, fcname, errcode); if (error_class > MPICH_ERR_LAST_CLASS) { if (errcode & ~ERROR_CLASS_MASK) { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. The error stack follows:\n", error_class, fcname); MPIR_Err_print_stack(stderr, errcode); } else { MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n" "%s. Please file a bug report. No error stack is available.\n", error_class, fcname); } errcode = (errcode & ~ERROR_CLASS_MASK) | MPI_ERR_UNKNOWN; } /* First, check the nesting level */ if (MPIR_Nest_value()) return errcode; if (MPIR_Err_is_fatal(errcode) || file_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) { MPIU_Snprintf(error_msg, 4096, "Fatal error in %s: ", fcname); len = (int)strlen(error_msg); MPIR_Err_get_string(errcode, &error_msg[len], 4096-len, NULL); MPID_Abort(NULL, MPI_SUCCESS, 13, error_msg); } /* If the last error in the stack is a user function error, return that error instead of the corresponding mpi error code? */# if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL { error_ring_mutex_lock(); { if (errcode != MPI_SUCCESS) { int ring_idx; int ring_id; int generic_idx; if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id, &generic_idx ) != 0) { MPIU_Error_printf( "Invalid error code (%d) (error ring index %d invalid)\n", errcode, ring_idx ); } else { if (generic_idx >= 0 && ErrorRing[ring_idx].id == ring_id && ErrorRing[ring_idx].use_user_error_code) { errcode = ErrorRing[ring_idx].user_error_code; } } } } error_ring_mutex_unlock(); }# endif if (file_ptr->errhandler->handle == MPI_ERRORS_RETURN) { return errcode; } else { /* Invoke the provided error handler */ /* The user error handler may make calls to MPI routines, so the * nesting counter must be incremented before the handler is called */ MPIR_Nest_incr(); switch (file_ptr->errhandler->language) { case MPID_LANG_C:#ifdef HAVE_CXX_BINDING case MPID_LANG_CXX:#endif (*file_ptr->errhandler->errfn.C_File_Handler_function)( (MPI_File *)&file_ptr->handle, &errcode ); break;#ifdef HAVE_FORTRAN_BINDING case MPID_LANG_FORTRAN90: case MPID_LANG_FORTRAN: (*file_ptr->errhandler->errfn.F77_Handler_function)( (MPI_Fint *)&file_ptr->handle, &errcode ); break;#endif } MPIR_Nest_decr(); } return errcode;}#endif#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG_CLASS/* Given a message string abbreviation (e.g., one that starts "**"), return the corresponding index. For the generic (non * parameterized messages), use idx = FindGenericMsgIndex( "**msg" ); */static int FindGenericMsgIndex( const char *msg ){ int i, c; for (i=0; i<generic_msgs_len; i++) { /* Check the sentinals to insure that the values are ok first */ if (generic_err_msgs[i].sentinal1 != 0xacebad03 || generic_err_msgs[i].sentinal2 != 0xcb0bfa11) { /* Something bad has happened! Don't risk trying the short_name pointer; it may have been corrupted */ break; } c = strcmp( generic_err_msgs[i].short_name, msg ); if (c == 0) return i; if (c > 0) { /* don't return here if the string partially matches */ if (strncmp(generic_err_msgs[i].short_name, msg, strlen(msg)) != 0) return -1; } } return -1;}/* Here is an alternate search routine based on bisection. int i_low, i_mid, i_high, c; i_low = 0; i_high = generic_msg_len - 1; while (i_high - i_low >= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -