Bug 29147 - getconf: Wrong values for symbolic constants defined in limits.h
Summary: getconf: Wrong values for symbolic constants defined in limits.h
Status: UNCONFIRMED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: ---
Assignee: Adhemerval Zanella
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-05-14 23:05 UTC by cquike
Modified: 2022-07-29 22:10 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Potential patch (589 bytes, patch)
2022-05-14 23:05 UTC, cquike
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description cquike 2022-05-14 23:05:24 UTC
Created attachment 14102 [details]
Potential patch

I am trying to understand the output of some of the values in getconf and I came to the conclusion that a number of symbolic constants defined in limits.h are not properly printed by getconf utility.

According to POSIX.1-2018 (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html), the getconf utility shall print "the symbolic constants listed under the headings ``Maximum Values'' and ``Minimum Values'' in the description of the <limits.h> header". Quoting the reference book "Advanced Programming in the UNIX environment": "Those minimum values do not change from one system to another. They specify the most restrictive values for these features".

I realized first with the _POSIX_PIPE_BUF constant. According to POSIX.1-2018 (https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) the value must be 512. However, on a Fedora 35 machine:

# getconf -a | grep  _POSIX_PIPE_BUF
_POSIX_PIPE_BUF                    4096

Looking at the sources it seems that _POSIX_PIPE_BUF (the minimum value for _any_ POSIX implementation) is using pathconf(_PC_PIPE_BUF, ...) which is the value for _this_ specific implementation.

I have jot down a potential patch that fixes the problem (albeit only for _POSIX_PIPE_BUF, not for the rest of the constants in limits.h) and have attached it here.
Comment 1 cquike 2022-05-14 23:12:50 UTC
BTW, the patch is not to be taken verbatim. Since for those variables there is no "call" to get the value, some of the code should be rewritten in order not to be confusing in terms of variable names. A quick possible solution is to change all appearances of "call" by "source" (sed -i 's/call/source/' getconf.c).
Comment 2 Adhemerval Zanella 2022-05-18 19:47:03 UTC
POSIX defines the values exported on limits.h, getconf is a glibc provided program. And glibc does not provide proper getconf documentation, although man-pages clearly states that the obtained values are done either through sysconf or pathconf (which always returns the implementation values).

So I am not sure if getconf should follow what limits.h defines instead of what implementation sets, changing will be a semantic change that might break some assumptions (which is always tricky).
Comment 3 cquike 2022-05-23 20:02:28 UTC
Thanks Adhemerval for your comments.

I agree that the documentation of getconf is not very clear on what the tool is supposed to deliver.

So I see three possible options for this isse:

