This program illustrates how to use APIs to log software errors using FFDC.
This program calls the Log Software Error (QPDLOGER) API to perform FFDC without the use of pointers. The OPM program physically moves the data that is pointed to, as shown at (1), which slows down performance.
/*********************************************************************/
/* */
/*Program Name: FFDCPGM1 */
/* */
/*Program Language: ILE C */
/* */
/*Description: This program illustrates how to use APIs to log */
/* software errors using FFDC. */
/* */
/* */
/*Header Files Included: except */
/* stdio */
/* string */
/* qmhchgem */
/* qpdloger */
/* qusec */
/* */
/*APIs Used: QPDLOGER */
/* */
/*********************************************************************/
/*********************************************************************/
/*********************************************************************/
/* System Includes */
/*********************************************************************/
#include <except.h> /* from QSYSINC/H */
#include <stdio.h> /* from QSYSINC/H */
#include <string.h> /* from QSYSINC/H */
/*********************************************************************/
/* Miscellaneous Includes */
/*********************************************************************/
#include <qmhchgem.h>
#include <qpdloger.h>
#include <qusec.h>
/*********************************************************************/
/* Structures */
/*********************************************************************/
typedef struct {
void *parm1;
void *parm2;
char *pgm_name;
int pgm_name_size;
} ffdc_info_t;
/*********************************************************************/
/* Prototypes */
/*********************************************************************/
void UNEXPECTED_HDLR(_INTRPT_Hndlr_Parms_T *);
/*********************************************************************/
/* FUNCTION NAME: main */
/* */
/* FUNCTION: Generates exception and then passes control */
/* to exception handler. */
/* */
/* INPUT: Two character strings. */
/* */
/* OUTPUT: NONE */
/* */
/* EXCEPTIONS: CPFxxxx - All unexpected CPF exceptions */
/* MCHxxxx - All unexpected MCH exceptions */
/* */
/*********************************************************************/
void main(int argc, char *argv[])
{
/*******************************************************************/
/* NOTE: argv will contain the parameters passed in to this */
/* function. In this case, two parameters are passed */
/* in. */
/*******************************************************************/
/*******************************************************************/
/* The argv parameter contains the parameters that were passed as */
/* character arrays. argv[0] contains the program name, and the */
/* parameter(s) starts with argv[1]. */
/*******************************************************************/
char *nulptr; /* Pointer used to generate error */
char pgm_name[30]; /* Program name */
volatile ffdc_info_t ffdc_info; /* FFDC info for unexpected error */
/*******************************************************************/
/* Set up FFDC information for unexpected error. */
/*******************************************************************/
ffdc_info.parm1 = argv[1];
ffdc_info.parm2 = argv[2];
ffdc_info.pgm_name = pgm_name;
memcpy(pgm_name, argv[0], strlen(argv[0]));
ffdc_info.pgm_name_size = strlen(argv[0]);
/*******************************************************************/
/* Enable the exception handler, and pass ffdc_info into the */
/* exception handler via the communications area so that data */
/* can be used for FFDC. */
/*******************************************************************/
#pragma exception_handler (UNEXPECTED_HDLR, ffdc_info, 0, _C2_MH_ESCAPE)
/*******************************************************************/
/* Set the pointer to null, then try to increment. This will */
/* generate an MCH3601 error that will be trapped by the */
/* unexpected handler. */
/*******************************************************************/
nulptr = NULL;
nulptr++;
#pragma disable_handler
} /* main */
/*********************************************************************/
/* FUNCTION NAME: UNEXPECTED_HDLR */
/* */
/* FUNCTION: Handle unexpected exception. This exception */
/* handler is used to log the software error via */
/* FFDC. */
/* */
/* INPUT: Interrupt handler information */
/* */
/* OUTPUT: NONE */
/* */
/* EXCEPTIONS: CPFxxxx - All unexpected CPF exceptions */
/* MCHxxxx - All unexpected MCH exceptions */
/* */
/*********************************************************************/
void UNEXPECTED_HDLR(_INTRPT_Hndlr_Parms_T *errmsg)
{
typedef struct {
char obj_name[30];
char obj_lib[30];
char obj_type[10];
} obj_info_t;
typedef struct {
int data_offset;
int data_length;
} data_info_t;
char pgm_suspected[10],
msg_id[12],
msg_key[4],
print_job_log,
data[2*(sizeof(char *))],
*data_item,
ile_mod_name[11];
int point_of_failure,
num_items,
num_objs;
data_info_t data_info[2];
obj_info_t obj_info[1];
ffdc_info_t *ffdc_info;
Qus_EC_t ErrorCode;
ErrorCode.Bytes_Provided = 0;
/*******************************************************************/
/* Getting pointer in local storage to the Communications Area. */
/*******************************************************************/
ffdc_info = (ffdc_info_t *)(errmsg->Com_Area);
/*******************************************************************/
/* Need to notify message handler that we will handle the error. */
/* Leave the message in the job log, just mark it handled. */
/*******************************************************************/
QMHCHGEM(&(errmsg->Target), /* Invocation pointer */
0, /* Call stack counter */
(char *)&errmsg->Msg_Ref_Key,/* Message key */
"*HANDLE ", /* Modification option */
"", /* Reply text */
0, /* Reply text length */
&ErrorCode); /* Error code */
/*******************************************************************/
/* Set up the suspected program. */
/*******************************************************************/
memcpy(pgm_suspected, "*PRV ", 10);
/*******************************************************************/
/* Set up the detection identifier. */
/*******************************************************************/
memset(msg_id, ' ', 12);
memcpy(msg_id, errmsg->Msg_Id, 7);
/*******************************************************************/
/* Set up the message key. */
/*******************************************************************/
memcpy(msg_key, (char *)&errmsg->Msg_Ref_Key, 4);
/*******************************************************************/
/* Set up point of failure. Since this example program is small */
/* and we know where the error occurred, we will just put a dummy */
/* value in. However, this can be very useful information in */
/* larger programs. */
/*******************************************************************/
point_of_failure = 100;
/*******************************************************************/
/* Set up to print the job log. */
/*******************************************************************/
print_job_log = 'Y';
/*******************************************************************/
/* Set up data items. */
/*******************************************************************/
data_item = data;
/*******************************************************************/
/* Put in first parameter. */
/*******************************************************************/
memcpy(data_item, (char *)ffdc_info->parm1, sizeof(char *)); (1)
/*******************************************************************/
/* Add in the second parameter. */
/*******************************************************************/
data_item += sizeof(char *);
memcpy(data_item, (char *)ffdc_info->parm2, sizeof(char *));
/*******************************************************************/
/* Reset the data item pointer. */
/*******************************************************************/
data_item -= sizeof(char *);
/*******************************************************************/
/* Set up data item offset/length information. */
/*******************************************************************/
data_info[0].data_offset = 0;
data_info[0].data_length = sizeof(char *);
data_info[1].data_offset = sizeof(char *);
data_info[1].data_length = sizeof(char *);
/*******************************************************************/
/* Set up the number of data items. In this case we only have one.*/
/*******************************************************************/
num_items = 2;
/*******************************************************************/
/* Set up the object name array. In this case, we have no objects */
/* to dump, but we will put dummy values in to illustrate. */
/*******************************************************************/
memcpy(obj_info[0].obj_name, "OBJUSRSPC ", 30);
memcpy(obj_info[0].obj_lib, "QTEMP ", 30);
memcpy(obj_info[0].obj_type, "*USRSPC ", 10);
/*******************************************************************/
/* Set the number of objects in name array. */
/*******************************************************************/
num_objs = 0;
/*******************************************************************/
/* Set up the ILE module name. */
/*******************************************************************/
memcpy(ile_mod_name, ffdc_info->pgm_name, ffdc_info->pgm_name_size);
/*******************************************************************/
/* Call QPDLOGER to perform FFDC. */
/*******************************************************************/
ErrorCode.Bytes_Provided = sizeof(ErrorCode);
QPDLOGER(pgm_suspected,
msg_id,
msg_key,
point_of_failure,
&print_job_log,
data_item,
data_info,
num_items,
obj_info,
num_objs,
&ErrorCode,
ile_mod_name);
} /* UNEXPECTED_HDLR */