$ZINTerrupt

$ZINT[ERRUPT] specifies the code that GT.M XECUTEs at the time of processing an interrupt (for example, through a MUPIP INTRPT). While a $ZINTERRUPT action is in process, GT.M defers any additional interrupt signals. At the time of invoking an interrupt handler, GT.M saves the current values of $ECODE and $REFERENCE and restores them when the interrupt handler returns. GT.M neither saves nor restores the current device ($IO).

GT.M permits the SET command to modify the value of $ZINTERRUPT.

If an interrupt handler changes the current IO device (via USE), it is the responsibility of the interrupt handler to restore the current IO device before returning. There are sufficient legitimate possibilities why an interrupt routine would want to change the current IO device (for example; daily log switching), that this part of the process context is not saved and restored automatically.

The initial value for $ZINTERRUPT is taken from the UNIX environment variable gtm_zinterrupt if it is specified, otherwise it defaults to the following string:

IF $ZJOBEXAM()

The IF statement executes the $ZJOBEXAM function but effectively discards the return value.

[Note] Note

If the default value for $ZINTERRUPT is modified, no $ZJOBEXAM() occurs unless the replacement value directly or indirectly invokes that function. In other words, while $ZJOBEXAM() is part of the interrupt handling by default, it is not an implicit part of the interrupt handling.

The interrupt handler is executed by GT.M when on a statement boundary or on an appropriate boundary in a potentially long running COMMAND (in the same place as GT.M recognizes <CTRL-C>). If a GT.M process is in a long running external call (for example; waiting in a message queue) GT.M does not have sufficient control of the process state to immediately drive the interrupt handler. GT.M recognizes the interrupt request and drives the handler after the external call returns to GT.M and the process reaches an appropriate execution boundary.

[Note] Note

The interrupt handler does not operate "outside" the current M environment but rather within the environment of the process.

It is possible for the interrupt handler to be executed while the process executing a TP transaction holds the critical section for one or more regions. Use of this feature may create temporary hangs or pauses while the interrupt handler executes. For the default case where the interrupt handler uses $ZJOBEXAM() to create a dump, the pause duration depends on the number of local variables in the process at the time of the dump and on the speed of the secondary storage device. Such a dump is slower on a network-mounted secondary storage device than on a storage device directly connected to the local system. Design interrupt driven code to account for this issue.

When GT.M uses an interrupt handler, it saves and restores the current value of $REFERENCE. However, GT.M does not implicitly save or restore the current device ($IO). If an interrupt handler changes $IO (via USE), ensure that the interrupt handler restores the current device before returning. To restore the device which was current when the interrupt handler began, specify USE without any deviceparameters. Any attempt to do IO on a device which was actively doing IO when the interrupt was recognized may cause a ZINTERCURSEIO error.

Code in $ZINTERRUPT must use routine names in any entryref argument to a DO, GOTO, JOB, ZGOTO or any extrinsic as the arrival of the interrupt can activate the code while executing an arbitrary routine in the application.

During the execution of the interrupt handling code, $ZININTERRUPT evaluates to 1 (TRUE).

If an error occurs while compiling the $ZINTERRUPT code, the error handler is not invoked, GT.M sends the ERRWZINTR message and the compiler error message to the operator log facility. If the GT.M process is at a direct mode prompt or is executing a direct mode command (for example, a FOR loop), GT.M also sends the ERRWZINTR error message to the user console along with the compilation error. In both cases, the interrupted process resumes execution without performing any action specified by the defective $ZINTERRUPT vector.

The error handler is invoked if an error occurs while executing the $ZINTERRUPT code. If an error occurs during execution of the interrupt handler's stack frame (before it calls anything), that error is prefixed with the ERRWZINTR error. The error handler then executes normal error processing associated with the module that was interrupted. Any other errors that occur in code called by the interrupt handler are handled by normal error handling. See Chapter 13: “Error Processing.

If a TP transaction is in progress (0<$TLEVEL), updates to globals are not safe since a TP restart can be signaled at any time prior to the transaction being committed - even after the interrupt handler returns. A TP restart reverses all global updates and unwinds the M stack so it is as if the interrupt never occurred. The interrupt handler is not redriven as part of a transaction restart. Referencing (reading) globals inside an interrupt handler can trigger a TP restart if a transaction is active. When programming interrupt handling, either discard interrupts when 0<$TLEVEL (forcing the interrupting party to try again), or use local variables that are not restored by a TRESTART to defer the interrupt action until after the final TCOMMIT.

[Important] Important

Because sending an interrupt signal requires the sender to have appropriate permissions, the use of the job interrupt facility itself does not present any inherent security exposures. Nonetheless, because the dump files created by the default action contain the values of every local variable in the context at the time they are made, inappropriate access to the dump files would constitute a security exposure. Make sure the design and implementation of any interrupt logic includes careful consideration to security issues.

Example:

set $zinterrupt="do ^interrupthandler($io)"
interrupthandler(currentdev)
       do ^handleinterrupt ; handle the interrupt
       use currentdev      ; restore the device which was current when the interrupt was recognized
       quit

For more information on interrupt handling, refer to “Interrupt Handling”.