Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ signals(sig) — Micro Focus COBOL 4.0.5

Media Vault

Software Library

Restoration Projects

Artifacts Sought

   =========================================================================
                       M I C R O  F O C U S  C O B O L

                                   V4.0.5

                           Running Under The DG/UX
                           Operating System Version 5.4R3.10
                           On The AViiON
   =========================================================================

                           SIGNAL HANDLING
                           ===============

   This document should be considered as additional information for the
   section "Mixing C and COBOL Programs" in the Chapter "Mixed Language
   Programming" in the COBOL User Guide. It describes the Micro Focus
   support for two routines, cobpostsighandler and cobremovesighandler,
   that you can use to complement or override the signal handling used by
   the run-time system.

   TABLE OF CONTENTS
   =================
   OVERVIEW
   OPERATION
       Example
       Writing signal handlers
           Coping with more than one handler for the same signal
           Converting signal handlers written for signal()
       Coping with Third Party software that uses signals
       signal() vs sigaction()


   OVERVIEW
   ========
   This chapter describes the calls you need to make if you want to use
   signal handling in your application, especially if you are mixing COBOL
   and C in your application.

   The run-time system (RTS) sets up default signal handlers for all signals
   whose OS default action would be to cause termination. These default
   handlers make sure that the COBOL system is properly cleaned up before
   terminating. Hence, any open files are closed (to prevent file
   corruption), the terminal is reset to a sane state, user posted exit and
   error procedures are executed, and so on.

   The RTS also uses signal handling to provide various functionality. For
   example, interrupt key detection, Animator Zoom interrupt key, Job
   Control, ALT/CTRL detection, and so on.

   This COBOL system provides two routines that you can use to complement or
   override the signal handling used by the run-time system (RTS):
   cobpostsighandler and cobremovesighandler.

   These routines allow multiple handlers per signal and allow you to
   prioritize use of these handlers. They should only be used from inside a
   C program, not least of because, you will need to #include <signal.h> for
   the signal values, which vary between platforms.

   These routines should be used instead of the OS signal calls (signal(),
   sigaction(), etc) which only provide the ability to post a single signal
   handler for each call which often prevents more than one application
   being able to work together reliably.

   For example, if you used one of the OS signal calls to post a signal
   handler before invoking a COBOL program, then your signal handler would
   be overridden. Whereas, if you used one of the OS signal calls after
   invoking a COBOL program, the default RTS handler, additional COBOL
   functionality and user posted signal handlers would all be overridden,
   causing unexpected results.

   OPERATION
   =========
   These routines have the form:

   sighandler = cobpostsighandler (signal, priority, handler) ;

   where:

       signal      specifies the signal, as defined in the <signal.h>
                   include file.
                   Type: integer.

       priority    specifies the priority of <handler>. The range of
                   possible priority values is 1 to 254, with 254 being of
                   the highest priority. Values 127 and 129 - 139 are
                   reserved for use by Micro Focus. Also see below.
                   Type: integer.

       handler     is the name of your signal handler.
                   Type: This must be a C function returning an integer
                         value.

   returning:

       sighandler  is a pointer that can be used to remove your signal
                   handler later. If this value is NULL, then you can not
                   post a signal handler for this signal. This could be due
                   to lack of memory or the signal being "disabled" by the
                   tunable signal_regime - Also see below.
                   Type: (void *) pointer.


   cobremovesighandler (sighandler) ;

   where:

       sighandler  is the pointer returned when posting your signal handler
                   using a previous cobpostsighandler call.

   returning:

       (Nothing)   There is no return value from this call.


   The cobpostsighandler() call adds your specified handler into the list of
   handlers for the specified signal, at the specified priority. A pointer
   is returned which should be used in any subsequent cobremovesighandler()
   call. If the handler can not be posted for the signal for any reason,
   then NULL is returned.

   The cobremovesighandler() call removes a posted handler from the list of
   handlers for the appropriate signal. The <sighandler> passed must be the
   value returned from a previous cobpostsighandler() call.

   You should be aware of the following when using the cobpostsighandler()
   routine:

   o   The RTS also uses cobpostsighandler() to post all of its signal
       handling.

   o   The default RTS signal handlers are posted with priority 127. Default
       handlers are posted for all signals whose OS default action would
       cause termination. The RTS default handlers either make sure that
       the COBOL system has been cleaned up before terminating, or cause the
       signal to be ignored.

       These default signal handlers assume that the signals were generated
       by the OS due to a serious error or that a signal has been
       unexpectedly raised. Hence, they usually produce an RTS message,
       such as 114 or 115.

   o   The RTS provides various functionality via the use of signal handlers.
       These handlers are posted with a priority in the range of 129 to 139.

   o   Hence, you should post a signal handler with priority 128 if you want
       it to override (or be processed before) the default RTS handler for
       that signal. You should use a priority of 126 (or less) if you want
       to make sure that your handler is processed after the default RTS
       handler (if the default RTS handler does not exit).

   o   When a signal is received, the handler posted with the highest
       priority, for that signal, is called. The signal handler should take
       any appropriate action (eg. setting a flag to be acted upon later)
       and then either return a value of 0 or non-zero.

       If the signal handler returns 0, then no further signal handlers will
       be processed.

       If the signal handler returns a non-zero value, then the handler with
       the next highest priority, for that signal, will be called. This
       continues until all the handlers, for that signal, have been called
       or until one of the handlers returns a value of 0.

   o   If two handlers are posted with the same priority, the last one
       posted will be executed first.

   o   If the same handler is posted twice, and neither of them are removed
       via cobremovesighandler(), then the handler will be executed twice
       (assuming the handler, and all handlers executed in between, do not
       return a value of 0).

   o   Once you have posted a handler, you do not need to re-post it. The
       handler will be called each time that signal is received (assuming
       that the first receipt of the signal does not cause termination). If
       you only want your handler to be executed once, then you must remove
       it, via cobremovesighandler(), in your signal handler.

   o   Whilst processing signal handlers, the signal will be blocked. This
       prevents recursion if the same signal is received in rapid succession.

   o   A signal handler must return normally. That is, it should return a
       value using the C syntax

              return(num) ;

       and should not use any other function that terminates a signal
       handler function, such as longjmp(). Doing so will cause the signal
       to remain blocked, preventing any further signal to be processed
       successfully.

   o   Certain signals are generated by the operating system when a serious
       error has occurred. Catching these signals could cause unexpected
       and potentially dangerous results. You should not catch any of the
       following signals:

           SIGBUS
           SIGSEGV
           SIGEMT
           SIGILL
           SIGIOT / SIGABRT
           SIGSYS
           SIGFPE
           SIGTRAP

   o   Preventing the RTS from processing certain signals could stop certain
       RTS functionality working. If you catch any of these signals (with
       a priority of 140 or more), then your signal handler should return a
       non-zero value so that the RTS's handler is also executed. The
       signals concerned include:

           SIGCHLD
           SIGPIPE
           SIGUSR1
           SIGUSR2
           SIGVTALRM
           SIGWINCH
           SIGCONT
           SIGTSTP
           SIGTTIN
           SIGTTOU

   o   The cobpostsighandler and cobremovesighandler functions are only
