summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-07-01 05:35:29 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-07-01 05:35:29 (GMT)
commit5e98cfee43a6755c258d0e7b9a3babea73c0534f (patch)
treec15e9463dba9a700e6542e6556eaee71564c1a3e
parent43f091f462202a84a863f000582e75fd6c04e6f4 (diff)
downloadhdf5-5e98cfee43a6755c258d0e7b9a3babea73c0534f.zip
hdf5-5e98cfee43a6755c258d0e7b9a3babea73c0534f.tar.gz
hdf5-5e98cfee43a6755c258d0e7b9a3babea73c0534f.tar.bz2
[svn-r11009] Purpose:
Bug fix Description: When a series of files is mounted on one another and one of those files is not unmounted, the library gets confused at shutdown and goes into an infinite loop in the file interface. Solution: If there are still files left in the "closing" state when shutting down the file API, iterate over those file IDs and unmount any child files that we find mounted on those files. Platforms tested: FreeBSD 4.11 (sleipnir) Too minor to require h5committest
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5F.c53
-rw-r--r--test/mount.c152
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
diff --git a/src/H5F.c b/src/H5F.c
index 63e108b..8c73e86 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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.");