Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0001806 [Issue 8 drafts] Shell and Utilities Editorial Clarification Requested 2024-02-02 22:53 2024-03-25 16:31
Reporter calestyo View Status public  
Assigned To
Priority normal Resolution Accepted As Marked  
Status Resolution Proposed   Product Version Draft 4
Name Christoph Anton Mitterer
Organization
User Reference
Section Shell Command Language
Page Number 2571
Line Number 83916, ff.
Final Accepted Text Note: 0006727
Summary 0001806: ambiguous description of which attribtes `unset` unsets in case of readonly attribute being set
Description Hey.

Lines 83916 to 83918 say:
> The unset utility shall unset each variable or function
> definition specified by name that does not have the
> readonly attribute and remove any attributes other than
> readonly that have been given to name (see Section 2.15
> export and readonly).

I'd interpret this as:

- Unless readonly is set, it unsets the variable/value (clearly).

- But IMO it's not absolutely clear what it does to attributes:
  "and remove any attributes other than readonly"
  would strictly speaking mean:
  - it does not unset readonly
  - it DOES unset any other attributes (i.e. export)

Those shells that I could test, behaved how one would expect, i.e. once readonly is set, unset cannot modify the variable (neither it's value, nor ANY of its attributes).

Desired Action If the above assumption is correct, then:

Change lines 83916 to 83918 to:

The unset utility shall unset each variable or function definition specified by name that does not have the readonly attribute. If name is unset it shall further remove any attributes that have been given to it (see Section 2.15 export and readonly), unless it has the readonly attribute.



The subclause ", unless it has the readonly attribute" could in principle also be omitted, but makes it perhaps clearer.


Thanks,
Chris.

btw: There is no specification, whether unset shall continue trying with further names, if one readonly is encountered.
Not sure if that's left open by intention.
Tags tc1-2024
Attached Files

- Relationships

-  Notes
(0006647)
larryv (reporter)
2024-02-03 00:30

You may want to read 0001075 for some of the thinking behind the current wording.
(0006653)
mirabilos (reporter)
2024-02-13 20:10

Huh, this looks indeed like a bug introduced by 1075.

Specifically, the comment by joerg, which I read as “the bourne shell first checks if the variable is readonly; if so, it errors; if not, it unsets the content and removes all attributes”, and which corresponds to my reading, was misinterpreted.

And when I start a jsh to test it, I get…

$ foo=bar
$ export foo
$ env | grep foo
foo=bar
$ readonly foo
$ env | grep foo
foo=bar
$ unset foo; echo $?
foo: is read only
$ echo $?
1
$ env | grep foo
foo=bar

… which supports my reading, and calestyo’s expected behaviour.
(0006654)
mirabilos (reporter)
2024-02-13 20:25

How about something like this (I *think* there are no possible
other causes of “could not be unset” than it being readonly any
more):

────────────────────────────────────────────────────────────────────────

Each variable or function specified by name that does not have the
readonly attribute (see Section 2.15 export and readonly) shall be
unset and have all of its attributes removed.

If -v is specified, name refers to a variable name and the shell
shall unset it and remove it from the environment.

If -f is specified, name refers to a function and the shell shall
unset the function definition.

If neither -f nor -v is specified, name refers to a variable; if
a variable by that name does not exist, it is unspecified whether
a function by that name, if any, shall be unset.

Unsetting a variable or function that was not previously set shall
not be considered an error and does not cause the shell to abort.

[…]

EXIT STATUS

    0 All name operands were successfully unset or not set.
   >0 At least one name was readonly and could not be unset.
(0006655)
calestyo (reporter)
2024-02-13 22:48

Well, from a recent curiosity I've had brought up on help-bash, and where I personally would have thought that the wording/intention and thus order of respectively context in which things should be made was rather clear, I learned again that wordings may be interpreted quite differently and unless something is most definitely specified, people will interpret it to their likings (which of course includes myself).

So I think whatever we write in the end, it should be 100% clear what happens:

- unsetting means: (trying) to unset an already set variable with or without attributes as well as trying to unset a not set variable which has however attributes

- No error, unless the unsetting fails for which ever reason (like the attribute readonly being set or an invalid identifier being used) especially not in the case when it's tried to unset a variable (with a valid identifier) that is not set, regardless of whether or not it has attributes (other than readonly) set

- Once the readonly attribute readonly is set, the set state of the variable, its value and all of it's attributes are no more changeable. This implies, that unsetting such variable would in no way change it (including none of it's attributes), but also that one cannot e.g. first set the readonly attribute on an unset variable, and later on set it once.

I think the latter is not really 100% clear by the current wording of the readonly built-in, which says:
"The values of variables with the readonly attribute cannot be changed by subsequent assignment, nor can those variables be unset by the unset utility."
=> IMO that "change value" could be interpreted as "it only affects variables which have a value / are set, because if the variable is not yet set (but has already the readonly attriute, setting it then, doesn't really change the value, or does it?

- Not sure whether the standard should say anything with respect to "local" variables (which it does not cover). Can one "re-define" a readonly variable at a local scope? Should that left be an implementation decision, or would allowing that already break the intentions behind readonly?

- What happens if unset fails for one variable. Will it still try the others before it returns non-zero? Is that unspecified?
(0006656)
calestyo (reporter)
2024-02-13 22:55

And I just noticed: The last case could in principle also be: if it would fail for at least one variable, none are unset.
(0006679)
kre (reporter)
2024-02-25 07:34

