summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2002-07-12 18:35:57 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2002-07-12 18:35:57 (GMT)
commit5607e34da0650f919ed7cb6a3b9dcb7a6c27f02d (patch)
treedf053f4ae2612262828e346b54d3c0bb7f8a0456 /src
parentd482fed23b592111eab1667d1afb6c401f9f830c (diff)
downloadhdf5-5607e34da0650f919ed7cb6a3b9dcb7a6c27f02d.zip
hdf5-5607e34da0650f919ed7cb6a3b9dcb7a6c27f02d.tar.gz
hdf5-5607e34da0650f919ed7cb6a3b9dcb7a6c27f02d.tar.bz2
[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)
Diffstat (limited to 'src')
-rw-r--r--src/H5F.c191
1 files changed, 100 insertions, 91 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 12999b0..1e6f3a7 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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) {
-
- /* 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) {
+ /* 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");
- }
+ 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) {
+ /* 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) {
#ifdef H5F_DEBUG
- if (H5DEBUG(F)) {
- fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
- }
+ if (H5DEBUG(F)) {
+ fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n");
+ }
#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)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open");
+ } /* end if */
/* 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");
-
- /* 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");
-
- /* Free the ID list */
- if(oid_list != NULL)
- H5MM_xfree(oid_list);
-
- /* 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);
+ case H5F_CLOSE_SEMI:
+ 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 && 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;
-
- default:
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree");
- } /* end switch */
- } /* end if */
+ } /* 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(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<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);
+ } while(f->nopen_objs > 0);
+
+ /* 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 */
/* Only flush at this point if the file will be closed */
if(closing) {