diff options
-rw-r--r-- | release_docs/RELEASE.txt | 2 | ||||
-rw-r--r-- | src/H5F.c | 53 | ||||
-rw-r--r-- | test/mount.c | 152 |
3 files changed, 206 insertions, 1 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 132bbdb..1510e41 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -296,6 +296,8 @@ Bug Fixes since HDF5-1.6.0 release Library ------- + - Fixed bug where unmounted files could cause the library to go into + an infinite loop when shutting down. QAK - 2005/06/30 - The library didn't save the information of family driver in file. The original file member size was lost after file was closed (see bug #213). This has been fixed by saving driver name and member @@ -415,6 +415,53 @@ done: /*------------------------------------------------------------------------- + * Function: H5F_term_unmount_cb + * + * Purpose: H5F_term_interface' callback function. This routine + * unmounts child files from files that are in the "closing" + * state. + * + * Programmer: Quincey Koziol + * Thursday, Jun 30, 2005 + * + * Modification: + * + *------------------------------------------------------------------------- + */ +static int +H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void UNUSED *key) +{ + H5F_t *f = (H5F_t *)obj_ptr; /* Alias for search info */ + unsigned u; /* Local index */ + int ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5F_term_unmount_cb) + + assert(f); + + if(f->mtab.nmounts) { + /* Unmount all child files */ + for (u=0; u<f->mtab.nmounts; u++) { + f->mtab.child[u].file->mtab.parent = NULL; + if(H5G_close(f->mtab.child[u].group)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group") + if(H5F_close(f->mtab.child[u].file)<0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file") + } /* end if */ + f->mtab.nmounts = 0; + + /* Decrement reference count for file */ + H5I_dec_ref(obj_id); + } /* end if */ + else + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "no files to unmount") + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5F_term_unmount_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5F_term_interface * * Purpose: Terminate this interface: free all memory and reset global @@ -444,7 +491,11 @@ H5F_term_interface(void) if (H5_interface_initialize_g) { if ((n=H5I_nmembers(H5I_FILE))!=0) { H5I_clear_type(H5I_FILE, FALSE); - } else if (0==(n=H5I_nmembers(H5I_FILE_CLOSING))) { + } else if ((n=H5I_nmembers(H5I_FILE_CLOSING))!=0) { + /* Attempt to unmount any child files from files that are closing */ + (void)H5I_search(H5I_FILE_CLOSING, H5F_term_unmount_cb, NULL); + } + else { H5I_dec_type_ref(H5I_FILE); H5I_dec_type_ref(H5I_FILE_CLOSING); H5_interface_initialize_g = 0; diff --git a/test/mount.c b/test/mount.c index 389c48e..bff93d6 100644 --- a/test/mount.c +++ b/test/mount.c @@ -1520,6 +1520,157 @@ error: /*------------------------------------------------------------------------- + * Function: test_missing_unmount + * + * Purpose: Test that the library correctly closes open files when they + * have child files that have not been unmounted. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Thursday, June 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_missing_unmount(hid_t fapl) +{ + hid_t fid1=-1, fid2=-1, fid3=-1; /* File IDs */ + hid_t gidA=-1, gidE=-1, gidM=-1; /* Group IDs */ + hid_t gidAE=-1, gidAEM=-1; /* Group IDs */ + char filename1[1024], + filename2[1024], + filename3[1024]; /* Name of files to mount */ + + TESTING("missing unmount"); + + h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1); + h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2); + h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3); + + /* Create file #1 */ + if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidA) < 0) + TEST_ERROR + + if(H5Fclose(fid1) < 0) + TEST_ERROR + + + /* Create file #2 */ + if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidE = H5Gcreate(fid2, "E", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidE) < 0) + TEST_ERROR + + if(H5Fclose(fid2) < 0) + TEST_ERROR + + + /* Create file #3 */ + if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidM = H5Gcreate(fid3, "M", (size_t)0)) < 0) + TEST_ERROR + + if(H5Gclose(gidM) < 0) + TEST_ERROR + + if(H5Fclose(fid3) < 0) + TEST_ERROR + + + /* Re-open files and mount file #2 in file #1 and file #3 in file #2 */ + if((fid1 = H5Fopen(filename1, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if((gidA = H5Gopen(fid1, "A")) < 0) + TEST_ERROR + + /* Close file #1 */ + if(H5Fclose(fid1) < 0) + TEST_ERROR + + if((fid2 = H5Fopen(filename2, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if(H5Fmount(gidA, ".", fid2, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open group in mounted file */ + if((gidAE = H5Gopen(fid2, "A/E")) < 0) + TEST_ERROR + + /* Close file #2 */ + if(H5Fclose(fid2) < 0) + TEST_ERROR + + if((fid3 = H5Fopen(filename3, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + TEST_ERROR + + if(H5Fmount(gidAE, ".", fid3, H5P_DEFAULT) < 0) + TEST_ERROR + + /* Open group in mounted file */ + if((gidAEM = H5Gopen(fid3, "A/E/M")) < 0) + TEST_ERROR + + /* Close file #3 */ + if(H5Fclose(fid3) < 0) + TEST_ERROR + + /* (Still have all file #2 & #3 mounted and groups open in all three files) */ + + /* Unmount file #2 & #3 */ + if(H5Funmount(gidAE,".") < 0) + TEST_ERROR + + /* Skip unmounting file #2 from file #1 */ + + /* Close groups in mounted file */ + if(H5Gclose(gidAEM) < 0) + TEST_ERROR + + if(H5Gclose(gidAE) < 0) + TEST_ERROR + + /* Close group in top file */ + if(H5Gclose(gidA) < 0) + TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Gclose(gidM); + H5Gclose(gidE); + H5Gclose(gidAEM); + H5Gclose(gidAE); + H5Gclose(gidA); + H5Fclose(fid3); + H5Fclose(fid2); + H5Fclose(fid1); + } H5E_END_TRY; + return 1; +} /* end test_missing_unmount() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test file mounting @@ -1560,6 +1711,7 @@ main(void) nerrors += test_close(fapl); nerrors += test_mount_after_close(fapl); nerrors += test_mount_after_unmount(fapl); + nerrors += test_missing_unmount(fapl); if (nerrors) goto error; puts("All mount tests passed."); |