[svn-r5784] Purpose:

Bug fix.

Description:
    "strong" file closing feature was re-using free'd memory for objects which
    were still open in the file.

Solution:
    Used the "dmalloc" tools to determine where the memory was being
    re-used and re-arranged the code to avoid these cases.

Platforms tested:
    FreeBSD 4.6 (sleipnir)
This commit is contained in:
Quincey Koziol 2002-07-12 13:35:57 -05:00
parent d482fed23b
commit 5607e34da0

181
src/H5F.c
View File

@ -2594,6 +2594,17 @@ H5F_close(H5F_t *f)
/* Double-check that this file should be closed */
assert(1==f->nrefs);
/* Get the close degree from the file */
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT)
fc_degree = f->shared->lf->cls->fc_degree;
else
fc_degree = f->shared->fc_degree;
/* if close degree if "semi" and there are objects left open and we are
* holding open the file with this file ID, fail now */
if(fc_degree==H5F_CLOSE_SEMI && f->nopen_objs>0 && f->shared->nrefs==1)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open");
/*
* Unmount and close each child before closing the current file.
*/
@ -2605,109 +2616,107 @@ H5F_close(H5F_t *f)
} /* end if */
f->mtab.nmounts = 0;
/* Only attempt to close the file if this is the last shared file */
if (1==f->shared->nrefs) {
/* Close file according to close degree:
* H5F_CLOSE_WEAK: if there are still objects open, wait until
* they are all closed.
* H5F_CLOSE_SEMI: if there are still objects open, return fail;
* otherwise, close file.
* H5F_CLOSE_STRONG: if there are still objects open, close them
* first, then close file.
*/
switch(fc_degree) {
case H5F_CLOSE_WEAK:
/*
* If object headers are still open then delay deletion of
* resources until they have all been closed. Flush all
* caches and update the object eader anyway so that failing toi
* close all objects isn't a major problem. If the file is on
* the H5I_FILE list then move it to the H5I_FILE_CLOSING list
* instead.
*/
if (f->nopen_objs>0) {
#ifdef H5F_DEBUG
if (H5DEBUG(F)) {
fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
"open (file close will complete when %s closed)\n",
f->name,
f->nopen_objs,
1 == f->nopen_objs?" is":"s are",
1 == f->nopen_objs?"that header is":"those headers are");
}
#endif
/* Register an ID for closing the file later */
if (!f->closing)
f->closing = H5I_register(H5I_FILE_CLOSING, f);
HGOTO_DONE(SUCCEED);
} else {
if (f->closing) {
/* Get the number of opened object in file */
if(H5F_get_obj_count(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE, &oid_count) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file counts");
/* Get the close degree from the file */
if(f->shared->fc_degree == H5F_CLOSE_DEFAULT)
fc_degree = f->shared->lf->cls->fc_degree;
else
fc_degree = f->shared->fc_degree;
/* Close file according to close degree:
* H5F_CLOSE_WEAK: if there are still objects open, wait until
* they are all closed.
* H5F_CLOSE_SEMI: if there are still objects open, return fail;
* otherwise, close file.
* H5F_CLOSE_STRONG: if there are still objects open, close them
* first, then close file.
*/
switch(fc_degree) {
case H5F_CLOSE_WEAK:
/*
* If object headers are still open then delay deletion of
* resources until they have all been closed. Flush all
* caches and update the object eader anyway so that failing toi
* close all objects isn't a major problem. If the file is on
* the H5I_FILE list then move it to the H5I_FILE_CLOSING list
* instead.
*/
if (f->nopen_objs>0) {
#ifdef H5F_DEBUG
if (H5DEBUG(F)) {
fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
"open (file close will complete when %s closed)\n",
f->name,
f->nopen_objs,
1 == f->nopen_objs?" is":"s are",
1 == f->nopen_objs?"that header is":"those headers are");
fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
}
#endif
/* Register an ID for closing the file later */
if (!f->closing)
f->closing = H5I_register(H5I_FILE_CLOSING, f);
HGOTO_DONE(SUCCEED);
} else {
if (f->closing) {
} /* end if */
/* Indicate that the file will be closing */
closing=1;
} /* end else */
break;
case H5F_CLOSE_SEMI:
if (f->nopen_objs>0) {
#ifdef H5F_DEBUG
if (H5DEBUG(F)) {
fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
}
if (H5DEBUG(F)) {
fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still "
"open (file close will complete when %s closed)\n",
f->name,
f->nopen_objs,
1 == f->nopen_objs?" is":"s are",
1 == f->nopen_objs?"that header is":"those headers are");
}
#endif
} /* end if */
/* Indicate that the file will be closing */
closing=1;
} /* end else */
break;
case H5F_CLOSE_SEMI:
/* Check if we are allowed to close this file handle */
if(oid_count > 0)
/* Register an ID for closing the file later */
if (!f->closing)
f->closing = H5I_register(H5I_FILE_CLOSING, f);
HGOTO_DONE(SUCCEED);
} else {
if (!f->closing && f->shared->nrefs>1)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open");
/* Indicate that the file will be closing */
closing=1;
break;
} /* end else */
break;
case H5F_CLOSE_STRONG:
/* Forcefully close all opened objects in file */
do {
/* Allocate space for the IDs of objects still currently open */
if((oid_list = H5MM_malloc(oid_count*sizeof(hid_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
case H5F_CLOSE_STRONG:
/* Forcefully close all opened objects in file */
do {
/* Allocate space for the IDs of objects still currently open */
if((oid_list = H5MM_malloc(f->nopen_objs*sizeof(hid_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* Get the list of IDs of open objects */
if(H5F_get_obj_ids(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE, oid_list) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object list in file");
/* Try to close all the open objects */
for(i=0; i<oid_count; i++)
if(H5I_dec_ref(oid_list[i]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object");
/* Get the list of IDs of open objects */
if(H5F_get_obj_ids(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE, oid_list) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get object list in file");
/* Try to close all the open objects */
for(i=0; i<f->nopen_objs; i++)
if(H5I_dec_ref(oid_list[i]) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object");
/* Free the ID list */
if(oid_list != NULL)
H5MM_xfree(oid_list);
/* Free the ID list */
if(oid_list != NULL)
H5MM_xfree(oid_list);
} while(f->nopen_objs > 0);
/* Get the revised object count */
if(H5F_get_obj_count(f, H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE, &oid_count) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file counts");
} while(oid_count > 0);
/* Indicate that the file will be closing */
closing=1;
break;
/* Indicate that the file will be closing */
closing=1;
break;
default:
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree");
} /* end switch */
} /* end if */
default:
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree");
} /* end switch */
/* Only flush at this point if the file will be closed */
if(closing) {