dhesi@sun505.UUCP (Rahul Dhesi) (09/23/89)
For about ten years, signal() has been a function returning pointer to int. It worked, and we were all happily writing portable code. So what happens? Both Sun and ANSI decide that milliions of lines of existing code were all wrong, and that signal() ought really to return pointer to void. After much thinking I have found no advantage to this change, and the big disadvantage that stable existing code now brreaks. Now I'm faced with this problem: How do I use signal() in such a way that my code is portable, without manually editing it for each implementation? I need a way of having my code automatically use void or int as appropriate. Any suggestions? -- Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com> UUCP: oliveb!cirrusl!dhesi
cpcahil@virtech.UUCP (Conor P. Cahill) (09/23/89)
In article <880@cirrusl.UUCP>, dhesi@sun505.UUCP (Rahul Dhesi) writes: > For about ten years, signal() has been a function returning pointer to > int. It worked, and we were all happily writing portable code. No, signal(2) now returns a pointer to a function returning void. > After much thinking I have found no advantage to this change, and the > big disadvantage that stable existing code now brreaks. Since signal() returns the pointer to the old signal handler or signal handling status, and a signal handler, being called asynchronously with respect to the rest of the code in the program, does not "return" a value the "type" of a signal handler should be void. > Now I'm faced with this problem: How do I use signal() in such a way > that my code is portable, without manually editing it for each > implementation? I need a way of having my code automatically use void > or int as appropriate. How about cc arg "-DSIGNAL_TYPE=void" and using it as: SIGNAL_TYPE (*signal())(); -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
guy@auspex.auspex.com (Guy Harris) (09/24/89)
>After much thinking I have found no advantage to this change, and the >big disadvantage that stable existing code now brreaks. I have yet to see any example of code that ceases to work on the implementations of UNIX generally available. It may cause warnings from your compiler, but that's life. BTW, Sun decided to do that because bodies such as X3J11 and POSIX were moving in that direction, and AT&T adopted that change for S5R3. I seem to remember some indication that Ultrix has done so as well; eventually, I expect any non-stagnant version of UNIX to do so. >Now I'm faced with this problem: How do I use signal() in such a way >that my code is portable, without manually editing it for each >implementation? I need a way of having my code automatically use void >or int as appropriate. Have a #define to control it, set in an include file, and use some scheme to set up the include file, either by having the user manually supply it or having something like Larry Wall's configuration files.
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/24/89)
In article <880@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes: >For about ten years, signal() has been a function returning pointer to >int. It worked, and we were all happily writing portable code. signal() has NEVER returned pointer to int. However, I know what you're trying to say. Before the "void" type was added to C, one declared functions that returned no value as "int" (usually eliding the explicit "int", to underscore the point that no value was actually being returned, despite the declared function type). That meant that signal handler functions, which cannot return a value, were defined as functions returning (implicit) int due to the lack of a better way to specify them. After "void" was added to C around 1979, the opportunity existed to correctly declare such function types as returning no value. In fact a "void"-cognizant "lint" would normally squawk about the lack of a return value for a nominally int-valued function, and most "lint"s had a kludge installed to shut them up in precisely the cases under discussion. >So what happens? Both Sun and ANSI decide that milliions of lines of >existing code were all wrong, and that signal() ought really to return >pointer to void. Not pointer to void. Actually, I instigated this change. Larry Rossler had been unsuccessfully arguing inside AT&T for the change ever since "void" appeared. It was quite apparent to X3J11 and P1003 that type correctness REQUIRED the change. The ancient pre-"void" usage was simply incorrect. Signal handlers DO NOT return an int value and it is WRONG to define them as returning one. This is not just a matter of theoretical "purity", either, as the difference in return types can easily show up as a difference in the linkage actually used in the function invocation. The first widespread correct post-"void" version of <signal.h> went out with the BRL UNIX System V emulation for 4.2BSD. The correct types were adopted by X3J11 and P1003; the SVID Issue 2, IEEE Std 1003.1, forthcoming ANSI X3.159, and presumably all other current UNIX/C standards specify the correct type. SVR3.0 <signal.h> is correct. Presumably Sun picked up the correct type from one of these. >After much thinking I have found no advantage to this change, and the >big disadvantage that stable existing code now brreaks. Implementations that permitted you to be sloppy about the void/int function return distinction can continue to permit such sloppiness. Presumably they use compatible linkage for both function return types. >Now I'm faced with this problem: How do I use signal() in such a way >that my code is portable, without manually editing it for each >implementation? I need a way of having my code automatically use void >or int as appropriate. The correct signal handler return type is void no matter what <signal.h> says. There have been compilers (early 4BSD PCCs, for example) that couldn't correctly handle pointers to functions returning void. For that reason and that reason only, it may behoove you to define a type sig_hdlr_ret_t in your site's equivalent of <std.h> (i.e. a header used by all your applications, that augments the standard C environment with things to provide a uniform interface to implementation dependencies); set it to int or void depending on how well the environment deals with this, and code your signal handlers as returning sig_hdlr_ret_t.
dhesi@sun505.UUCP (Rahul Dhesi) (09/25/89)
In article <11142@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) quotes me: >>For about ten years, signal() has been a function returning pointer to >>int. It worked, and we were all happily writing portable code. > >signal() has NEVER returned pointer to int. However, I know what you're >trying to say. Actually, once back in 1982, I caught a signal handler returning pointer to int when it thought nobody was looking... Sorry about my garbled thoughts, however. Yes, the type of signal() is pointer to function returning int, not function returning pointer to int. >Before the "void" type was added to C, one declared functions that >returned no value as "int"... [...other points...] Yes, I realize that since signal handlers don't return a value they should have a return type of void, not int. Yes, it's true that declaring them as returning int means the compiler must use appropriate linkage. Yes, a programmer could negligently try to make a signal handler return a value. Yes, void is better than int. >The ancient pre-"void" usage was simply incorrect. And this is where we disagree. Before the "void" data type existed, the c equivalent of a "procedure", i.e., a function from which no return value was needed, was by convention a function returning int. There is nothing actually wrong with this. Within the scope of the language rules, this was the accepted and correct way to do this. The new existense of the "void" data type did not suddenly make existing programs incorrect. It just gave us a better way to do the same thing. Not right versus wrong, just better versus not-so-good. [Note 1] As an analogy, the existence of the enum data type doesn't make it wrong to use the pre-enum technique of having a series of #defines. It just gives us a better of of doing the same thing. Since more than one person has suggested some sort of #define, I should point out that that is not an automatic solution. What *should* have been done by all the vendors/organizations who changed the type of signal was to guarantee the existence of a macro in signal.h so that I could then do: #ifdef SIGTYPE typdef sig_ret_t SIGTYPE #else /* if SIGTYPE not defined, we *know* it's int */ typedef sig_ret_t int #endif That would have made new code automatically portable and made the transition much easier. --- Note 1. Actually, I'm not fully convinced that signal handlers should return void rather than int. Letting them return int allows a future extension to signal handlers so that they *can* return a value. As an example, the return value from a SIGINT handler could tell the kernel whether or not to restart any interrupted system call. Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com> UUCP: oliveb!cirrusl!dhesi
davidsen@crdos1.crd.ge.COM (Wm E Davidsen Jr) (09/25/89)
In article <880@cirrusl.UUCP>, dhesi@sun505.UUCP (Rahul Dhesi) writes: | For about ten years, signal() has been a function returning pointer to | int. It worked, and we were all happily writing portable code. Actually I think you mean "pointer to function returning int." Since the value of the pointer to proc is used, and a pointer to any proc type can hold the address of any other proc type, I don't see that the question ever comes up. Your existing code will work fine, since the declaration is in signal.h and you can still save the value returned by signal in a variable declared int (*sighold)(); without portability problems. Some compilers may warn you about this but you can always say sighold = (int (*)())signal(SIGALRM, myproc); which is the correct ugly cast of types. -- bill davidsen (davidsen@crdos1.crd.GE.COM -or- uunet!crdgw1!crdos1!davidsen) "The world is filled with fools. They blindly follow their so-called 'reason' in the face of the church and common sense. Any fool can see that the world is flat!" - anon
guy@auspex.auspex.com (Guy Harris) (09/26/89)
>Note 1. Actually, I'm not fully convinced that signal handlers should >return void rather than int. Letting them return int allows a future >extension to signal handlers so that they *can* return a value. And allows all programs written not to have the handler for the signals in question to fall apart in a million pieces once the signal mechanism is modified to expect a return value. Yes, signal handlers should return void rather than int.