Defect report from : SHware Systems , SHwareSystemsDev.Co.
(Please direct followup comments direct to yyyyyyyyyyyyyy@xxxxxxxxxxxxx)
@ page 212 line 7145 section confstr,pathconf,sysconf objection {020429-02}
Problem:
Defect code : 1. Error
Problem: getconf is portable, conf interfaces aren't, as specified. Please note
that the below is how I'm interpreting the spec as written, but I do allow I
may have overlooked something that invalidates my reasoning, so no flames,
please :-)
Scenario:
confstr(), (f)pathconf(), and sysconf() define their name parameter to be of
type int, yet specifies also A) some options may be omitted by an
implementation, and the associated identifiers from unistd.h, and B) the
specification does not indicate which values any of these constants shall
assume when specified in unistd.h, just that they be defined somehow.
While these functions are included to support the facilitation of binary
package redistribution, such allowances render these functions potentially
non-portable for source distributions of an application, and even binary
packages may fail to execute as intended if an implementor isn't careful. These
allowances do not affect the getconf utility, as its name parameter is a string
value, not an integer, and it's presumed an array of supported values for such
strings will be scanned to generate the appropriate integer value for passing
to the appropriate conf interface, and if the argument is not found exit
returning an error code >0. This level of indirection makes getconf portable,
as you can throw any text at it and it should blurp appropriately. While it may
make for faster implementations, using an integer name isn't portable with the
allowances above.
Rationale:
For A), allowing missing identifiers immediately makes any application
desiring to use the interfaces non-portable source. They are explicitly bound
to the implementation on which they were originally developed and for which it
can be guaranteed all identifiers referenced by the application are defined in
unistd.h. If an optional identifier is specified in an application source for
testing and the identifier is not declared in unistd.h on any other
implementation, any compile will fail with an 'identifier not found' error, yet
both systems may be certified as conformant to the spec. The only way to avoid
this error is for each instance where an optional identifier is to be used that
the code be enclosed, in simplest form, as follows:
#ifdef ident
long sc_ident_rslt=sysconf(ident); // or confstr(ident), etc.
// use sc_ident_rslt...
#endif
or constructions to this effect. However, it is not specified such constructs
SHALL be required, and constructs like this make the specification that sysconf
set errno if an identifier is not supported superfluous, nominally. For cases
where applications hard code ident values, e.g.
errno=0; long rslt=sysconf(1000); if !errno {/* no ident 1000 */};
the requirement to set errno is still valid, yet this usage is patently
non-portable, requiring the compiler invoker to ensure that each hard coded
value refers to the desired test option on their system.
The other alternative is to specify that all identifiers be declared in
unistd.h to some integer value, even if the implementation doesn't support that
optional functionality.
Which brings us to B), the lack of which integer value is to be assigned each
identifier:
As stands, this lack of specification affects potential binary portability more
than source portability. Succinctly, a binary may fail to give correct results
on another implementation, other environmental and architectural considerations
being accounted for, because the unistd.h declarations of the constants aren't
guaranteed to be equivalent in the two environments, just that they conform to
the spec. The spec presumes an implementor of varying conformance levels for a
specific architecture will use a single version of unistd.h for all
implementations, thus implicitly maintaining an equivalence of name usage, or
possibly multiple versions where the usage of values specific to each
implementation is a subset of the maximum amount of values needed to be
accounted for, but there is nothing in the spec. that mandates such equivalence
or usage of values.
While a single implementor can assure by the presumed usages above that an
application will function correctly, it has no control over how another
implementor may produce a conforming unistd.h. Thusly, while a binary
distributin could conceivably load and begin execution in another environment,
there is no way the application could rely on the results returned by a conf
interface to adapt it's function to that environment's configuration. There is
no guarantee that identifiers of the same name would have equal values, or that
identifiers from an option group implemented on one machine could be assigned
values that specify entirely different options on another machine. The only way
I see to provide this level of portabilty is to explicitly specify that each
identifier that is a potential legal value for an interfaces' name property be
assigned an explicit integer value.
This presumes it is desired to maintain backwards compatibility with the
previous and current format of these interfaces' declarations. The solution
that enables maximal future portability is to change the type of the name
parameter from int to char*, or const char*, or provide additional interfaces
that use a string parameter for name. This would simplify any implementation of
getconf also. It could be this was what was originally intended for these
interfaces, yet the functional difference between a compiletime header
identifier and an explicit runtime string constant was overlooked.
Action:
As above, multiple ways of reconciling the discrepancies exist:
For the current interfaces,
1) all mention that an identifier is optional should be excised (preferred), or
require implementors to document that application developers cannot presume use
of any optional identifier will give consistent results in other environments.
The description of margin notation usage should be reworded to indicate that
a) an identifier shall be recognized, but give meaningful output only when the
Option Group indicated is in fact implemented in that execution environment, or
b) indicates that any usage of such identifier will be appropriately ifdef'd in
the applications' source, using either the identifier explicitly or a feature
test identifier that guarantees in accordance with the specification that
identifier shall also be defined in unistd.h.
2) All identifiers should be assigned explicit values. For case 1b), it would
need to be also specified that even if an implementors' unistd.h did not
include an identifier because the Option wasn't implemented, the value assigned
can not be co-opted to some other purpose for features specific to their
implementation.
This has the benefit also, that in the case where an application does hard code
a specific value in a an interface call, the behavior produced will be
consistent with the interface description regardless of platform the
application is compiled on, presuming the same system call mechanisms are
adhered to by platform variants.
For future portability considerations, ranges of non-overlapping values may be
specified for option groups currently with optional subgroups, e.g. Batch
Services, or to reserve values for use by a new group, or sub-group of an
existing group, that a revision of the spec may deem appropriate, e.g. if RPC
features are incorporated as a sub-group of a network IO service(s) at some
point, the spec could have a new ASYNC_IO_RPC_SUPPORT and SYNCH_IO_RPC_SUPPORT
interface gtroups, which would be assigned values from the ranges reserved for
ASYNCHRONOUS_IO, and SYNCHRONOUS_IO, respectively. Larger ranges reserving
values for LEGACY, OBSOLETE, and groups optional in previous versions; plus a
range for vendor-specific non-portable customizations, may also be specified.
3) The current interfaces should be marked LEGACY as a Corrigenda item,
introducing new interfaces where name is a char or wchar param, and OBSOLETE
for next Issue of the spec. The extended portability benefits of interfaces
specified as such, IMO, outweighs the loss of speed, entailed by requiring text
lookups in the implementations thereof, for those applications accessing the
interfaces directly. getconf's speed shouldn't be affected, as it does the
lookups to begin with now.
Optionally, the interfaces could be extended to accept a textname param as a
varargs extension, with the int name only usage marked as LEGACY; or a helper
interface that converts a text identifier to the integer assigned by that
implementation could be defined. With the first, all cs, pc, and sc constants
could eventually be removed from unistd.h, as the text constants actually
supported would only need to be specified in the system docs and the
Conformance statement, and declared privately in the implementations of the
interfaces.
4) Other compatibility considerations should be discussed, and a consensus
reached, before picking which remedy seems most suitable.
|