1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *   Copyright (C) 2004 University of Chicago.
4  *   See COPYRIGHT notice in top-level directory.
5  */
6 
7 #include <stdarg.h>
8 #include <stdio.h>
9 
10 #include "mpioimpl.h"
11 #include "adio_extern.h"
12 
13 /* MPICH error handling implementation */
14 /* FIXME: These external prototypes should be included from
15    mpich/src/include/mpiext.h */
16 int MPIR_Err_create_code_valist(int, int, const char [], int, int,
17 				const char [], const char [], va_list );
18 int MPIR_Err_is_fatal(int);
19 
20 void MPIR_Get_file_error_routine( MPI_Errhandler,
21 				  void (**)(MPI_File *, int *, ...),
22 				  int * );
23 int MPIR_File_call_cxx_errhandler( MPI_File *, int *,
24 				   void (*)(MPI_File *, int *, ... ) );
25 
26 typedef int (* MPIR_Err_get_class_string_func_t)(int error, char *str, int length);
27 void MPIR_Err_get_string( int, char *, int, MPIR_Err_get_class_string_func_t );
28 
29 struct MPID_Comm;
30 int MPID_Abort(struct MPID_Comm *comm, int mpi_errno, int exit_code, const char *error_msg);
31 
MPIO_Err_create_code(int lastcode,int fatal,const char fcname[],int line,int error_class,const char generic_msg[],const char specific_msg[],...)32 int MPIO_Err_create_code(int lastcode, int fatal, const char fcname[],
33 			 int line, int error_class, const char generic_msg[],
34 			 const char specific_msg[], ... )
35 {
36     va_list Argp;
37     int error_code;
38 
39     va_start(Argp, specific_msg);
40 
41     error_code = MPIR_Err_create_code_valist(lastcode, fatal, fcname, line,
42 					     error_class, generic_msg,
43 					     specific_msg, Argp);
44 
45     va_end(Argp);
46 
47     return error_code;
48 }
49 
MPIO_Err_return_file(MPI_File mpi_fh,int error_code)50 int MPIO_Err_return_file(MPI_File mpi_fh, int error_code)
51 {
52     MPI_Errhandler e;
53     void (*c_errhandler)(MPI_File *, int *, ... );
54     int  kind;   /* Error handler kind (see below) */
55     char error_msg[4096];
56     int len;
57 
58     /* If the file pointer is not valid, we use the handler on
59        MPI_FILE_NULL (MPI-2, section 9.7).  For now, this code assumes that
60        MPI_FILE_NULL has the default handler (return).  FIXME.  See
61        below - the set error handler uses ADIOI_DFLT_ERR_HANDLER;
62     */
63 
64     /* First, get the handler and the corresponding function */
65     if (mpi_fh == MPI_FILE_NULL) {
66 	e = ADIOI_DFLT_ERR_HANDLER;
67     }
68     else {
69 	ADIO_File fh;
70 
71 	fh = MPIO_File_resolve(mpi_fh);
72 	e = fh->err_handler;
73     }
74 
75     /* Actually, e is just the value provide by the MPICH routines
76        file_set_errhandler.  This is actually a *pointer* to the
77        errhandler structure.  We don't know that, so we ask
78        the MPICH code to translate this object into an error handler.
79        kind = 0: errors are fatal
80        kind = 1: errors return
81        kind = 2: errors call function
82     */
83     if (e == MPI_ERRORS_RETURN || e == MPIR_ERRORS_THROW_EXCEPTIONS || !e) {
84 	/* FIXME: This is a hack in case no error handler was set */
85 	kind = 1;
86 	c_errhandler = 0;
87     }
88     else {
89 	MPIR_Get_file_error_routine( e, &c_errhandler, &kind );
90     }
91 
92     /* --BEGIN ERROR HANDLING-- */
93     if (MPIR_Err_is_fatal(error_code) || kind == 0)
94     {
95 	ADIOI_Snprintf(error_msg, 4096, "I/O error: ");
96 	len = (int)strlen(error_msg);
97 	MPIR_Err_get_string(error_code, &error_msg[len], 4096-len, NULL);
98 	MPID_Abort(NULL, MPI_SUCCESS, error_code, error_msg);
99     }
100     /* --END ERROR HANDLING-- */
101     else if (kind == 2) {
102 	(*c_errhandler)( &mpi_fh, &error_code, 0 );
103     }
104     else if (kind == 3) {
105 	MPIR_File_call_cxx_errhandler( &mpi_fh, &error_code, c_errhandler );
106     }
107 
108     /* kind == 1 just returns */
109     return error_code;
110 }
111 
MPIO_Err_return_comm(MPI_Comm mpi_comm,int error_code)112 int MPIO_Err_return_comm(MPI_Comm mpi_comm, int error_code)
113 {
114     /* note: MPI calls inside the MPICH implementation are prefixed
115      * with an "N", indicating a nested call.
116      */
117     MPI_Comm_call_errhandler(mpi_comm, error_code);
118     return error_code;
119 }
120