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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/****************************************************************
* *
* Copyright (c) 2001-2018 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_stdio.h"
#include <stdarg.h>
#include <errno.h>
#include "gtm_multi_thread.h"
#include "gtm_putmsg_list.h"
#include "gtmimagename.h"
#include "error.h"
#include "util.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gtmmsg.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "anticipatory_freeze.h"
#include "toktyp.h"
#include "cgp.h"
GBLREF boolean_t created_core;
GBLREF boolean_t dont_want_core;
GBLREF boolean_t run_time;
GBLREF char cg_phase;
GBLREF gd_region *gv_cur_region;
GBLREF jnlpool_addrs_ptr_t jnlpool;
GBLREF int gtm_errno;
GBLREF void (*stx_error_va_fptr)(int in_error, ...); /* Function pointer for stx_error_va() so this can avoid
* pulling stx_error() into gtmsecshr.
*/
error_def(ERR_ASSERT);
error_def(ERR_GTMASSERT);
error_def(ERR_GTMASSERT2);
error_def(ERR_GTMCHECK);
error_def(ERR_JOBINTRRETHROW);
error_def(ERR_JOBINTRRQST);
error_def(ERR_MEMORY);
error_def(ERR_OUTOFSPACE);
error_def(ERR_REPEATERROR);
error_def(ERR_REPLONLNRLBK);
error_def(ERR_STACKOFLOW);
error_def(ERR_TPRETRY);
int rts_error_va(void *csa, int argcnt, va_list var);
/* ----------------------------------------------------------------------------------------
* WARNING: For chained error messages, all messages MUST be followed by an fao count;
* ======= zero MUST be specified if there are no parameters.
* ----------------------------------------------------------------------------------------
*/
/* coverity[+kill] */
int rts_error(int argcnt, ...)
{
va_list var;
sgmnt_addrs *csa;
jnlpool_addrs_ptr_t local_jnlpool; /* needed by PTHREAD_CSA_FROM_GV_CUR_REGION */
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
PTHREAD_CSA_FROM_GV_CUR_REGION(csa, local_jnlpool);
VAR_START(var, argcnt);
return rts_error_va(csa, argcnt, var);
}
/* coverity[+kill] */
int rts_error_csa(void *csa, int argcnt, ...)
{
va_list var;
VAR_START(var, argcnt);
return rts_error_va(csa, argcnt, var);
}
int rts_error_va(void *csa, int argcnt, va_list var)
{
int msgid;
va_list var_dup;
const err_ctl *ctl;
boolean_t was_holder;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
# ifdef DEBUG
if (TREF(rts_error_unusable) && !TREF(rts_error_unusable_seen))
{
TREF(rts_error_unusable_seen) = TRUE;
/* The below assert ensures that this rts_error invocation is appropriate in the current context of the code that
* triggered this rts_error. If ever this assert fails, investigate the window of DBG_MARK_RTS_ERROR_UNUSABLE
* and DBG_MARK_RTS_ERROR_USABLE in the call-stack.
*/
assert(FALSE);
}
# endif
PTHREAD_MUTEX_LOCK_IF_NEEDED(was_holder); /* get thread lock in case threads are in use */
/* Note that rts_error does not return most of the times (control gets transferred somewhere else) so no point
* unlocking thread mutex at the end of this function. This means that if one thread gets an error, the rest of
* the threads might wait if/when they need to make a PTHREAD_MUTEX_LOCK_IF_NEEDED call. But that is considered
* okay since the process is anyways going to terminate due to the error in one thread. This is at least true
* for the current use of threads in mupip. If/when threads are used in GT.M this will need to be revisited.
*/
VAR_COPY(var_dup, var);
if (-1 == gtm_errno)
gtm_errno = errno;
msgid = va_arg(var_dup, int);
/* If there was a previous fatal error that did not yet get printed, do it before overwriting the
* util_output buffer with the about-to-be-handled nested error. This way one will see ALL the
* fatal error messages (e.g. assert failures) in the order in which they occurred instead of
* just the last nested one.
*/
if (DUMPABLE)
PRN_ERROR;
/* This is simply a place holder msg to signal tp restart or otherwise rethrow an error */
if ((ERR_TPRETRY == msgid) || (ERR_REPEATERROR == msgid) || (ERR_REPLONLNRLBK == msgid) || (ERR_JOBINTRRQST == msgid)
|| (ERR_JOBINTRRETHROW == msgid))
{
SET_ERROR_CONDITION(msgid); /* sets "error_condition" & "severity" */
} else
{ /* Note this message is not flushed out. This is so user console is not polluted with messages that are going to be
* handled by a ZTRAP. If ZTRAP is not active, the message will be flushed out in mdb_condition_handler - which is
* usually the top level handler or is rolled over into by higher handlers.
*/
if (IS_GTMSECSHR_IMAGE)
util_out_print(NULL, RESET);
SET_ERROR_CONDITION(msgid); /* sets "error_condition" & "severity" */
if (!run_time && (CGP_PARSE == cg_phase) && !DUMP)
{
(*stx_error_va_fptr)(msgid, var_dup);
TREF(director_token) = TK_ERROR;
return FALSE;
}
gtm_putmsg_list(csa, argcnt, var);
if (DUMPABLE)
created_core = dont_want_core = FALSE; /* We can create a(nother) core now */
if (IS_GTMSECSHR_IMAGE)
util_out_print(NULL, OPER); /* gtmsecshr errors always immediately pushed out */
}
va_end(var_dup);
va_end(var);
DRIVECH(msgid); /* Drive the topmost (inactive) condition handler */
/* Note -- at one time there was code here to catch if we returned from the condition handlers
* when the severity was error or above. That code had to be removed because of several errors
* that are handled and returned from. An example is EOF errors. SE 9/2000
*/
return FALSE;
}
|