mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-04-12 17:31:09 +08:00
[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
This commit is contained in:
parent
43f091f462
commit
5e98cfee43
@ -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
|
||||
|
53
src/H5F.c
53
src/H5F.c
@ -413,6 +413,53 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
@ -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;
|
||||
|
152
test/mount.c
152
test/mount.c
@ -1518,6 +1518,157 @@ error:
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* 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
|
||||
@ -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.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user