HP OpenVMS Systems

ask the wizard
Content starts here

Bug in exit handler example?

» close window

The Question is:

$DCLEXH Example doesn't compile.
In the OpenVMS Programming Concepts documentation the following elementary
example is given for implementing an exit handler :
#include <stdio>
#include <ssdef>
/* Exit control block */
struct {
       unsigned int *desblk;
       unsigned int (*exh)();
       unsigned int argcount;
       unsigned int *cond_value;
 }exitblock = {0, &exitrtn, 1, 0};
main() {
	unsigned int status;
	/* Declare the exit handler */
               status = SYS$DCLEXH(&exitblock);
               if ((status & 1) != 1)
int exitrtn (int condition ) {
        if ((status & 1) != 1)
	/* Clean up */
	 return 1;
        /* Normal exit */
                 return 0;
The example does not build owing to the conflict between the definition of
the exit handler routine (  function (int) returning int ) and
the declaration in the exitblock structure ( function () returning unsigned
int )
The system services reference implies that the exit handler must have at
least one parameter by which to pass the condition value of the exit (and
presumably the test in exitrtn () above should be for "condition").
How should this really look?

The Answer is :

  Thank you for bringing the problem in the OpenVMS documentation to
  the attention of the OpenVMS Wizard.
  The example program in the documentation uses old C syntax (VAX C),
  and has various problems when compiling under more recent C compilers
  such as Compaq C.
  The OpenVMS Wizard will be including the following example program
  and the BASIC example from topic 3483 in future OpenVMS documentation
  sets.  The attached program compiles cleanly under Compaq C V6.2 on
  OpenVMS Alpha V7.2-1, and operates as expected.
#include <lib$routines.h>
#include <ssdef.h>
#include <stddef.h>
#include <stdio.h>
#include <starlet.h>
#include <stsdef.h>
// Declare the Exit control block
  int ExitHandlerRtn( int *, int );
  unsigned int RetStat;
  //  Declare the variables used by the exit handler.
  //  Because of the environment the exit handler is
  //  invoked in, the use of static variables or other
  //  (non-stack local) storage is required.
  static unsigned int ConditionValue;
  static struct ECB
    unsigned int *Reserved;
    int (*HandlerRtn)(int *, int);
    unsigned int ArgCount;
    unsigned int *CondVal;
    unsigned int ApplVal;
    } ExitControlBlock;
  //  The following initializes the exit control block.
  //  The initialization of the argument count cell be
  //  easily replaced by an explicit specification of 2
  //  (as only the CondVal and ApplVal longwords exist),
  //  but the calculation accounts (transparently) for
  //  any user arguments added or removed from the end
  //  of the block.  The minimum value for the argument
  //  count is 1 longword, for the CondVal pointer...
  //  ApplVal is initialized with a random value...
  ExitControlBlock.Reserved = NULL;
  ExitControlBlock.HandlerRtn = ExitHandlerRtn;
  ExitControlBlock.ArgCount = ((sizeof( ExitControlBlock ) -
    offsetof( struct ECB, CondVal )) / sizeof( int ));
  ExitControlBlock.CondVal = &ConditionValue;
  ExitControlBlock.ApplVal = 303147;
  // Now declare the exit handler routine.
  RetStat = sys$dclexh( &ExitControlBlock );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    return RetStat;
  //  Now exit...
  //  (We should not get to the return statement...)
  RetStat = sys$exit( SS$_NORMAL );
  return RetStat;
//  Now for the exit handler routine.  This shows the one
//  value that is always passed, plus another value that
//  is application specific -- application-specific values
//  can be created by incrementing the argument count and
//  lengthening the exit control block.
int ExitHandlerRtn( int *CondVal, int ApplVal )
  printf("The exit handler is running...\n");
  printf("The condition value is: ...... %d\n", *CondVal );
  printf("A user-specified value is: ... %d\n", ApplVal );
  return SS$_NORMAL;

answer written or last revised on ( 17-FEB-2000 )

» close window