1. Keep the status quo. The current GNU getconf is not POSIX compliant with the command of the same name (although to be fair the documentation doesn't claim it is). The problem I see is that according to the documentation (man getconf) the value returned by getconf corresponds to a system configuration var as defined by pathconfig. However, pathconfig in Linux does not define _POSIX_PIPE_BUF.  It is simply not possible to get the value of _POSIX_PIPE_BUF using pathconfig. Interestingly, the Linux pathconfig manpage does actually refer to _POSIX_PIPE_BUF as the minimum value that can be used for a pipe buffer, clearly distinguishing it from _PC_PIPE_BUF, which is the value that applications might want to use get "more liberal values". So in that sense, at least under Linux, the behaviour of GNU version of getconf is inconsistent with the documentation (man getconf, man pathconfig).

2. Change the behaviour to follow the POSIX standard. As you pointed out this might be a bit tricky since it could break expectations from existing applications. However, it could be argued, that applications that request the value of _POSIX_PIPE_BUF do really care about getting the POSIX behaviour. They are basically requesting the minimum value of the pipe buffer for _any_ POSIX compliant implementation. So in that sense that variable is quite related to POSIX, otherwise there is no much point on asking for it rather than _PC_PIPE_BUF. In the case this change takes place, the documentation should clearly state the differences with previous behaviour under the section BUGS.

3. Similar to other GNU utilities, change the behaviour to either 1. or 2. depending on POSIXLY_CORRECT environmental variable being defined or not.

Let me know your thoughts on that.
Comment 4 Adhemerval Zanella 2022-05-23 20:47:42 UTC
(In reply to cquike from comment #3)
> Thanks Adhemerval for your comments.
> 
> I agree that the documentation of getconf is not very clear on what the tool
> is supposed to deliver.
> 
> So I see three possible options for this isse:
> 
> 1. Keep the status quo. The current GNU getconf is not POSIX compliant with
> the command of the same name (although to be fair the documentation doesn't
> claim it is). The problem I see is that according to the documentation (man
> getconf) the value returned by getconf corresponds to a system configuration
> var as defined by pathconfig. However, pathconfig in Linux does not define
> _POSIX_PIPE_BUF.  It is simply not possible to get the value of
> _POSIX_PIPE_BUF using pathconfig. Interestingly, the Linux pathconfig
> manpage does actually refer to _POSIX_PIPE_BUF as the minimum value that can
> be used for a pipe buffer, clearly distinguishing it from _PC_PIPE_BUF,
> which is the value that applications might want to use get "more liberal
> values". So in that sense, at least under Linux, the behaviour of GNU
> version of getconf is inconsistent with the documentation (man getconf, man
> pathconfig).

Keep in mind that man-pages is not the canonical documentation.

POSIX standard also defines that for getconf each configuration variable 
shall be determined as if it were obtained by calling the function from
which it is defined to be available (either fpathconf, sysconf, or confstr) [1].

And for fpathconf, POSIX only defines a handfull of symbolic constants an 
implementation should support (which _POSIX_PIPE_BUF is not listed).  Also 
for _POSIX_PIPE_BUF, it means the 'Maximum number of bytes that is guaranteed 
to be atomic when writing to a pipe'.

So I do not agree that glibc getconf is not POSIX compliant with current POSIX 
requirements, neither that returning a value different than _PC_PIPE_BUF for
_POSIX_PIPE_BUF makes much sense, since it is the system obtained value the one 
that actually matters.

> 
> 2. Change the behaviour to follow the POSIX standard. As you pointed out
> this might be a bit tricky since it could break expectations from existing
> applications. However, it could be argued, that applications that request
> the value of _POSIX_PIPE_BUF do really care about getting the POSIX
> behaviour. They are basically requesting the minimum value of the pipe
> buffer for _any_ POSIX compliant implementation. So in that sense that
> variable is quite related to POSIX, otherwise there is no much point on
> asking for it rather than _PC_PIPE_BUF. In the case this change takes place,
> the documentation should clearly state the differences with previous
> behaviour under the section BUGS.

This does not make sense, if user issues 'getconf _POSIX_PIPE_BUF <path>'
and the system defined a minimum value that is larger than what POSIX defines
as the minimum value; the implementation does follow POSIX since
'conforming implementation shall provide a value at least this large or 
shall have no limit' [1].

I am still not really convinced that getconf should return any value defined
in limits.h, since for the users perspective what really matters is the 
implementation-defined one and whether it supports the minimal POSIX values
or not (for the limits.h a conforming implementation should support the
minimum set anyway).

> 
> 3. Similar to other GNU utilities, change the behaviour to either 1. or 2.
> depending on POSIXLY_CORRECT environmental variable being defined or not.

And I don't think this will make getconf more POSIX compliant, since POSIX
does not state POSIXLY_CORRECT as an affecting environment variable. 

> 
> Let me know your thoughts on that.


[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html
[2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/fpathconf.html
[3] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
Comment 5 cquike 2022-05-24 00:57:55 UTC
> POSIX standard also defines that for getconf each configuration variable 
> shall be determined as if it were obtained by calling the function from
> which it is defined to be available (either fpathconf, sysconf, or confstr)
> [1].
> 
> And for fpathconf, POSIX only defines a handfull of symbolic constants an 
> implementation should support (which _POSIX_PIPE_BUF is not listed).  Also 
> for _POSIX_PIPE_BUF, it means the 'Maximum number of bytes that is
> guaranteed 
> to be atomic when writing to a pipe'.
> 

Maybe I am interpreting it wrongly, but I see that getconf provides variables that are defined via fpathconf, sysconf, confstr _or_ limits.h. The third bullet under "system_var" says literally "The names of the symbolic constants listed under the headings ``Maximum Values'' and ``Minimum Values'' in the description of the <limits.h> header" ([1]). And indeed _POSIX_PIPE_BUF is listed under "Minimum values" in the description of limits.h ([3]) and not under fpathconf, as you correctly mention ([2]).

In fact, consider the output of this small program:

#include <limits.h>
#include <stdio.h>

int main()
{
  printf("_POSIX_PIPE_BUF: %d\n", _POSIX_PIPE_BUF);
}

$ ./a.out
_POSIX_PIPE_BUF: 512

and the output of getconf:

$ getconf _POSIX_PIPE_BUF /
4096

which are, in my opinion, in contradiction. By the way, it also highlights yet another problem with the current implementation: for _POSIX_PIPE_BUF it shouldn´t be needed to provide a path, since it is a symbolic constant.


> for the users perspective what really matters is the 
> implementation-defined

For most applications I agree with you. That means that POSIX conformant applications applications are most interested on querying fpathconf(fd, _PC_PIPE_BUF) or the equivalent getconf PIPE_BUF /path . However _strictly_ conformant applications ([4]) should not rely on the implementation supporting a limit larger than _POSIX_PIPE_BUF. It is for those applications where this constant might be useful.

> And I don't think this will make getconf more POSIX compliant, since POSIX
> does not state POSIXLY_CORRECT as an affecting environment variable. 

Yes, you are right.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html
[2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/fpathconf.html
[3] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
[4] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_02_01
Comment 6 Andreas Schwab 2022-05-24 07:49:21 UTC
> And I don't think this will make getconf more POSIX compliant, since POSIX
> does not state POSIXLY_CORRECT as an affecting environment variable. 

This is irrelevant, without POSIXLY_CORRECT a GNU system is not POSIX compliant on purpose.
Comment 7 Adhemerval Zanella 2022-05-26 17:22:39 UTC
(In reply to cquike from comment #5)
> > POSIX standard also defines that for getconf each configuration variable 
> > shall be determined as if it were obtained by calling the function from
> > which it is defined to be available (either fpathconf, sysconf, or confstr)
> > [1].
> > 
> > And for fpathconf, POSIX only defines a handfull of symbolic constants an 
> > implementation should support (which _POSIX_PIPE_BUF is not listed).  Also 
> > for _POSIX_PIPE_BUF, it means the 'Maximum number of bytes that is
> > guaranteed 
> > to be atomic when writing to a pipe'.
> > 
> 
> Maybe I am interpreting it wrongly, but I see that getconf provides
> variables that are defined via fpathconf, sysconf, confstr _or_ limits.h.
> The third bullet under "system_var" says literally "The names of the
> symbolic constants listed under the headings ``Maximum Values'' and
> ``Minimum Values'' in the description of the <limits.h> header" ([1]). And
> indeed _POSIX_PIPE_BUF is listed under "Minimum values" in the description
> of limits.h ([3]) and not under fpathconf, as you correctly mention ([2]).

Another issue is POSIX is not clear how the 'Maximum' and 'Minimum' values should
be obtained, but getting the POSIX defined values seems rational.

> 
> In fact, consider the output of this small program:
> 
> #include <limits.h>
> #include <stdio.h>
> 
> int main()
> {
>   printf("_POSIX_PIPE_BUF: %d\n", _POSIX_PIPE_BUF);
> }
> 
> $ ./a.out
> _POSIX_PIPE_BUF: 512
> 
> and the output of getconf:
> 
> $ getconf _POSIX_PIPE_BUF /
> 4096
> 
> which are, in my opinion, in contradiction. By the way, it also highlights
> yet another problem with the current implementation: for _POSIX_PIPE_BUF it
> shouldn´t be needed to provide a path, since it is a symbolic constant.
> 
> 
> > for the users perspective what really matters is the 
> > implementation-defined
> 
> For most applications I agree with you. That means that POSIX conformant
> applications applications are most interested on querying fpathconf(fd,
> _PC_PIPE_BUF) or the equivalent getconf PIPE_BUF /path . However _strictly_
> conformant applications ([4]) should not rely on the implementation
> supporting a limit larger than _POSIX_PIPE_BUF. It is for those applications
> where this constant might be useful.

Right, it seems that other system do return the limits.h value (Solaris 11, AIX 7.2,
and MacOSX) so it seems that it would be good to have the same behavior.

> 
> > And I don't think this will make getconf more POSIX compliant, since POSIX
> > does not state POSIXLY_CORRECT as an affecting environment variable. 
> 
> Yes, you are right.
> 
> [1] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html
> [2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/fpathconf.html
> [3] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
> [4]
> https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.
> html#tag_02_02_01
Comment 8 cquike 2022-07-29 22:10:00 UTC
Thank you for posting the patch to libc-alpha, which I have seen now. Do you know if there is a chance of this to be merged?
Thank you!