ast@cs.vu.nl (Andy Tanenbaum) (05/28/90)
From: Andy Tanenbaum <ast@cs.vu.nl> We have gone through this before, but I still haven't gotten an unambiguous answer. Let me try a specific example to make it clearer. Suppose you want to write a routine raise() that is ANSI conformant and also POSIX conformant. Raise calls the POSIX kill function, so it includes <signal.h>. The <signal.h> header contains the prototype for kill(), which uses pid_t, a type defined in <sys/types.h>. POSIX mandates <sys/types.h> but ANSI does not require it. Thus it is probably not ANSI-legal to put #include <sys/types.h> in raise(), since an ANSI routine cannot depend on something that ANSI doesn't require. The raise routine would not be portable then, and maybe not even conformant. On the other hand, putting the #include in <signal.h> probably isn't legal either, and certainly not portable to non POSIX systems. The question is: it has to go somewhere, but where? I have thought about putting it in <signal.h> but protected by #ifdef _POSIX_SOURCE, just as the prototype for kill is. However, our earlier discussion in this group suggested that this wasn't legal either. Does anybody know what the story is? Andy Tanenbaum (ast@cs.vu.nl) Volume-Number: Volume 20, Number 20
gwyn@smoke.brl.mil (Doug Gwyn) (05/30/90)
From: Doug Gwyn <gwyn@smoke.brl.mil> In article <711@longway.TIC.COM> Andy Tanenbaum <ast@cs.vu.nl> writes: >We have gone through this before, but I still haven't gotten an unambiguous >answer. Let me try a specific example to make it clearer. I'm sure I've given unambiguous answers. The rules are really quite clear and simple. >Suppose you want to write a routine raise() that is ANSI conformant and also >POSIX conformant. Raise calls the POSIX kill function, so it includes ><signal.h>. The <signal.h> header contains the prototype for kill(), which >uses pid_t, a type defined in <sys/types.h>. POSIX mandates <sys/types.h> >but ANSI does not require it. Thus it is probably not ANSI-legal to put >#include <sys/types.h> >in raise(), since an ANSI routine cannot depend on something that ANSI >doesn't require. The raise routine would not be portable then, and maybe >not even conformant. On the other hand, putting the #include in <signal.h> >probably isn't legal either, and certainly not portable to non POSIX >systems. >The question is: it has to go somewhere, but where? I have thought about >putting it in <signal.h> but protected by #ifdef _POSIX_SOURCE, just as >the prototype for kill is. However, our earlier discussion in this group >suggested that this wasn't legal either. Does anybody know what the story >is? The above description makes no sense. The run-time code for raise does not "include <signal.h>". In fact, it must not even (in a conventional linkage environment) invoke the POSIX kill() function, because the external identifier "kill" is not in the name space reserved for ANSI C implementations (and thus is reserved for use by programs, with perhaps totally non-POSIX meaning). It could, however, invoke a function named "_kill" or some other such name reserved for use by implementations. <signal.h> must not define extra garbage such as the kill() interface or the POSIX *_t typedefs, except under control of some "feature test macro" such as _POSIX_SOURCE. In the case of the typedefs, I would urge that they not be defined as a side effect of #including <signal.h> even in the presence of _POSIX_SOURCE. You don't need pid_t to properly declare getpid() or kill() in an implementation; instead, simply use the equivalent type derived from basic types (in this case, probably "int"). Note that this is essential also for the ANSI C declaration of vprintf() in <stdio.h>, since the va_* identifiers must NOT be defined as a side effect of #including <stdio.h>, so the implementation of <stdio.h> must not #include <stdarg.h>. On the other hand, the implementation of an ANSI C library routine can certainly depend on things not mentioned in the C standard, such as for example _kill() and <sys/types.h>. The following is valid source code to implement ANSI C conformant raise() in a hypothetical POSIX implementation: /* raise() -- send a signal to the current process public-domain implementation last edit: 16-Jan-1990 Gwyn@BRL.MIL complies with the following standards: ANSI X3.159-1989 IEEE Std 1003.1-1988 SVID Issue 3 */ #define getpid _getpid /* required support for ANSI C */ #define kill _kill /* required support for ANSI C */ #include <sys/types.h> /* for pid_t */ extern pid_t getpid(); /* UNIX/POSIX system call */ extern int kill(); /* UNIX/POSIX system call */ int raise(sig) int sig; { return kill(getpid(), sig); /* set errno to EINVAL if sig invalid */ } Volume-Number: Volume 20, Number 21
ast@cs.vu.nl (Andy Tanenbaum) (06/01/90)
From: Andy Tanenbaum <ast@cs.vu.nl> In article <712@longway.TIC.COM> Doug Gwyn <gwyn@smoke.brl.mil> writes: ><signal.h> must not define extra garbage such as the kill() interface >or the POSIX *_t typedefs, except under control of some "feature test >macro" such as _POSIX_SOURCE. In the case of the typedefs, I would >urge that they not be defined as a side effect of #including <signal.h> >even in the presence of _POSIX_SOURCE. You don't need pid_t to properly >declare getpid() or kill() in an implementation; instead, simply use the >equivalent type derived from basic types (in this case, probably "int"). POSIX specifically defines kill's first argument as type pid_t, so it would seem to be poor programming practice to use int, even if this is legal. If one replaced the *_t types by their definitions everywhere, then a decision to change pid_t from, say, int, to, say, long, would require a real expert to dig through all the code to find those int's that really are pid_t's. Maintenance of such code would be exceedingly difficult. I think that the only realistic way is to use pid_t in the prototype of kill. This prototype is required in <signal.h> (protected by #ifdef _POSIX_SOURCE). This then raises the question of how to make pid_t known. In the example implementation given, <sys/types.h> is included in raise.c. If this is indeed legal, then that is clearly one way to do it, as presumably all the names introduced by <sys/types.h> are not present in the object file, raise.o, and thus do not pollute the name space. However, why do you urge not to put #include <sys/types.h> into <signal.h> under protection of #ifdef _POSIX_SOURCE? Andy Tanenbaum (ast@cs.vu.nl) Volume-Number: Volume 20, Number 23
gwyn@smoke.brl.mil (Doug Gwyn) (06/05/90)
From: Doug Gwyn <gwyn@smoke.brl.mil> In article <714@longway.TIC.COM> From: Andy Tanenbaum <ast@cs.vu.nl> >If one replaced the *_t types by their definitions everywhere, then a >decision to change pid_t from, say, int, to, say, long, would require >a real expert to dig through all the code to find those int's that really >are pid_t's. You miss an important point -- we're talking about system code provided by the IMPLEMENTOR, not application code. Presumably the implementor IS a real expert, and furthermore is in charge of the decision about what specific typedefs will be used. I suspect that many implementors will provide (for implementation use only) additional headers, say <sys/_types.h>, that define identifiers such as __pid_t that are just like the POSIX ones but taken from the name space reserved for use by implementations. Then, for example, <sys/types.h> could contain: /* <sys/types.h>: */ #include <sys/_types.h> #define pid_t __pid_t and <signal.h> could contain: /* <signal.h>: */ #include <sys/_types.h> #ifdef _POSIX_SOURCE extern int kill(__pid_t, int); #endif which addresses the maintenance issue that the implementor might be faced with. (Applications are oblivious to all this substructure, which is the way things SHOULD be.) >This then raises the question of how to make pid_t known. In the example >implementation given, <sys/types.h> is included in raise.c. If this is >indeed legal, then that is clearly one way to do it, as presumably all the >names introduced by <sys/types.h> are not present in the object file, >raise.o, and thus do not pollute the name space. Yes, that was one of the points of the example. >However, why do you urge not to put #include <sys/types.h> into <signal.h> >under protection of #ifdef _POSIX_SOURCE? Because I don't think that use of _POSIX_SOURCE should pollute the name space beyond the minimum required for POSIX. Volume-Number: Volume 20, Number 26
karl@IMA.IMA.ISC.COM (Karl Heuer) (06/07/90)
From: karl@IMA.IMA.ISC.COM (Karl Heuer) In article <717@longway.TIC.COM> From: Doug Gwyn <gwyn@smoke.brl.mil> >In article <714@longway.TIC.COM> From: Andy Tanenbaum <ast@cs.vu.nl> >>However, why do you urge not to put #include <sys/types.h> into <signal.h> >>under protection of #ifdef _POSIX_SOURCE? > >Because I don't think that use of _POSIX_SOURCE should pollute the >name space beyond the minimum required for POSIX. In an earlier thread in this newsgroup, it was decided that this is in fact a requirement of POSIX. (Clarified in the Supplement, I believe.) If the user himself has not included <sys/types.h>, then the name `pid_t' is not reserved to the implementation, and so it falls in the user's namespace. Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint Volume-Number: Volume 20, Number 27
rml@hpfcdc.fc.hp.com (Bob Lenk) (06/13/90)
From: Bob Lenk <rml@hpfcdc.fc.hp.com> In article <719@longway.TIC.COM> karl@IMA.IMA.ISC.COM (Karl Heuer) writes: > In an earlier thread in this newsgroup, it was decided that this is in fact a > requirement of POSIX. (Clarified in the Supplement, I believe.) If the user > himself has not included <sys/types.h>, then the name `pid_t' is not reserved > to the implementation, and so it falls in the user's namespace. It is worth pointing out that official interpretations of an IEEE standard can only be issued by the IEEE. Discussions in this newsgroup (including this posting) can be very informative and useful, but they do not decide the meaning of the standard. In fact, there has been an official request for an interpretation in this area, and I understand the interpretation being issued is that all namespace reserved for the implementation by the 1003.1-1988 standard is reserved whenever any header mentioned in the standard is #included with _POSIX_SOURCE #defined. Draft 5 of the 1003.1a revision (actually 1003.1-199x) makes some changes in this area, but clearly reserves names ending in _t when any POSIX.1 header is included. Bob Lenk rml@hpfcla.hp.com hplabs!hpfcla!rml Volume-Number: Volume 20, Number 28