diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2002-07-12 18:35:57 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2002-07-12 18:35:57 (GMT) |
commit | 5607e34da0650f919ed7cb6a3b9dcb7a6c27f02d (patch) | |
tree | df053f4ae2612262828e346b54d3c0bb7f8a0456 /src | |
parent | d482fed23b592111eab1667d1afb6c401f9f830c (diff) | |
download | hdf5-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.c | 191 |
1 files changed, 100 insertions, 91 deletions
@@ -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) { |