12.4 The Foreign Include File
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Foreign Language Interface
        • The Foreign Include File
          • Argument Passing and Control
          • Atoms and functors
          • Analysing Terms via the Foreign Interface
          • Constructing Terms
          • Unifying data
          • Convenient functions to generate Prolog exceptions
          • Foreign language wrapper support functions
          • Serializing and deserializing Prolog terms
          • BLOBS: Using atoms to store arbitrary binary data
          • Exchanging GMP numbers
          • Calling Prolog from C
          • Discarding Data
          • String buffering
          • Foreign Code and Modules
          • Prolog exceptions in foreign code
          • Catching Signals (Software Interrupts)
            • PL_sigaction()
            • PL_signal()
            • PL_raise()
            • PL_handle_signals()
            • PL_get_signum_ex()
          • Miscellaneous
          • Errors and warnings
          • Environment Control from Foreign Code
          • Querying Prolog
          • Registering Foreign Predicates
          • Foreign Code Hooks
          • Storing foreign data
          • Embedding SWI-Prolog in other applications
    • Packages

12.4.16 Catching Signals (Software Interrupts)

SWI-Prolog offers both a C and Prolog interface to deal with software interrupts (signals). The Prolog mapping is defined in section 4.12. This subsection deals with handling signals from C.

If a signal is not used by Prolog and the handler does not call Prolog in any way, the native signal interface routines may be used.

Any handler that wishes to call one of the Prolog interface functions should call PL_sigaction() to install the handler. PL_signal() provides a deprecated interface that is notably not capable of properly restoring the old signal status if the signal was previously handled by Prolog.

int PL_sigaction(int sig, pl_sigaction_t *act, pl_sigaction_t *oldact)
Install or query the status for signal sig. The signal is an integer between 1 and 64, where the where the signals up to 32 are mapped to OS signals and signals above that are handled by Prolog's synchronous signal handling. The pl_sigaction_t is a struct with the following definition:
typedef struct pl_sigaction
{ void        (*sa_cfunction)(int);     /* traditional C function */
  predicate_t sa_predicate;             /* call a predicate */
  int         sa_flags;                 /* additional flags */
} pl_sigaction_t;

The sa_flags is a bitwise or of PLSIG_THROW, PLSIG_SYNC and PLSIG_NOFRAME. Signal handling is enabled if PLSIG_THROW is provided, sa_cfunction or sa_predicate is provided. sa_predicate is a predicate handle for a predicate with arity 1. If no action is provided the signal handling for this signal is restored to the default before PL_initialise() was called.

Finally, 0 (zero) may be passed for sig. In that case the system allocates a free signal in the Prolog range (32 ... 64). Such signal handler are activated using PL_thread_raise().

void (*)() PL_signal(sig, func)
This function is equivalent to the BSD-Unix signal() function, regardless of the platform used. The signal handler is blocked while the signal routine is active, and automatically reactivated after the handler returns.

After a signal handler is registered using this function, the native signal interface redirects the signal to a generic signal handler inside SWI-Prolog. This generic handler validates the environment, creates a suitable environment for calling the interface functions described in this chapter and finally calls the registered user-handler.

By default, signals are handled asynchronously (i.e., at the time they arrive). It is inherently dangerous to call extensive code fragments, and especially exception related code from asynchronous handlers. The interface allows for synchronous handling of signals. In this case the native OS handler just schedules the signal using PL_raise(), which is checked by PL_handle_signals() at the call- and redo-port. This behaviour is realised by or-ing sig with the constant PL_SIGSYNC.220A better default would be to use synchronous handling, but this interface preserves backward compatibility.

Signal handling routines may raise exceptions using PL_raise_exception(). The use of PL_throw() is not safe. If a synchronous handler raises an exception, the exception is delayed to the next call to PL_handle_signals();

int PL_raise(int sig)
Register sig for synchronous handling by Prolog. Synchronous signals are handled at the call-port or if foreign code calls PL_handle_signals(). See also thread_signal/2.
int PL_handle_signals(void)
Handle any signals pending from PL_raise(). PL_handle_signals() is called at each pass through the call- and redo-port at a safe point. Exceptions raised by the handler using PL_raise_exception() are properly passed to the environment.

The user may call this function inside long-running foreign functions to handle scheduled interrupts. This routine returns the number of signals handled. If a handler raises an exception, the return value is -1 and the calling routine should return with FALSE as soon as possible.

int PL_get_signum_ex(term_t t, int *sig)
Extract a signal specification from a Prolog term and store as an integer signal number in sig. The specification is an integer, a lowercase signal name without SIG or the full signal name. These refer to the same: 9, kill and SIGKILL. Leaves a typed, domain or instantiation error if the conversion fails.