!      available with Micro Focus COBOL for 32bit systems, which include
!      all Micro Focus COBOL for UNIX systems.

   o   Micro Focus reserves the right to change their default signal
       handlers or use extra signals in the future.

   Example
   =======
   The following example illustrates how a handler for the SIGALRM signal
   could be set up.

        #include <stdio.h>
        #include <signal.h>

        int
        mysigcatch(sig)
        int sig;
        {
                cobprintf("Here is new signal handler\n");
                return(0);  /* Do not process any further handlers */
        }

        void
        mysigexit(sighand)
        void *sighand;
        {
                cobprintf("Cancelling handler\n");
                cobremovesighandler(sighand);     /* Remove the handler */
        }

        main(argc, argv)
        int argc;
        char *argv[];
        {
                void *sighandle;

                extern void *cobpostsighandler();

                sighandle = cobpostsighandler(SIGALRM, 128, mysigcatch);
                cobfunc("cobolprog", argc, argv); /* call a cobol program
                                                  using cobfunc function */
                alarm(1);                         /* raise the signal */
                pause();                          /* wait for the signal */
                sleep(4);
                mysigexit(sighandle);
                cobexit(0);                 /* Cobexit - close down COBOL
                                               run-time environment */
        }

   Writing signal handlers
   =======================
   A signal handler should do very little. A signal can be generated at any
   time so the routine that was being executed could be in an "unsafe"
   state (eg. in the middle of modifying global variables) and so trying to
   execute it in your signal handler could cause problems. The routine
   being executed could be a C system routine such as malloc().

   There are a small subset of system C routines that are safe to call
   from signal handlers. You should not try and call any other C system
   routines, or any COBOL routines, from your signal handler. See your
   system documentation for more information on the safe C system routines.

   Coping with more than one handler for the same signal
   -----------------------------------------------------
   The cobpostsighandler() call provides the ability for two or more
   handlers to be posted for the same signal. When that signal is generated
   by the OS (eg. a SIGINT generated when the interrupt key is pressed),
   then each handler can take appropriate action and then let other handlers
   be executed (by returning a non-zero value). Alternatively, they can
   decide to make the signal "ignored" by returning a value 0 to prevent
   other handlers from being executed. However, so that your handler can
   work with other handlers for the same signal, a handler of priority 140
   (or more) should return non-zero to let other handlers have the
   opportunity to also be notified. A handler of priority 128 can return 0
   if you do not want the RTS default action to be executed (which may cause
   termination).

   When you raise a signal (eg. by using alarm() to raise a SIGALRM signal,
   or when raising a signal to a different run-unit or application), then it
   is probable that only your signal handler(s) wants to be called and other
   posted signal handlers are not expecting the signal. Hence, in this
   case, you should set a global resource before raising the signal and then
   check that resource in your signal handler. If the resource is set
   (as expected), then the signal was raised by you, so you can take the
   appropriate action and return 0 to prevent other handlers from being
   unexpectedly called. If the resource is unset, then someone else (or
   something else, such as the OS) raised the signal and so you can take no
   action and should let other handlers execute by returning a non-zero
   value.

   Examples of global resources are global variables (if in the same
   run-unit), shared memory, pipes, files, and so on. Hence, in the above
   example, we could have set a global variable before raising the alarm()
   signal. We would then need to check the global variable in the signal
   handler, mysigcatch. If it was set, we would carry out our action, reset
   the variable and return 0. However, if the global variable had not been
   set, then some other code is likely to have raised the signal. Hence, we
   would have not wanted to carry out our action and would instead need to
   return a non-zero value immediately. This allows the appropriate action
   to be taken in some other handler.

   Converting signal handlers written for signal()
   -----------------------------------------------
   If you have any signal handlers which are posted using an OS signal call,
   such as signal() or sigaction(), then they should be changed to use
   cobpostsighandler(). This is so that your handler and any default RTS
   handler, additional COBOL functionality and user posted signal handlers
   can all co-exist without one overriding the other, causing unexpected
   results.

   The cobpostsighandler() interface is very similar to the signal()
   interface. The two parameters you pass to signal() are also passed to
   cobpostsighandler(), plus a priority.

   However, the following differences apply:

   o   The return value from signal() is the previous signal handler that
       was posted for the signal. This is returned because signal() only
       allows one handler per signal. The cobpostsighandler() routine
       allows multiple handlers per signal.

       The return value from cobpostsighandler() is either a pointer or
       NULL. If non-NULL, the pointer returned can later be used to remove
       the handler using cobremovesighandler(). If NULL, then the handler
       could not be posted for the signal.

   o   The signal handler function needs to return an integer value, instead
       of no value.

   o   A signal handler function, posted via OS signal calls, can be
       terminated by functions such as longjmp() and siglongjmp(). These
       routines can not be used to terminate a signal handler function
       posted via cobpostsighandler(). Doing so would cause the signal to
       remain blocked, preventing any further signal from being processed
       successfully.

   o   A signal handler function, posted via signal(), needs to re-post
       itself, using another signal() call, if it wants to catch any
       subsequent signals. This is because the OS resets the signal to the
       OS default handler before the signal handler function is called.

       Once you have posted a handler, via cobpostsighandler(), it stays
       posted, you do not need to re-post it. If you only want your handler
       to be executed once, then you must remove it, via
       cobremovesighandler().

   Coping with Third Party software that uses signals
   ==================================================
   If you are using any Third Party software that posts a signal handler
   using an OS signal call, such as signal() or sigaction(), then unexpected
   results may occur. For example, if the Third Party software posts its
   handler before COBOL has been invoked, then when COBOL is invoked the
   Third Parties handler may be overridden by an RTS/COBOL handler. If the
   the Third Party subsequently raises a signal, then a 115 error may occur.

   The Run-Time tunable 'signal_regime' can be used to overcome this. This
   tunable will prevent handlers from being posted for the specified signal
   if a signal handler is posted before the first COBOL invocation. For more
   information on this tunable see the chapter "Run-Time Configuration",
   in the COBOL System Reference.

   If handlers are prevented from being posted for a signal, due to this
   tunable, then cobpostsighandler() will return NULL. Hence, the default
   RTS handlers and any additional COBOL functionality achieved using the
   signal will not be available. It also means that you should check the
   value returned from any cobpostsighandler() calls for NULL.

   Use of the 'signal_regime' tunable is only recommended for use with
   Third Party software. You should always use cobpostsighandler() in your
   own code.

   signal() vs sigaction()
   =======================
   On some platforms, the OS function sigaction() is available. It is more
   robust than signal() when signals are being received in rapid succession
   or when a machine is heavily loaded. The cobpostsighandler() call will
   use sigaction() by default.

   The cobpostsighandler() function can be forced to use signal() instead of
   sigaction() if the signal_interface tunable is used. For more information
   on this tunable see the chapter "Run-Time Configuration", in the COBOL
   System Reference.


   =========================================================================
   Micro Focus is a registered trademark of Micro Focus Limited.
   UNIX is a registered trademark of X/Open Company Ltd.
   =========================================================================
   @(#)Vrn/signals.1/4.0.00/06Sep95/nrV
   Copyright (C) 1993-95 Micro Focus Limited

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026