Custom error messages and behaviour of H5Eget_msg()

I’m trying to customise the error messages reported by my software when HDF5 encounters a problem. I’m having difficulty with reporting both the name of the source file and the type of error encountered.

The code at the end of this post (based on section 9.4 here) provides a minimal example of the issue.

If I run the code as it is below the file names in the error stack are reported fine e.g.

FileName: ../../../src/H5F.c
FileName: ../../../src/H5Fint.c
FileName: ../../../src/H5FD.c
FileName: ../../../src/H5FDsec2.c

However if I uncomment the line that calls H5Eget_msg() to try and retrieve the type of error too, the file names are no longer correctly handled and I get something like this (it changes on each run):

FileName: �p3ȊU
FileName: `p3ȊU
FileName: `l3ȊU
FileName: q3ȊU

Does H5Eget_msg() modify err_desc in someway the I’m not appreciating? Many thanks for any pointers.


#include "hdf5.h"

#define H5FILE_NAME        "SDS.h5"
#define MSG_SIZE       32

herr_t custom_print_cb(unsigned n, const H5E_error2_t *err_desc, void* client_data)
{
    /* uncomment these two lines and file names break */    
    //char maj[MSG_SIZE];
    //ssize_t len = H5Eget_msg(err_desc->maj_num, NULL, maj, MSG_SIZE);

    printf("FileName: %s\n", err_desc->file_name);

    return 0;
}

herr_t _rhdf5PrintErrorR( hid_t estack_id, void * stream) {
    ssize_t s = H5Eget_num(estack_id);
    void *client_data;
    if ( s > 0) {
        herr_t eee = H5Ewalk2(estack_id, H5E_WALK_DOWNWARD, &custom_print_cb, client_data);
    }
    return 0;
}

int main (void) {
    hid_t       file;        
    void *err_func_data;
    H5E_auto_t myfct = &_rhdf5PrintErrorR;

    H5Eset_auto (H5E_DEFAULT, myfct, &err_func_data);

    /* Open the file.  It should fail */
    file = H5Fopen(H5FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT);
    if(file < 0) {
      return 1;
    } else {
      return 0;
    }  
}

Hi @grimbough,

by modifying your code slightly with a call to H5Eget_num(), it looks like the call to H5Eget_msg() is inadvertently causing the error stack to be cleared. When this happens, it looks as though HDF5 frees the memory allocated to the function/file name strings, but does not set the pointer to NULL and so your callback function is just printing out freed memory.

Several H5E APIs are designed specifically to avoid clearing the error stack, such as H5Ewalk2, for obvious reasons. However, it looks like either H5Eget_msg() was missed or was intentionally made this way for some reason. I’m afraid I don’t have an immediate solution to your problem, but I’ll look into fixing the issue with HDF5 not setting the pointers to NULL after freeing the memory and will see whether H5Eget_msg() can be changed to avoid clearing the error stack.

1 Like

Many thanks for the really clear explanation. I hadn’t thought of using H5Eget_num() to check the status of the stack.

Based on this my work around is to make a copy of the stack and then walk through that, and the copy isn’t changed by calls to H5Eget_msg() e.g.

hid_t estack_id_copy = H5Eget_current_stack();
herr_t eee = H5Ewalk2(estack_id_copy, H5E_WALK_DOWNWARD, &custom_print_cb, client_data);

This seems to be sufficient for me.