[svn-r19386] Purpose: Fix assertion failure caused by fractal heap header file pointer

Description:
The fractal heap header structure keeps a pointer to the file associated with
it.  However, it is possible for that file pointer to be closed while the
header is still in cache (through the shared file pointer).  Previously, the
header's file pointer was not updated and subsequently pointed to an invalid
file structure.  Modified fractal heap code to update the file pointer every
time the header is accessed.

Tested: jam, linew, amani (h5committest)
This commit is contained in:
Neil Fortner 2010-09-15 10:29:38 -05:00
parent 96c26d2b17
commit cb9a804f82
4 changed files with 147 additions and 7 deletions

View File

@ -244,6 +244,9 @@ Bug Fixes since HDF5-1.8.0 release
Library
-------
- Fixed a bug that could occur when getting information for a new-style
group that was previously opened through a file handle that was
later closed. (NAF - 2010/09/15)
- Added define check in H5public.h if stdint.h is supported by the C++
compiler. This define is only available on Windows with VS2010 and
using CMake to build the library. (ADB - 2010/09/13 - Bug 1938)

View File

@ -859,9 +859,6 @@ HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr-
if(NULL == (hdr = H5HF_hdr_protect(fh->f, dxpl_id, heap_addr, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
/* Set the shared heap header's file context for this operation */
hdr->f = fh->f;
/* Delete heap, starting with header (unprotects header) */
if(H5HF_hdr_delete(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
@ -913,9 +910,6 @@ HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
if(hdr->file_rc)
hdr->pending_delete = TRUE;
else {
/* Set the shared heap header's file context for this operation */
hdr->f = f;
/* Delete heap now, starting with header (unprotects header) */
if(H5HF_hdr_delete(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")

View File

@ -552,6 +552,9 @@ H5HF_hdr_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
/* Set the header's address */
hdr->heap_addr = addr;
/* Update header's file pointer */
hdr->f = f;
/* Set the return value */
ret_value = hdr;

View File

@ -2975,7 +2975,7 @@ test_size(hid_t fapl, H5HF_create_t *cparam)
FAIL_STACK_ERROR
/* Re-open the heap */
if(NULL == (fh = H5HF_open(f, H5P_DATASET_XFER_DEFAULT, fh_addr)))
if(NULL == (fh = H5HF_open(f, dxpl, fh_addr)))
FAIL_STACK_ERROR
/* Check the heap's size */
@ -3019,6 +3019,145 @@ error:
return(1);
} /* test_size() */
/*-------------------------------------------------------------------------
* Function: test_reopen_hdr
*
* Purpose: Test opening a header through one file handle, closing
* that file handle, then reopening through a different file
* handle that was open the whole time. The header should
* stay in cache between the two opens.
*
* Return: Success: 0
* Failure: 1
*
* Programmer: Neil Fortner
* Tuesday, September 14, 2010
*
*-------------------------------------------------------------------------
*/
static unsigned
test_reopen_hdr(hid_t fapl, H5HF_create_t *cparam)
{
hid_t file1 = -1; /* File ID */
hid_t file2 = -2; /* File ID */
hid_t dxpl = H5P_DATASET_XFER_DEFAULT; /* DXPL to use */
char filename[FHEAP_FILENAME_LEN]; /* Filename to use */
H5F_t *f = NULL; /* Internal file object pointer */
H5HF_t *fh = NULL; /* Fractal heap wrapper */
haddr_t fh_addr; /* Address of fractal heap */
hsize_t heap_size; /* Total size of heap on disk */
/* Set the filename to use for this test (dependent on fapl) */
h5_fixname(FILENAME[0], fapl, filename, sizeof(filename));
/* Create the file to work on */
if((file1 = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
FAIL_STACK_ERROR
/* Get a pointer to the internal file object */
if(NULL == (f = (H5F_t *)H5I_object(file1)))
FAIL_STACK_ERROR
/* Ignore metadata tags in the file's cache */
if (H5AC_ignore_tags(f) < 0)
FAIL_STACK_ERROR
/* Display testing message */
TESTING("reopening header through different file")
/* Create absolute heap */
if(NULL == (fh = H5HF_create(f, dxpl, cparam)))
FAIL_STACK_ERROR
/* Get heap's address */
if(H5HF_get_heap_addr(fh, &fh_addr) < 0)
FAIL_STACK_ERROR
if(!H5F_addr_defined(fh_addr))
TEST_ERROR
/* Insert an object */
if(add_obj(fh, dxpl, (size_t)0, (size_t)10, NULL, NULL) < 0)
TEST_ERROR
/* Close the fractal heap */
if(H5HF_close(fh, dxpl) < 0)
FAIL_STACK_ERROR
fh = NULL;
/* Close the file */
if(H5Fclose(file1) < 0)
FAIL_STACK_ERROR
/* Re-open the file */
if((file1 = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
FAIL_STACK_ERROR
/* Re-open the file again */
if((file2 = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0)
FAIL_STACK_ERROR
/* Get a pointer to the internal file object (file1) */
if(NULL == (f = (H5F_t *)H5I_object(file1)))
FAIL_STACK_ERROR
/* Ignore metadata tags in the file's cache */
if (H5AC_ignore_tags(f) < 0)
FAIL_STACK_ERROR
/* Open the heap */
if(NULL == (fh = H5HF_open(f, dxpl, fh_addr)))
FAIL_STACK_ERROR
/* Close the heap */
if(H5HF_close(fh, dxpl) < 0)
FAIL_STACK_ERROR
fh = NULL;
/* Close the file (file1) */
if(H5Fclose(file1) < 0)
FAIL_STACK_ERROR
/* Get a pointer to the internal file object (file2) */
if(NULL == (f = (H5F_t *)H5I_object(file2)))
FAIL_STACK_ERROR
/* Reopen the heap */
if(NULL == (fh = H5HF_open(f, dxpl, fh_addr)))
FAIL_STACK_ERROR
/* Check the heap's size */
heap_size = 0;
if(H5HF_size(fh, dxpl, &heap_size) < 0)
FAIL_STACK_ERROR
/* Close the fractal heap */
if(H5HF_close(fh, H5P_DATASET_XFER_DEFAULT) < 0)
FAIL_STACK_ERROR
/* Close the file (file2) */
if(H5Fclose(file2) < 0)
FAIL_STACK_ERROR
/* All tests passed */
PASSED()
return(0);
error:
H5E_BEGIN_TRY {
if(fh)
H5HF_close(fh, dxpl);
H5Fclose(file1);
H5Fclose(file2);
} H5E_END_TRY;
return(1);
} /* test_reopen_hdr() */
#ifndef QAK2
/*-------------------------------------------------------------------------
@ -16159,6 +16298,7 @@ curr_test = FHEAP_TEST_NORMAL;
nerrors += test_id_limits(fapl, &small_cparam);
nerrors += test_filtered_create(fapl, &small_cparam);
nerrors += test_size(fapl, &small_cparam);
nerrors += test_reopen_hdr(fapl, &small_cparam);
#else /* QAK */
HDfprintf(stderr, "Uncomment tests!\n");
#endif /* QAK */