H5Aexists says attributes are being written to datasets, but they're not there

OS: Ubuntu 22.04
HDF5 1.14.3

Per the title I am experiencing a problem where I am calling a function that I wrote to write attributes to a collection of datasets which I had previously created in the code (CUDA file) using a fork to mpirun that executes a binary which contains some PHDF5 that wrote the datasets because they are large.

After returning from this mpirun command, the parent process continues on, and runs this function to write attributes to the datasets because PHDF5 attribute writing is a novice trap AFAIK:

void writeAttributes(const std::string filename, const int Nx, const int Ny, const int Nz){
    hid_t file_id, dset_id;

    herr_t status;

    file_id = H5Fopen(filename.data(), H5F_ACC_RDWR, H5P_DEFAULT);
    if (file_id < 0) {
        std::cerr << "Error opening file: " << filename << std::endl;
        return;
    }

    const char *dset_names[8] = {"rho", "rhovx", "rhovy", "rhovz", "Bx", "By", "Bz", "e"};

    for (int idset = 0; idset < 8; idset++){
        std::cout << "Opening dataset " << dset_names[idset] << " for attribute writing" << std::endl;
        dset_id = H5Dopen(file_id, dset_names[idset], H5P_DEFAULT);
        if (dset_id < 0) {
            std::cerr << "Error opening dataset: " << dset_names[idset] << std::endl;
            status = H5Fclose(file_id);
            return;
        }
        addAttributes(dset_id, Nx, Ny, Nz);
        verifyAttributes(dset_id);
        // status = H5Dclose(dset_id);
    }

    std::cout << "Closing dset_id, and file_id" << std::endl;
    status = H5Dclose(dset_id); 
    status = H5Fclose(file_id);
    return;
} 

As you can see there is plenty of error-checking in here, and inside the two functions addAttributes, and verifyAttributes. Nothing trips, in fact verifyAttributes, which uses H5Aexists, reports that all the attributes exist, for every dataset, and the code halts without a problem. However, after running $ h5dump -n 1 --contents=1 fluid_data.h5 I get the following:

HDF5 "fluid_data.h5" {
FILE_CONTENTS {
 group      /
 dataset    /Bx
 dataset    /By
 dataset    /Bz
 dataset    /e
 dataset    /rho
 dataset    /rhovx
 dataset    /rhovy
 dataset    /rhovz
 }
}

Where are these attributes that were supposed to exist? Same kind of deal with $ h5ls Going a little crazy over here, any help is appreciated.

Just solved this, so I wanted to close the loop, and explain what I did.

The basic solution was to take the function writeAttributes(const char **fargs) outside of the execution context of the CUDA process. This CUDA process was forked from a parent Python process, which was forked by a bash shell. To write the simulation data into a .h5 file, the CUDA process forks an mpirun call into a PHDF5 execution context. My suspicion was that there was something holding over from this mpirun fork which prevented the attributes from being written, so what I attempted was to place all the attribute writing code into another binary, and fork this after the the datasets were written. It worked!

Here’s the code snippet from the .cu file:

    // Fork PHDF5 dataset writing with mpirun system call 
    std::cout << "Writing datasets with PHDF5" << std::endl;
    int ret = callPHDF5(path_to_data, Nx, Ny, Nz, shm_name, fluid_data_size, num_proc, phdf5_bin_name);
    if (ret != 0) {
        std::cerr << "Error executing PHDF5 command" << std::endl;
    }

    // Write attributes serially to datasets - PHDF5 attribute writing is novice trap AFAIK
    std::cout << "Writing dataset attributes with HDF5" << std::endl;
    ret = callAttributes(path_to_data, Nx, Ny, Nz, attr_bin_name); // trying to write attributes in current context doesn't work
    if (ret != 0) {
        std::cerr << "Error executing PHDF5 command" << std::endl;
    /* Rest of main */
    return 0;
}

int callAttributes(const std::string file_name, const int Nx, const int Ny, const int Nz, const std::string attr_bin_name){
    std::string addatt_command = "./" + attr_bin_name + " " + file_name + " " + std::to_string(Nx) + " "
                                    + std::to_string(Ny) + " " + std::to_string(Nz);
    
    char cwd[1024];
    if (getcwd(cwd, sizeof(cwd)) != nullptr) {
        std::cout << "Current working directory: " << cwd << std::endl;
    } else {
       std::cerr << "Failed to get current working directory" << std::endl;
    }

    std::cout << "Executing command: " << addatt_command << std::endl;
    int ret = std::system(addatt_command.data()); 
    return ret;
}
1 Like