Skip to content

Commit 4012bed

Browse files
committed
grequest: Fix propagation of errors from callback functions.
Signed-off-by: Lisandro Dalcin <[email protected]>
1 parent 57ac9e2 commit 4012bed

File tree

1 file changed

+46
-23
lines changed

1 file changed

+46
-23
lines changed

ompi/request/grequest.c

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,55 @@
2424
#include "ompi/request/grequest.h"
2525
#include "ompi/mpi/fortran/base/fint_2_int.h"
2626

27-
/**
27+
/*
2828
* Internal function to specialize the call to the user provided free_fn
2929
* for generalized requests.
3030
* @return The return value of the user specified callback or MPI_SUCCESS.
3131
*/
32-
static inline int ompi_grequest_internal_free(ompi_grequest_t* greq)
32+
static inline int ompi_grequest_invoke_free(ompi_grequest_t* greq)
3333
{
34-
int rc = MPI_SUCCESS;
34+
int rc = OMPI_SUCCESS;
35+
MPI_Fint ierr;
36+
3537
if (NULL != greq->greq_free.c_free) {
38+
if (greq->greq_funcs_are_c) {
39+
rc = greq->greq_free.c_free(greq->greq_state);
40+
} else {
41+
greq->greq_free.f_free((MPI_Aint*)greq->greq_state, &ierr);
42+
rc = OMPI_FINT_2_INT(ierr);
43+
}
3644
/* We were already putting query_fn()'s return value into
3745
* status.MPI_ERROR but for MPI_{Wait,Test}*. If there's a
3846
* free callback to invoke, the standard says to use the
3947
* return value from free_fn() callback, too.
4048
*/
41-
if (greq->greq_funcs_are_c) {
42-
greq->greq_base.req_status.MPI_ERROR =
43-
greq->greq_free.c_free(greq->greq_state);
44-
} else {
45-
MPI_Fint ierr;
46-
greq->greq_free.f_free((MPI_Aint*)greq->greq_state, &ierr);
47-
greq->greq_base.req_status.MPI_ERROR = OMPI_FINT_2_INT(ierr);
49+
if (OMPI_SUCCESS != rc) {
50+
greq->greq_base.req_status.MPI_ERROR = rc;
4851
}
49-
rc = greq->greq_base.req_status.MPI_ERROR;
5052
}
5153
return rc;
5254
}
5355

56+
57+
/*
58+
* Internal function to dispatch the call to the user provided free_fn
59+
* for generalized requests. The freeing code executes as soon as both
60+
* wait/free and complete have occured.
61+
* @return The return value of the user specified callback or MPI_SUCCESS.
62+
*/
63+
static inline int ompi_grequest_internal_free(ompi_grequest_t* greq)
64+
{
65+
int rc = OMPI_SUCCESS;
66+
67+
if (REQUEST_COMPLETE(&greq->greq_base) && greq->greq_user_freed) {
68+
rc = ompi_grequest_invoke_free(greq);
69+
/* The free_fn() callback should be invoked only once. */
70+
if (NULL != greq->greq_free.c_free)
71+
greq->greq_free.c_free = NULL;
72+
}
73+
return rc;
74+
}
75+
5476
/*
5577
* See the comment in the grequest destructor for the weird semantics
5678
* here. If the request has been marked complete via a call to
@@ -66,14 +88,10 @@ static int ompi_grequest_free(ompi_request_t** req)
6688
ompi_grequest_t* greq = (ompi_grequest_t*)*req;
6789
int rc = OMPI_SUCCESS;
6890

69-
if( greq->greq_user_freed ) {
70-
return OMPI_ERR_OUT_OF_RESOURCE;
71-
}
7291
greq->greq_user_freed = true;
73-
if( REQUEST_COMPLETE(*req) ) {
74-
rc = ompi_grequest_internal_free(greq);
75-
}
76-
if (OMPI_SUCCESS == rc ) {
92+
rc = ompi_grequest_internal_free(greq);
93+
94+
if (OMPI_SUCCESS == rc) {
7795
OBJ_RELEASE(*req);
7896
*req = MPI_REQUEST_NULL;
7997
}
@@ -180,7 +198,7 @@ int ompi_grequest_start(
180198
ompi_request_t** request)
181199
{
182200
ompi_grequest_t *greq = OBJ_NEW(ompi_grequest_t);
183-
if(greq == NULL) {
201+
if (greq == NULL) {
184202
return OMPI_ERR_OUT_OF_RESOURCE;
185203
}
186204
/* We call RETAIN here specifically to increase the refcount to 2.
@@ -211,13 +229,14 @@ int ompi_grequest_start(
211229
int ompi_grequest_complete(ompi_request_t *req)
212230
{
213231
ompi_grequest_t* greq = (ompi_grequest_t*)req;
232+
bool greq_release = !REQUEST_COMPLETE(req);
214233
int rc;
215234

216235
rc = ompi_request_complete(req, true);
217-
if( greq->greq_user_freed ) {
236+
if (OMPI_SUCCESS == rc && greq_release) {
218237
rc = ompi_grequest_internal_free(greq);
238+
OBJ_RELEASE(req);
219239
}
220-
OBJ_RELEASE(req);
221240
return rc;
222241
}
223242

@@ -237,6 +256,11 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
237256
int rc = OMPI_SUCCESS;
238257
ompi_grequest_t *g = (ompi_grequest_t*) request;
239258

259+
/* MPI mandates that query_fn must be called after the request is
260+
* completed. Make sure the caller does not break the contract.
261+
*/
262+
assert( REQUEST_COMPLETE(request) );
263+
240264
/* MPI-3 mandates that the return value from the query function
241265
* (i.e., the int return value from the C function or the ierr
242266
* argument from the Fortran function) must be returned to the
@@ -268,9 +292,8 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
268292
rc = OMPI_FINT_2_INT(ierr);
269293
}
270294
}
271-
if( MPI_SUCCESS != rc ) {
295+
if (OMPI_SUCCESS != rc) {
272296
status->MPI_ERROR = rc;
273297
}
274298
return rc;
275299
}
276-

0 commit comments

Comments
 (0)