summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.");