[comp.unix.questions] SunOS: 1; portability: 0

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.