IDL and Signals
Signals pose one of the more difficult challenges faced by the UNIX programmer. Although seemingly simple, they are a tough portability problem because there are several variants, and their semantics are subtle, inconvenient, and easily confused. These issues are only magnified when signals are used in a program like IDL that employs multiple threads. IDL has always done whatever is necessary with signals in order to get its job done, but its signal assumptions can also affect user written code linked to it.
Note: This discussion refers primarily to UNIX IDL. Microsoft Windows uses different mechanisms to solve these problems.
The following is a brief list of problems and contradictions inherent in UNIX signals. For a more complete description, see Chapter 10 of External Programming in the UNIX Environment by W. Richard Stevens.
- POSIX signals (sigaction) promise to unify and simplify signals, but not all platforms support them fully.
- You can only have one signal handler function registered for each signal. This means that if one part of a program uses a signal, the rest of the program must leave that signal alone.
- In order to meet the needs of programs originally developed under different UNIX systems (AT&T System V, BSD, Posix), most UNIX implementations provide more than one package of signal functions. Typically, a given program is restricted to one of these libraries. If a programmer links code into IDL that chooses a library or signal options different from that used by IDL itself, unexpected results may occur.
- The number and exact semantics of some signals differ in different versions.
- Details of signal blocking differ.
- Some System V implementations of signals are unreliable, meaning that signals can occur in a process and be missed.
- Some older System V systems reset the handling action to SIG_DFL before calling the handler. This opens a window in time where two signals in a row can cause the process to be killed. Also, the signal handler must re-establish itself every time it is called.
- On most platforms, if a signal is generated more than once while it is blocked, the second and subsequent occurrences are lost. In other words, most UNIX implementations do not queue signals.
These are among the reasons that most libraries avoid signals, and leave their use to the programmer. IDL, however, must use signals to function properly. In order to allow users to link their code into IDL while using signals, IDL provides a signal API built on top of the signal mechanism supported by the target platform. The IDL signal API has the following attributes:
- It disallows use of SIGTRAP and SIGFPE. These signals are reserved to IDL.
- It disallows use of SIGALRM. Most uses for SIGALRM are provided by the IDL timer API.
- It works with all other signals, including those IDL doesn’t currently use, so the interface won’t change over time.
- It allows multiple signal handlers for each signal, so IDL and other code can use the same signal simultaneously.
- It unifies the signal interface by supplying a stable consistent interface with known behavior to the underlying system signal mechanism.
- It keeps IDL in charge of which signal package is used and how.
This is not a perfect solution, it is a compromise between the needs of IDL and programmers wishing to link code with it. Usually, the IDL signal abstraction is sufficient, but it does have the following limitations:
- The calling program must not attempt to catch SIGTRAP or SIGFPE, either directly or through library routines that use these signals to achieve their ends. Furthermore, the IDL signal abstraction does not allow the caller to catch these signals, so your program must leave exception handling to IDL.
- The caller loses control over signal package choice and some minor signal abilities.
- Having multiple signal handler routines for a given signal opens the possibility that one handler might do something that causes problems for the others (like change the signal mask, or longjmp()). To minimize such problems, user code linked into IDL must not call the actual system signal routines, and must not longjmp() out of signal handlers—a tactic that is usually allowed, but which would seriously damage IDL’s signal state.
- Since there may be more than one signal handler registered for a given signal, the signal dispositions of SIG_IGN and SIG_DFL are not directly available to the caller as they would be if you were allowed to use the system signal facilities directly.
If you find that these restrictions are too limiting for your application, chances are your code is not compatible with IDL and should be executed in a separate process. We then encourage you to consider running IDL in a separate process and to use an interprocess communication mechanism such as RPC.