From 80d6d8e4727b438194a881b57a35e72d029550bb Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 3 Sep 2003 21:05:16 -0500 Subject: [svn-r7442] Purpose: Bug fix Description: The VFL driver ID in a file's access proprty list wasn't being reference counted correctly, causing the VFL driver to get prematurely closed after several calls to "H5Pget_access_plist->H5Pclose". Solution: Increment VFL driver ID reference count when copy of file's access property list is made in H5Pget_access_plist() Platforms tested: FreeBSD 4.9 (sleipnir) h5committest --- release_docs/RELEASE.txt | 3 +++ src/H5F.c | 11 ++++++++-- src/H5FDprivate.h | 2 -- test/tmisc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 9214522..b946348 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -56,6 +56,9 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Corrected bug in repeated calls to H5Pget_access_plist() which would + incorrectly manage reference counts of internal information and + eventually blow up. QAK - 2003/09/02 - Return rank of the array datatype on successful call to H5Tget_array_dims(). QAK - 2003/08/30 - Corrected bug in H5Tdetect_class which was not correctly detecting diff --git a/src/H5F.c b/src/H5F.c index 5ac2d6f..a99c3e7 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -922,14 +922,18 @@ H5Fget_access_plist(hid_t file_id) if (H5F_acs_close(ret_value, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information"); + /* Increment the reference count on the driver ID and insert it into the property list */ + if(H5I_inc_ref(f->shared->lf->driver_id)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver") if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID"); + /* Set the driver "info" in the property list */ driver_info = H5FD_fapl_get(f->shared->lf); - if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info"); + /* Set the file close degree appropriately */ if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) { HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree"); } else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) { @@ -1812,6 +1816,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d haddr_t stored_eoa; /*relative end-of-addr in file */ unsigned tent_flags; /*tentative flags */ char driver_name[9]; /*file driver name/version */ + H5FD_class_t *drvr; /* File driver class info */ hbool_t driver_has_cmp; /*`cmp' callback defined? */ hsize_t userblock_size = 0; int super_vers; /* Superblock version # */ @@ -1838,7 +1843,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d * it is the application's responsibility to never open the same file * more than once at a time. */ - driver_has_cmp = H5FD_has_cmp(fapl_id); + if((drvr=H5FD_get_class(fapl_id))==NULL) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class") + driver_has_cmp = (NULL!=drvr->cmp); /* * Opening a file is a two step process. First we try to open the file in diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 7993e91..447bef9 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -21,8 +21,6 @@ #include "H5FDpublic.h" -#define H5FD_has_cmp(id) (NULL!=H5FD_get_class(id)->cmp) - H5_DLL int H5FD_term_interface(void); H5_DLL H5FD_class_t *H5FD_get_class(hid_t id); H5_DLL hsize_t H5FD_sb_size(H5FD_t *file); diff --git a/test/tmisc.c b/test/tmisc.c index ba255ba..b7f17ac 100644 --- a/test/tmisc.c +++ b/test/tmisc.c @@ -191,6 +191,9 @@ unsigned m13_rdata[MISC13_DIM1][MISC13_DIM2]; /* Data read from dataset #define MISC14_DSET3_NAME "Dataset3" #define MISC14_METADATA_SIZE 4096 +/* Definitions for misc. test #15 */ +#define MISC15_FILE "tmisc15.h5" + /**************************************************************** ** ** test_misc1(): test unlinking a dataset from a group and immediately @@ -2565,6 +2568,56 @@ test_misc14(void) /**************************************************************** ** +** test_misc15(): Test that checking a file's access property list +** more than once correctly increments internal reference counts. +** +****************************************************************/ +static void +test_misc15(void) +{ + hid_t file; /* File ID */ + hid_t fapl; /* File access property list */ + herr_t ret; /* Generic return value */ + + /* Create the file & get it's FAPL */ + file = H5Fcreate(MISC15_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(file, FAIL, "H5Fcreate"); + + fapl = H5Fget_access_plist(file); + CHECK(fapl, FAIL, "H5Fget_access_plist"); + + ret = H5Pclose(fapl); + CHECK(ret, FAIL, "H5Pclose"); + + ret = H5Fclose(file); + CHECK(ret, FAIL, "H5Fclose"); + + /* Open the file & get it's FAPL again */ + file = H5Fopen(MISC15_FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file, FAIL, "H5Fopen"); + + fapl = H5Fget_access_plist(file); + CHECK(fapl, FAIL, "H5Fget_access_plist"); + + ret = H5Pclose(fapl); + CHECK(ret, FAIL, "H5Pclose"); + + ret = H5Fclose(file); + CHECK(ret, FAIL, "H5Fclose"); + + /* Verify that the file is still OK */ + ret = H5Fis_hdf5(MISC15_FILE); + CHECK(ret, FAIL, "H5Fis_hdf5"); + + file = H5Fopen(MISC15_FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + CHECK(file, FAIL, "H5Fopen"); + + ret = H5Fclose(file); + CHECK(ret, FAIL, "H5Fclose"); +} /* end test_misc15() */ + +/**************************************************************** +** ** test_misc(): Main misc. test routine. ** ****************************************************************/ @@ -2588,6 +2641,7 @@ test_misc(void) test_misc12(); /* Test VL-strings in chunked datasets operating correctly */ test_misc13(); /* Test that a user block can be insert in front of file contents */ test_misc14(); /* Test that deleted dataset's data is removed from sieve buffer correctly */ + test_misc15(); /* Test that checking a file's access property list more than once works */ } /* test_misc() */ @@ -2626,4 +2680,5 @@ cleanup_misc(void) HDremove(MISC13_FILE_1); HDremove(MISC13_FILE_2); HDremove(MISC14_FILE); + HDremove(MISC15_FILE); } -- cgit v0.12