When working out the desired wording to make this clear (and I believe I
agree with what is being proposed, but as I said in a note to 0001075,
the text here should not refer to "all attributes" - since everyone agrees
that readonly cannot be undone by "unset" - the only attribute that the
standard knows about is "export" - the text just need to say that if the
variable is not readonly, the export attibute is cleared, as well as the
value.

What bash chooses to do with its "integer" attribute is none of our business
(nor any of its others) - similarly for other shells that have more
attributes than readonly and export ... the NetBSD shell has an "unexportable"
attribute, that prevents "export" being applied (we have one specific use
of that one).

With all of this, everyone should also note that being readonly does not
(in any shell I can test) prevent the "export" attribute from being set,
it just stops "unset" from clearing it. There's no reason a shell that
provides some other way (than unset) from removing the export attribute
cannot allow that other mechanism to remove "export" from a readonly
variable (all of that is beyond the standard however - but the standard
must not prohibit any of this.)
(0006680)
calestyo (reporter)
2024-02-25 21:50

Hmm, I'd personally rather say the opposite and that `unset` and the concepts behind it and attributes should be generic, and if the meaning of `unset` is to clear the state of a variable it should really be generally defined like that.

Not yet another source of non-portability because people have to consider that out of 10 shell there are 12 different behaviours of how shells would unset.
(0006681)
larryv (reporter)
2024-02-25 22:36

As kre said in Note: 0003934:
If "unset" claims that "all" attributes are reset, then that would mean that some attribute that most of us have never heard of (the "null on weekends" attribute) must be reset by the "unset" command - yet the shell that invented that attribute might not act that way, and perhaps for good reason.
The standard doesn't generically define what variable/function attributes are, so the handling of attributes other than the export and readonly attributes is necessarily beyond its scope, and the notion of "non-portability" simply doesn't apply. The standard cannot govern that which is beyond its jurisdiction.
(0006682)
calestyo (reporter)
2024-02-25 23:00

Well, then POSIX looses effectively a portable way to make sure to fully unset the state a variable, as any implementation may add its own exceptions to this.

The tool's description in POSIX even is "unset - unset values and attributes of variables and functions", and I think it's natural to expect it to do just that (unless of course the standard provides exceptions, as in readonly)
(0006683)
larryv (reporter)
2024-02-25 23:16

You have it backwards. Although the Austin Group sometimes works actively to align implementations (e.g., 0001629), in general the role of the standard is not to impose behavior but to describe existing behavior.
(0006684)
larryv (reporter)
2024-02-25 23:22

Re: Note: 0006679:
With all of this, everyone should also note that being readonly does not (in any shell I can test) prevent the "export" attribute from being set, it just stops "unset" from clearing it. There's no reason a shell that provides some other way (than unset) from removing the export attribute cannot allow that other mechanism to remove "export" from a readonly variable (all of that is beyond the standard however - but the standard must not prohibit any of this.)
Indeed, this is already possible in bash 5.2.26 (including POSIX mode), ksh93u+ 2012-08-01, yash 2.54 (except POSIXly-correct mode), and zsh 5.9 (native mode):
readonly foo
export foo
if [ "$YASH_VERSION" ]
then
    typeset -X foo
else
    typeset +x foo
fi
(0006727)
geoffclare (manager)
2024-03-25 16:29
edited on: 2024-03-25 16:30

Proposed interpretation (review timer to start after approval of issue 8) ...

Interpretation response
------------------------
The standard is unclear on this issue, and no conformance distinction can be made between alternative implementations based on this. This is being referred to the sponsor.

Rationale:
-------------
The standard should not attempt to specify behavior for non-standard variable attributes. An application which sets such an attribute is using an extension, and the behavior of the extension is entirely a matter for the implementation.

Notes to the Editor (not part of this interpretation):
-------------------------------------------------------

On page 2571 line 83916-83923, replace the first four paragraphs of DESCRIPTION with:
The unset utility shall unset a variable or function definition specified by each name operand, as follows:

  • If −v is specified, name refers to a variable. If the named variable exists and does not have the readonly attribute, the shell shall unset it and shall remove the export attribute if the variable has it. Read-only variables cannot be unset.

  • If −f is specified, name refers to a function. If the named function exists, the shell shall unset the function definition.

  • If neither −f nor −v is specified and name refers to a variable that exists, the variable shall be unset as if -v was specified; if a variable by that name does not exist, it is unspecified whether a function by that name, if any, is unset.


On page 2573 line 83953, change:
All name operands were successfully unset.

to:
Each name operand either did not exist or was successfully unset.



- Issue History
Date Modified Username Field Change
2024-02-02 22:53 calestyo New Issue
2024-02-02 22:53 calestyo Name => Christoph Anton Mitterer
2024-02-02 22:53 calestyo Section => Shell Command Language
2024-02-02 22:53 calestyo Page Number => 2571
2024-02-02 22:53 calestyo Line Number => 83916, ff.
2024-02-03 00:30 larryv Note Added: 0006647
2024-02-13 20:10 mirabilos Note Added: 0006653
2024-02-13 20:25 mirabilos Note Added: 0006654
2024-02-13 22:48 calestyo Note Added: 0006655
2024-02-13 22:55 calestyo Note Added: 0006656
2024-02-25 07:34 kre Note Added: 0006679
2024-02-25 21:50 calestyo Note Added: 0006680
2024-02-25 22:36 larryv Note Added: 0006681
2024-02-25 23:00 calestyo Note Added: 0006682
2024-02-25 23:16 larryv Note Added: 0006683
2024-02-25 23:22 larryv Note Added: 0006684
2024-03-25 16:29 geoffclare Note Added: 0006727
2024-03-25 16:30 geoffclare Note Edited: 0006727
2024-03-25 16:31 geoffclare Final Accepted Text => Note: 0006727
2024-03-25 16:31 geoffclare Status New => Resolution Proposed
2024-03-25 16:31 geoffclare Resolution Open => Accepted As Marked
2024-03-25 16:31 geoffclare Tag Attached: tc1-2024


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker