Fix a confusing situation, and eliminate a potential memory leak.
MPI-1 does not say whether an errorhandler obtained via MPI_ERRHANDLER_GET (or MPI_COMM_GET_ERRHANDLER or ...) needs to be ERRHANDLER_FREE'd or not. I don't think it does, but some users will probably disagree. So per the lengthy comment in src/mpi/c/comm_get_errhandler.c, we increment the refcount whenever GET is invoked. This can lead to a memory leak in FINALIZE if the user GET's some intrinsic error handlers -- we'll increment the refcount, which means that it will never get to 0 during FINALIZE like it should. So add a little extra logic to ensure that they are OMPI_OBJ_DESTROY'ed during FINALIZE like they should be. This commit was SVN r3661.
Этот коммит содержится в:
родитель
102a18ff6f
Коммит
5cbf975955
@ -44,6 +44,16 @@ ompi_errhandler_t ompi_mpi_errhandler_null;
|
|||||||
ompi_errhandler_t ompi_mpi_errors_are_fatal;
|
ompi_errhandler_t ompi_mpi_errors_are_fatal;
|
||||||
ompi_errhandler_t ompi_mpi_errors_return;
|
ompi_errhandler_t ompi_mpi_errors_return;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local state to know when the three intrinsics have been freed; see
|
||||||
|
* the errhandler destructor for more info.
|
||||||
|
*/
|
||||||
|
static bool null_freed = false;
|
||||||
|
static bool fatal_freed = false;
|
||||||
|
static bool return_freed = false;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize OMPI errhandler infrastructure
|
* Initialize OMPI errhandler infrastructure
|
||||||
*/
|
*/
|
||||||
@ -105,13 +115,34 @@ int ompi_errhandler_init(void)
|
|||||||
*/
|
*/
|
||||||
int ompi_errhandler_finalize(void)
|
int ompi_errhandler_finalize(void)
|
||||||
{
|
{
|
||||||
/* Remove errhandler F2C table */
|
/* Forcibly release the intrinsic error handlers because in order
|
||||||
|
to be safe, we increase the refcount on error handlers in
|
||||||
OBJ_RELEASE(ompi_errhandler_f_to_c_table);
|
MPI_*_GET_ERRHANDLER and MPI_ERRHANDLER_GET. If these handles
|
||||||
|
are never ERRHANDLER_FREEd, then the refcount will not be
|
||||||
/* All done */
|
decremented and they will not naturally get to 0 during
|
||||||
|
FINALIZE. Hence, we RELEASE on the intrinsics until they are
|
||||||
|
freed. */
|
||||||
|
|
||||||
return OMPI_SUCCESS;
|
while (!null_freed) {
|
||||||
|
OBJ_DESTRUCT(&ompi_mpi_errhandler_null);
|
||||||
|
}
|
||||||
|
while (!fatal_freed) {
|
||||||
|
OBJ_DESTRUCT(&ompi_mpi_errors_are_fatal);
|
||||||
|
}
|
||||||
|
while (!return_freed) {
|
||||||
|
OBJ_DESTRUCT(&ompi_mpi_errors_return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JMS Add stuff here checking for unreleased errorhandlers,
|
||||||
|
similar to communicators, info handles, etc. */
|
||||||
|
|
||||||
|
/* Remove errhandler F2C table */
|
||||||
|
|
||||||
|
OBJ_RELEASE(ompi_errhandler_f_to_c_table);
|
||||||
|
|
||||||
|
/* All done */
|
||||||
|
|
||||||
|
return OMPI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -206,6 +237,15 @@ static void ompi_errhandler_destruct(ompi_errhandler_t *errhandler)
|
|||||||
ompi_pointer_array_set_item(ompi_errhandler_f_to_c_table,
|
ompi_pointer_array_set_item(ompi_errhandler_f_to_c_table,
|
||||||
errhandler->eh_f_to_c_index, NULL);
|
errhandler->eh_f_to_c_index, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset the static state if we're releasing one of the
|
||||||
|
intrinsics */
|
||||||
|
|
||||||
|
if (&ompi_mpi_errhandler_null == errhandler) {
|
||||||
|
null_freed = true;
|
||||||
|
} else if (&ompi_mpi_errors_are_fatal == errhandler) {
|
||||||
|
fatal_freed = true;
|
||||||
|
} else if (&ompi_mpi_errors_return == errhandler) {
|
||||||
|
return_freed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user