Email List: Xaustin-review-lX
[All Lists]

Defect in XSH confstr,pathconf,sysconf

To: yyyyyyyyyyyyyyy@xxxxxxxxxxxxx
Subject: Defect in XSH confstr,pathconf,sysconf
From: yyyyyyyyyy@xxxxxxx
Date: Tue, 30 Apr 2002 08:21:04 +0100 (BST)
        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.

<Prev in Thread] Current Thread [Next in Thread>
  • Defect in XSH confstr,pathconf,sysconf, SHwareSyst <=