Skip to content

Commit 64b7ae0

Browse files
committed
grequest callback return values and Fortran status
A little background first: the status object being updated here based on the callbacks' behavior is an internal req->req_status. At this level we're not directly updating the top level MPI_Status from the user. And the design is to put the callback return values in the req->req_status.MPI_ERROR. (and whether that propagates back into the top level MPI_Status is handled elsewhere, where the code knows whether it's in a MPI_Waitall or MPI_Wait etc). The problems fixed here are: 1. for Fortran the callback uses a stack variable fstatus that's a Fortran status object, then copies those values back into the req->req_status. But that steps on the design described above: it writes a garbage value from the stack into the MPI_ERROR field when it was supposed to leave the value untouched. If I make a test where I manually put garbage into fstatus it does make its way up the chain and make MPI_Wait fail. So I fixed this by initializing fstatus with an MPI_Status_c2f 2. the free_fn() callback never had its return value placed into any of the status.MPI_ERROR locations, and the standard specifically calls out that it's the free_fn() return value that's supposed to go into status.MPI_ERROR. Signed-off-by: Mark Allen <markalle@us.ibm.com>
1 parent 4da9d91 commit 64b7ae0

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

ompi/request/grequest.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* All rights reserved.
1212
* Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved.
1313
* Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
14+
* Copyright (c) 2021 IBM Corporation. All rights reserved.
1415
* $COPYRIGHT$
1516
*
1617
* Additional copyrights may follow
@@ -121,16 +122,24 @@ static void ompi_grequest_construct(ompi_grequest_t* greq)
121122
*/
122123
static void ompi_grequest_destruct(ompi_grequest_t* greq)
123124
{
125+
int rc;
124126
MPI_Fint ierr;
125127

126128
if (greq->greq_free.c_free != NULL) {
127129
if (greq->greq_funcs_are_c) {
128-
greq->greq_free.c_free(greq->greq_state);
130+
rc = greq->greq_free.c_free(greq->greq_state);
129131
} else {
130132
greq->greq_free.f_free((MPI_Aint*)greq->greq_state, &ierr);
133+
rc = OMPI_FINT_2_INT(ierr);
131134
}
132135
}
133136

137+
/* We were already putting query_fn()'s return value into
138+
* status.MPI_ERROR but for MPI_{Wait,Test}* the standard
139+
* says use the free_fn() callback too.
140+
*/
141+
greq->greq_base.req_status.MPI_ERROR = rc;
142+
134143
OMPI_REQUEST_FINI(&greq->greq_base);
135144
}
136145

@@ -214,8 +223,21 @@ int ompi_grequest_invoke_query(ompi_request_t *request,
214223
if (g->greq_funcs_are_c) {
215224
rc = g->greq_query.c_query(g->greq_state, status);
216225
} else {
226+
/* request->req_status.MPI_ERROR was initialized to success
227+
* and it's meant to be unmodified in the case of callback
228+
* success, and set when callbacks return a failure. But
229+
* if we leave fstatus uninitialized this sets
230+
* req_status.MPI_ERROR to whatever happened to be on the
231+
* stack at fstatus (f_query isn't supposed to directly set
232+
* its status.MPI_ERROR, according to the standard)
233+
*
234+
* So the Status_c2f below only really cares about transferring
235+
* the MPI_ERROR setting into fstatus so that when it's transferred
236+
* back in the f2c call, it has the starting value.
237+
*/
217238
MPI_Fint ierr;
218239
MPI_Fint fstatus[sizeof(MPI_Status) / sizeof(int)];
240+
MPI_Status_c2f(status, fstatus);
219241
g->greq_query.f_query((MPI_Aint*)g->greq_state, fstatus, &ierr);
220242
MPI_Status_f2c(fstatus, status);
221243
rc = OMPI_FINT_2_INT(ierr);

0 commit comments

Comments
 (0)