Example in ILE C: Logging software errors (program API without pointers)
This ILE C program calls the Log Software Error (QPDLOGER) API to perform first-failure data capture (FFDC) without using pointers.
The ILE C program physically moves the data that is pointed to, as shown at (1), which slows down performance.
Note: By using the code examples, you agree to the terms
of the Code license and disclaimer information.
/*********************************************************************/
/* */
/*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 */