1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/*
* Copyright (C) by Argonne National Laboratory
* See COPYRIGHT in top-level directory
*/
/*
Exercise attribute routines.
This version checks for correct behavior of the copy and delete functions
on an attribute, particularly the correct behavior when the routine returns
failure.
*/
#include <stdio.h>
#include "mpi.h"
#include "mpitest.h"
int test_communicators(void);
void abort_msg(const char *, int);
int copybomb_fn(MPI_Comm, int, void *, void *, void *, int *);
int deletebomb_fn(MPI_Comm, int, void *, void *);
int main(int argc, char **argv)
{
int errs;
MTest_Init(&argc, &argv);
errs = test_communicators();
MTest_Finalize(errs);
return MTestReturnValue(errs);
}
/*
* MPI 1.2 Clarification: Clarification of Error Behavior of
* Attribute Callback Functions
* Any return value other than MPI_SUCCESS is erroneous. The specific value
* returned to the user is undefined (other than it can't be MPI_SUCCESS).
* Proposals to specify particular values (e.g., user's value) failed.
*/
/* Return an error as the value */
int copybomb_fn(MPI_Comm oldcomm, int keyval, void *extra_state,
void *attribute_val_in, void *attribute_val_out, int *flag)
{
/* Note that if (sizeof(int) < sizeof(void *), just setting the int
* part of attribute_val_out may leave some dirty bits
*/
*flag = 1;
return MPI_ERR_OTHER;
}
/* Set delete flag to 1 to allow the attribute to be deleted */
static int delete_flag = 0;
int deletebomb_fn(MPI_Comm comm, int keyval, void *attribute_val, void *extra_state)
{
if (delete_flag)
return MPI_SUCCESS;
return MPI_ERR_OTHER;
}
void abort_msg(const char *str, int code)
{
fprintf(stderr, "%s, err = %d\n", str, code);
MPI_Abort(MPI_COMM_WORLD, code);
}
int test_communicators(void)
{
MPI_Comm dup_comm_world, d2;
int world_rank, world_size, key_1;
int err, errs = 0;
MPI_Aint value;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
#ifdef DEBUG
if (world_rank == 0) {
printf("*** Attribute copy/delete return codes ***\n");
}
#endif
MPI_Comm_dup(MPI_COMM_WORLD, &dup_comm_world);
MPI_Barrier(dup_comm_world);
MPI_Comm_set_errhandler(dup_comm_world, MPI_ERRORS_RETURN);
value = -11;
if ((err = MPI_Comm_create_keyval(copybomb_fn, deletebomb_fn, &key_1, &value)))
abort_msg("Keyval_create", err);
err = MPI_Comm_set_attr(dup_comm_world, key_1, (void *) (MPI_Aint) world_rank);
if (err) {
errs++;
printf("Error with first put\n");
}
err = MPI_Comm_set_attr(dup_comm_world, key_1, (void *) (MPI_Aint) (2 * world_rank));
if (err == MPI_SUCCESS) {
errs++;
printf("delete function return code was MPI_SUCCESS in put\n");
}
/* Because the attribute delete function should fail, the attribute
* should *not be removed* */
err = MPI_Comm_delete_attr(dup_comm_world, key_1);
if (err == MPI_SUCCESS) {
errs++;
printf("delete function return code was MPI_SUCCESS in delete\n");
}
err = MPI_Comm_dup(dup_comm_world, &d2);
if (err == MPI_SUCCESS) {
errs++;
printf("copy function return code was MPI_SUCCESS in dup\n");
}
if (err != MPI_ERR_OTHER) {
int lerrclass;
MPI_Error_class(err, &lerrclass);
if (lerrclass != MPI_ERR_OTHER) {
errs++;
printf("dup did not return an error code of class ERR_OTHER; ");
printf("err = %d, class = %d\n", err, lerrclass);
}
}
#ifndef USE_STRICT_MPI
/* Another interpretation is to leave d2 unchanged on error */
if (err && d2 != MPI_COMM_NULL) {
errs++;
printf("dup did not return MPI_COMM_NULL on error\n");
}
#endif
delete_flag = 1;
MPI_Comm_free(&dup_comm_world);
MPI_Comm_free_keyval(&key_1);
return errs;
}
|