//-------------------------------------------------------------------------- // Function: Exception::walkErrorStack ///\brief Walks the error stack for the current thread, calling the /// specified function. ///\param direction - IN: Direction in which the error stack is to be walked ///\param func - IN: Function to be called for each error encountered ///\param client_data - IN: Data passed to the error function ///\par Description /// Valid values for \a direction include: /// \li \c H5E_WALK_UPWARD - begin with the most specific error /// and end at the API /// \li \c H5E_WALK_DOWNWARD - begin at the API and end at the /// inner-most function where the error was first detected ///\par /// The function specified by \a func will be called for each /// error in the error stack. The \c H5E_walk_t prototype is as /// follows: ///\code /// typedef herr_t (*H5E_walk_t)(int n, H5E_error_t *err_desc, void *client_data) /// int n - Indexed position of the error in the stack; it begins at zero /// regardless of stack traversal direction /// H5E_error_t *err_desc - Pointer to a data structure describing the /// error. This structure is listed below. /// void *client_data - Pointer to client data in the format expected by /// the user-defined function. ///\endcode ///\par /// Data structure to describe the error: ///\code /// typedef struct H5E_error2_t { /// hid_t cls_id; //class ID /// hid_t maj_num; //major error ID /// hid_t min_num; //minor error number /// const char *func_name; //function in which error occurred /// const char *file_name; //file in which error occurred /// unsigned line; //line in file where error occurs /// const char *desc; //optional supplied description /// } H5E_error2_t; ///\endcode // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- void Exception::walkErrorStack( H5E_direction_t direction, H5E_walk2_t func, void* client_data ) { // calls the C API routine H5Ewalk to walk the error stack herr_t ret_value = H5Ewalk2( H5E_DEFAULT, direction, func, client_data ); if( ret_value < 0 ) throw Exception( "Exception::walkErrorStack", "H5Ewalk failed" ); }
Exception::Exception() noexcept { // FIXME: is this the best approach? Is it thread-safe? hid_t stack{H5Eget_current_stack()}; // Pop all but inner-most frame, i.e., the root cause. H5Epop(stack, H5Eget_num(stack) - 1); // Get inner-most error message. H5Ewalk2(stack, H5E_WALK_DOWNWARD, setError, what_); // Free stack. H5Eclose_stack(stack); }
static herr_t error_callback(hid_t estack_id, void *client_data) { int ret; ret=pthread_mutex_lock(&error_mutex); assert(ret==0); error_count++; ret=pthread_mutex_unlock(&error_mutex); assert(ret==0); return H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, client_data); }
/* * Class: hdf_hdf5lib_exceptions_HDFLibraryException * Method: getMinorErrorNumber * Signature: ()J * * Extract the HDF-5 minor error number from the HDF-5 error stack. */ JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_exceptions_HDF5LibraryException_getMinorErrorNumber (JNIEnv *env, jobject obj) { H5E_num_t err_nums; err_nums.maj_num = 0; err_nums.min_num = 0; H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, &err_nums); return err_nums.min_num; } /* end Java_hdf_hdf5lib_exceptions_HDF5LibraryException_getMinorErrorNumber() */
/* * Class: hdf_hdf5lib_H5 * Method: H5Ewalk2 * Signature: (JJLjava/lang/Object;Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_hdf_hdf5lib_H5_H5Ewalk2 (JNIEnv *env, jclass cls, jlong stk_id, jlong direction, jobject callback_op, jobject op_data) { ENVPTR->GetJavaVM(ENVPAR &jvm); visit_callback = callback_op; if ((op_data == NULL) || (callback_op == NULL)) { h5nullArgument(env, "H5Ewalk2: op_data or callback_op is NULL"); } /* end if */ else if (H5Ewalk2(stk_id, (H5E_direction_t)direction, (H5E_walk2_t)H5E_walk_cb, (void*)op_data) < 0) h5libraryError(env); } /* end iJava_hdf_hdf5lib_H5_H5Ewalk2f */
/* * h5libraryError() determines the HDF-5 major error code * and creates and throws the appropriate sub-class of * HDF5LibraryException(). This routine should be called * whenever a call to the HDF-5 library fails, i.e., when * the return is -1. * * Note: This routine never returns from the 'throw', * and the Java native method immediately raises the * exception. */ jboolean h5libraryError (JNIEnv *env) { char *args[2]; const char *exception = NULL; char *msg_str = NULL; int num_errs = 0; hid_t min_num; hid_t maj_num; ssize_t msg_size = 0; H5E_type_t error_msg_type; jstring str = NULL; hid_t stk_id = -1; H5E_num_t exceptionNumbers; exceptionNumbers.maj_num = 0; exceptionNumbers.min_num = 0; /* Save current stack contents for future use */ stk_id = H5Eget_current_stack(); /* This will clear current stack */ if(stk_id >= 0) H5Ewalk2(stk_id, H5E_WALK_DOWNWARD, walk_error_callback, &exceptionNumbers); maj_num = exceptionNumbers.maj_num; min_num = exceptionNumbers.min_num; exception = defineHDF5LibraryException(maj_num); /* get the length of the name */ msg_size = H5Eget_msg(min_num, NULL, NULL, 0); if(msg_size > 0) { msg_size++; /* add extra space for the null terminator */ msg_str = (char*)HDcalloc((size_t)msg_size, sizeof(char)); if(msg_str) { msg_size = H5Eget_msg(min_num, &error_msg_type, (char *)msg_str, (size_t)msg_size); str = ENVPTR->NewStringUTF(ENVPAR msg_str); HDfree(msg_str); } /* end if */ } /* end if */ else str = NULL; if(stk_id >= 0) H5Eset_current_stack(stk_id); args[0] = (char *)str; args[1] = 0; THROWEXCEPTION(exception, args); } /* end h5libraryError() */
/*------------------------------------------------------------------------- * Function: test_long_desc * * Purpose: Test long error description handling * * Return: Success: 0 * * Failure: -1 * * Programmer: Quincey Koziol * January 19, 2005 * *------------------------------------------------------------------------- */ static herr_t test_long_desc(void) { const char *format = "Testing very long description string, %s"; char *long_desc = NULL; char *full_desc = NULL; size_t u; const char *test_FUNC = "test_long_desc"; /* Allocate space for the error description info */ if(NULL == (long_desc = (char*)HDmalloc(LONG_DESC_SIZE))) TEST_ERROR; if(NULL == (full_desc = (char*)HDmalloc(LONG_DESC_SIZE + 128))) TEST_ERROR; /* Create the long part of the error description */ for(u = 0; u < LONG_DESC_SIZE; u++) long_desc[u] = 'A' + (u % 26); long_desc[LONG_DESC_SIZE - 1] = '\0'; /* Clear the default error stack */ if(H5Eclear2(H5E_DEFAULT) < 0) TEST_ERROR; /* Push an error with a long description */ if(H5Epush(H5E_DEFAULT, __FILE__, test_FUNC, __LINE__, ERR_CLS, ERR_MAJ_TEST, ERR_MIN_SUBROUTINE, format, long_desc) < 0) TEST_ERROR; /* Create the string that should be in the description. Must use HDsnprintf here * because snprintf is _snprintf on Windows */ HDsnprintf(full_desc, (size_t)(LONG_DESC_SIZE + 128), format, long_desc); /* Make certain that the description is correct */ if(H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, long_desc_cb, full_desc) < 0) TEST_ERROR; /* Clear the default error stack again */ if(H5Eclear2(H5E_DEFAULT) < 0) TEST_ERROR; HDfree(long_desc); HDfree(full_desc); return(0); error: if(long_desc) HDfree(long_desc); if(full_desc) HDfree(full_desc); return(-1); } /* end test_long_desc() */
/*------------------------------------------------------------------------- * Function: dump_error * * Purpose: Prints error stack in default and customized ways. * * Return: Success: 0 * * Failure: -1 * * Programmer: Raymond Lu * July 17, 2003 * *------------------------------------------------------------------------- */ static herr_t dump_error(hid_t estack) { /* Print errors in library default way */ HDfprintf(stderr, "********* Print error stack in HDF5 default way *********\n"); if(H5Eprint2(estack, stderr) < 0) TEST_ERROR; /* Customized way to print errors */ HDfprintf(stderr, "\n********* Print error stack in customized way *********\n"); if(H5Ewalk2(estack, H5E_WALK_UPWARD, custom_print_cb, stderr) < 0) TEST_ERROR; return 0; error: return -1; } /* end dump_error() */