root/opal/util/error.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_strerror_int
  2. opal_strerror_unknown
  3. opal_perror
  4. opal_strerror
  5. opal_strerror_r
  6. opal_error_register
  7. opal_delay_abort

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2005 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2007-2015 Los Alamos National Security, LLC. All rights
  14  *                         reserved.
  15  * Copyright (c) 2015      Research Organization for Information Science
  16  *                         and Technology (RIST). All rights reserved.
  17  * Copyright (c) 2017      FUJITSU LIMITED.  All rights reserved.
  18  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  19  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 
  27 #include "opal_config.h"
  28 
  29 #include <string.h>
  30 #include <errno.h>
  31 #include <stdio.h>
  32 #include <stdlib.h>
  33 #include <unistd.h>
  34 
  35 #include "opal/util/error.h"
  36 #include "opal/util/string_copy.h"
  37 #include "opal/constants.h"
  38 #include "opal/util/proc.h"
  39 #include "opal/util/printf.h"
  40 #include "opal/runtime/opal_params.h"
  41 
  42 #define MAX_CONVERTERS 5
  43 #define MAX_CONVERTER_PROJECT_LEN 10
  44 
  45 struct converter_info_t {
  46     int init;
  47     char project[MAX_CONVERTER_PROJECT_LEN];
  48     int err_base;
  49     int err_max;
  50     opal_err2str_fn_t converter;
  51 };
  52 typedef struct converter_info_t converter_info_t;
  53 
  54 /* all default to NULL */
  55 static converter_info_t converters[MAX_CONVERTERS] = {{0}};
  56 
  57 static int
  58 opal_strerror_int(int errnum, const char **str)
  59 {
  60     int i, ret = OPAL_SUCCESS;
  61     *str = NULL;
  62 
  63     for (i = 0 ; i < MAX_CONVERTERS ; ++i) {
  64         if (0 != converters[i].init &&
  65             errnum < converters[i].err_base &&
  66             converters[i].err_max < errnum) {
  67             ret = converters[i].converter(errnum, str);
  68             break;
  69         }
  70     }
  71 
  72     return ret;
  73 }
  74 
  75 
  76 /* caller must free string */
  77 static int
  78 opal_strerror_unknown(int errnum, char **str)
  79 {
  80     int i;
  81     *str = NULL;
  82 
  83     for (i = 0 ; i < MAX_CONVERTERS ; ++i) {
  84         if (0 != converters[i].init) {
  85             if (errnum < converters[i].err_base &&
  86                 errnum > converters[i].err_max) {
  87                 opal_asprintf(str, "Unknown error: %d (%s error %d)",
  88                          errnum, converters[i].project,
  89                          errnum - converters[i].err_base);
  90                 return OPAL_SUCCESS;
  91             }
  92         }
  93     }
  94 
  95     opal_asprintf(str, "Unknown error: %d", errnum);
  96 
  97     return OPAL_SUCCESS;
  98 }
  99 
 100 
 101 void
 102 opal_perror(int errnum, const char *msg)
 103 {
 104     int ret;
 105     const char* errmsg;
 106     ret = opal_strerror_int(errnum, &errmsg);
 107 
 108     if (NULL != msg && errnum != OPAL_ERR_IN_ERRNO) {
 109         fprintf(stderr, "%s: ", msg);
 110     }
 111 
 112     if (OPAL_SUCCESS != ret) {
 113         if (errnum == OPAL_ERR_IN_ERRNO) {
 114             perror(msg);
 115         } else {
 116             char *ue_msg;
 117             ret = opal_strerror_unknown(errnum, &ue_msg);
 118             fprintf(stderr, "%s\n", ue_msg);
 119             free(ue_msg);
 120         }
 121     } else {
 122         fprintf(stderr, "%s\n", errmsg);
 123     }
 124 
 125     fflush(stderr);
 126 }
 127 
 128 /* big enough to hold long version */
 129 #define UNKNOWN_RETBUF_LEN 50
 130 static char unknown_retbuf[UNKNOWN_RETBUF_LEN];
 131 
 132 const char *
 133 opal_strerror(int errnum)
 134 {
 135     int ret;
 136     const char* errmsg;
 137 
 138     if (errnum == OPAL_ERR_IN_ERRNO) {
 139         return strerror(errno);
 140     }
 141 
 142     ret = opal_strerror_int(errnum, &errmsg);
 143 
 144     if (OPAL_SUCCESS != ret) {
 145         char *ue_msg;
 146         ret = opal_strerror_unknown(errnum, &ue_msg);
 147         snprintf(unknown_retbuf, UNKNOWN_RETBUF_LEN, "%s", ue_msg);
 148         free(ue_msg);
 149         errno = EINVAL;
 150         return (const char*) unknown_retbuf;
 151     } else {
 152         return errmsg;
 153     }
 154 }
 155 
 156 
 157 int
 158 opal_strerror_r(int errnum, char *strerrbuf, size_t buflen)
 159 {
 160     const char* errmsg;
 161     int ret, len;
 162 
 163     ret = opal_strerror_int(errnum, &errmsg);
 164     if (OPAL_SUCCESS != ret) {
 165         if (errnum == OPAL_ERR_IN_ERRNO) {
 166             char *tmp = strerror(errno);
 167             opal_string_copy(strerrbuf, tmp, buflen);
 168             return OPAL_SUCCESS;
 169         } else {
 170             char *ue_msg;
 171             ret = opal_strerror_unknown(errnum, &ue_msg);
 172             len =  snprintf(strerrbuf, buflen, "%s", ue_msg);
 173             free(ue_msg);
 174             if (len > (int) buflen) {
 175                 errno = ERANGE;
 176                 return OPAL_ERR_OUT_OF_RESOURCE;
 177             } else {
 178                 errno = EINVAL;
 179                 return OPAL_SUCCESS;
 180             }
 181         }
 182     } else {
 183         len =  snprintf(strerrbuf, buflen, "%s", errmsg);
 184         if (len > (int) buflen) {
 185             errno = ERANGE;
 186             return OPAL_ERR_OUT_OF_RESOURCE;
 187         } else {
 188             return OPAL_SUCCESS;
 189         }
 190     }
 191 }
 192 
 193 
 194 int
 195 opal_error_register(const char *project, int err_base, int err_max,
 196                     opal_err2str_fn_t converter)
 197 {
 198     int i;
 199 
 200     for (i = 0 ; i < MAX_CONVERTERS ; ++i) {
 201         if (0 == converters[i].init) {
 202             converters[i].init = 1;
 203             opal_string_copy(converters[i].project, project, MAX_CONVERTER_PROJECT_LEN);
 204             converters[i].project[MAX_CONVERTER_PROJECT_LEN-1] = '\0';
 205             converters[i].err_base = err_base;
 206             converters[i].err_max = err_max;
 207             converters[i].converter = converter;
 208             return OPAL_SUCCESS;
 209         } else if (converters[i].err_base == err_base &&
 210                    converters[i].err_max == err_max &&
 211                    !strcmp (project, converters[i].project)) {
 212             converters[i].converter = converter;
 213             return OPAL_SUCCESS;
 214         }
 215     }
 216 
 217     return OPAL_ERR_OUT_OF_RESOURCE;
 218 }
 219 
 220 
 221 void
 222 opal_delay_abort(void)
 223 {
 224     // Though snprintf and strlen are not guaranteed to be async-signal-safe
 225     // in POSIX, it is async-signal-safe on many implementations probably.
 226 
 227     if (0 != opal_abort_delay) {
 228         int delay = opal_abort_delay;
 229         pid_t pid = getpid();
 230         char msg[100 + OPAL_MAXHOSTNAMELEN];
 231 
 232         if (delay < 0) {
 233             snprintf(msg, sizeof(msg),
 234                      "[%s:%05d] Looping forever "
 235                      "(MCA parameter opal_abort_delay is < 0)\n",
 236                      opal_process_info.nodename, (int) pid);
 237             write(STDERR_FILENO, msg, strlen(msg));
 238             while (1) {
 239                 sleep(5);
 240             }
 241         } else {
 242             snprintf(msg, sizeof(msg),
 243                      "[%s:%05d] Delaying for %d seconds before aborting\n",
 244                      opal_process_info.nodename, (int) pid, delay);
 245             write(STDERR_FILENO, msg, strlen(msg));
 246             do {
 247                 sleep(1);
 248             } while (--delay > 0);
 249         }
 250     }
 251 }

/* [<][>][^][v][top][bottom][index][help] */