guy@gorodish.Sun.COM (Guy Harris) (04/26/88)
> 3. OS - what is the interface to the signal handler under > SYS V and BSD! This particular point really continues a discussion started in comp.lang.c. The discussion was inspired by some misconceptions about UNIX signal handlers. Any rational version of UNIX will permit signal handlers to take a single argument that is the signal number. Any version that obliges signal handlers to be written to take more than one argument will cause *so* much already-written code to break that it can fairly well considered to be broken itself. Fortunately, 4BSD has, as far as I know, only been implemented only on systems where the extra "signal code" argument that it passes doesn't make a difference. As such, it is not (yet) broken in that sense. ANSI C specifies that signal handlers take one and only one argument. This also happens to break existing code; however, assuming that there are machines that cannot support "varargs" without "varargs" functions being explicitly declared as such, they had no choice. In other words, if you want to write portable code, write it so that signal handlers take one argument. This will work on any non-broken UNIX system. Thus, the issue of the interface to the signal handler is not an issue raised by multiple versions of UNIX. It *is* an issue if you have non-UNIX systems, but if you have to deal with non-UNIX systems, it's probably one of the least of the issues you will have to deal with. As for the relevance of this point to "most people" and "most users", the people mentioned in the original article: to borrow a phrase I have heard attributed to Frank Zappa, "most people" or "most users" wouldn't know a signal handler if it came up and bit them in the ass.
shankar@hpclscu.HP.COM (Shankar Unni) (04/27/88)
> In other words, if you want to write portable code, write it so that signal > handlers take one argument. This will work on any non-broken UNIX system. I presume that by broken UNIX systems, you mean "most" UNIX system. What am I going to do with that ubiquitous "SIGFPE"? That could mean the most amazing number of vastly different things on most systems. This becomes an especial problem if you have funky architectures that catch you on many funnies in many languages. As an example, take range-checking in Pascal (shudder! :-)). We'd like to avoid the overhead of generating 4 or 5 instructions to check a value and call a routine if anything goes wrong. Instead, we'd like to just use a "compare and trap" instruction. *Of course*, the trap raised by this instruction *just happens* to be the same one that's raised by an Integer Overflow or a divide by zero (even the subcode). We thus have to do some pretty fancy decoding of the instruction which trapped to figure out what happened. That could have been done by the UX signal mechanism instead, saving us a lot of grief... Since machines have come a *long* way since the xxx-7, maybe it's time to define a consistent and meaningful convention (standard?) for such signals. For instance, SIGFPE (which now has an underground subcode which may mean just about anything, depending on what system you are on..) could either have an ARCHITECTED subcode, or be changed to a whole new array of codes, for different things like Integer Overflow, Divide by zero, Floating-point underflow and so on... After all, no matter how you bury your head in the sand, C is not the only language out there. There's FORTRAN, Ada (soon coming to a computer near YOU..), Pascal (that name again..), COBOL (no comments..) and so on. The runtime semantics of such languages almost always force emission of UGLY runtime code to do thins which can easily be caught by the hardware, but for which U**X refuses to return a meaningful code. Naturally, this will have to be defined to allow machines which do not have a meaningful trap in a particular category to return a more generic code. > Thus, the issue of the interface to the signal handler is not an issue raised > by multiple versions of UNIX. It *is* an issue if you have non-UNIX systems, > but if you have to deal with non-UNIX systems, it's probably one of the least > of the issues you will have to deal with. This is not particularly a UNIX problem, it's an architecture problem. Shankar.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/27/88)
In article <670016@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes: >For instance, SIGFPE (which now has an underground subcode which may mean >just about anything, depending on what system you are on..) could either have >an ARCHITECTED subcode, or be changed to a whole new array of codes, for >different things like Integer Overflow, Divide by zero, Floating-point >underflow and so on... No matter how much work you put into an attempt to specify a fully general (i.e. portable) floating-point exception status data structure, I guarantee I can dream up a floating-point architecture that you haven't accommodated. There is nothing that forbids implementation- dependent extensions for SIGFPE handlers, but you need to be aware that they ARE implementation dependent. Frankly, I think you should consider SIGFPE a fatal symptom that indicates that you haven't designed a good enough algorithm; the correct solution is to fix the algorithm, not interpret the state of the floating-point processor once it's already too late. The simple use of SIGFPE is sufficient for this.
guy@gorodish.Sun.COM (Guy Harris) (04/27/88)
> I presume that by broken UNIX systems, you mean "most" UNIX system. You presume incorrectly. I know of no UNIX systems that *require* you to write signal handlers as: handler(signo, code) int signo; int code; { ... } If you omit the "code" argument, they will still work. > What am I going to do with that ubiquitous "SIGFPE"? Either: 1) do what 4BSD does, and rely on the fact that, in *most* current C implementations, you can get away with the above; 2) come up with a scheme where you can specify whether extra arguments are to be delivered to a signal handler; or 3) use only the 4BSD signal mechanism, or the 4BSD-derived POSIX signal mechanism, and in the "sigaction" structure declare the "sa_handler" field as a pointer to a function with a variable-length argument list: void (*sa_handler)(int, ...) 1) will cause problems with ANSI C; "signal" takes an argument that is a pointer to a function with one and only one argument, and the compiler will give you a warning if you try to cast the address of a function with more arguments to the type "pointer to a function with one argument". 3) is kind of rude. 2) is easy: struct sigaction { /* speaking here in POSIX terms */ union { void (*sau_old_handler)(int signo); void (*sau_new_handler)(int signo, int code); } sa_handler_union; sigset_t sa_mask; int sa_flags; }; #define SA_CLDSTOP 0xnnnn #define SA_NEWHANDLER 0xmmmm ... #define sa_handler sa_handler_union.sau_old_handler #define sa_newhandler sa_handler_union.sau_new_handler If SA_NEWHANDLER is set, the "sau_new_handler" member is used; otherwise, the "sau_old_handler" is used. Non-stupid programs written to the POSIX interface will set the flags field to a value that doesn't have the SA_NEWHANDLER bit set, so they will work OK. Programs that want to have handlers that receive the signal code will have to set that bit, but that's life. > > Thus, the issue of the interface to the signal handler is not an issue > > raised by multiple versions of UNIX. It *is* an issue if you have > > non-UNIX systems, but if you have to deal with non-UNIX systems, it's > > probably one of the least of the issues you will have to deal with. > > This is not particularly a UNIX problem, it's an architecture problem. Bullshit. If you don't have the UNIX/POSIX signal mechanism, or the ANSI C signal mechanism, you can easily define a signal mechanism that solves this problem. The *only* problem is that the ANSI C signal mechanism (which will presumably, once ANSI C is adopted, spread its influence to the POSIX signal mechanism) demands that signal handlers take only one argument. Thus, this is *at most* an ANSI C problem.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/29/88)
In article <51046@sun.uucp> guy@gorodish.Sun.COM (Guy Harris) writes: >The *only* problem is that the ANSI C signal mechanism (which will >presumably, once ANSI C is adopted, spread its influence to the POSIX signal >mechanism) demands that signal handlers take only one argument. There is no logical requirement that signal handlers registered via sigaction() (new form of sigvec()) and those registered via signal() must have the same interface, although it is easier to implement if they do. There are also other ways of obtaining extended information than by passing it as arguments to the signal handler function. I can think of two obvious ones and there are probably others. It is not ANSI C that introduced the single-argument signal handler; that was existing practice everywhere until one day Berkeley decided to change it on their systems. Unfortunately Berkeley did not address the portability issues when they made the change, thereby introducing an unnecessary complication into what was to that point a simple mechanism. The whole signal approach is a botch anyhow; complicating it without fixing it seems like a counterproductive direction.