[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:
Quincey Koziol 2005-07-01 00:35:29 -05:00
parent 43f091f462
commit 5e98cfee43
3 changed files with 206 additions and 1 deletions

View File

@ -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

View File

@ -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;

View File

@ -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.");