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 */