AI22-0058-1

!standard D.2.6(9/5)                                      23-04-26  AI22-0058-1/03

!standard D.2.6(29/2)

!standard D.5.1(4)

!standard D.5.1(5)

!standard D.5.1(9)

!standard D.11(3/5)

!standard D.11(8)

!standard D.14(5/2)

!standard D.14(17/2)

!class Binding Interpretation 22-01-11

!status No Action  8-0-0   23-06-12

!status work item 23-06-06

!status ARG Approved 15-0-0  23-01-19

!status work item 22-01-11

!status received 22-01-11

!priority Low

!difficulty Easy

!qualifier Clarification

!subject Preconditions for checking Task_Ids

!summary

Preconditions, rather than wording, are used to check Task_Ids in various Annex D subprograms.

!issue

Ada 2022 attempts to use preconditions and postconditions as much as possible. The following rule appears in a number of places in Annex D:

For all the operations defined in <<some package>>, Tasking_Error is raised if the task identified by T has terminated. Program_Error is raised if the value of T is Null_Task_Id.

This would be better described by a precondition.

!recommendation

Add preconditions to various subprograms in Annex D.

!wording

Add:

with Pre => (T /= Null_Task_Id or else raise Program_Error)
              and then
            (not Is_Terminated (T)
                or else raise Tasking_Error));

to Set_Deadline, Get_Deadline, Set_Relative_Deadline, Get_Relative_Deadline, Get_Last_Release_Time in D.2.6(9/5); to Set_Priority in D.5.1(4); to Get_Priority in D.5.1(5); to Hold, Continue, and Is_Held in D.11(3/5); and to Clock in D.14(5/2).

Add use Ada.Task_Identification;  on each of the above packages immediately after with Ada.Task_Identification;

In AARM D.5.1(12.a):

Replace  "the above rule saying" with "the precondition".

Delete D.2.6(29/2), D.5.1(9), D.11(8).

Modify D.14(17/2):

The function Clock returns the current execution time of the task identified by T[; Tasking_Error is raised if that task has terminated; Program_Error is raised if the value of T is Task_Identification.Null_Task_Id].

!discussion

The original English-language rule is backwards – one has to check for Null_Task_Id before checking whether a task is terminated.

Ada.Task_Identification.Is_Terminated is defined to raise Program_Error when passed a Null_Task_Id (see C.7.1), so we would not need to handle that case explicitly. We did so anyway to make the function of the precondition as clear as possible. Thus, this makes no semantic change (assuming a sensible reading of the original text).

[Editor's note: Since this makes no semantic change, it is classified as a Binding Interpretation. It could even be considered a presentation change, except that this does open the possibility of Suppressing the precondition check. Note, however, that there is no check name defined for the packages defined in the various annexes (that seems to be an omission, but one that should be considered on its own merits in a separate AI).]

!ACATS test

No semantic change is intended, so existing tests (if they exist) should cover this case.

!appendix

This AI was promoted from AI12-0316-1 to be reconsidered for post-Ada 2022 work. The !appendix of the original AI has additional motivation and discussion.

The first version of this AI was rewritten to use the suggestion from Randy Brukardt of February 26, 2019 to simplify the change and overcome objections raised during Meeting #60D.


 

From: Niklas Holsti

Sent: Sunday, June 04, 2023 12:58 PM (WG 9 List)

After reviewing these AIs I have some comments on four of them ...

[Editor’s note: We only include the relevant discussion here, and in the following messages.]

Changing from a prose rule to a precondition introduces a race

condition: the task in question might terminate after the precondition is checked, but before the operation actually tries to operate on the task. In that case the precondition check would pass, but still the operation should fail, reasonably by propagating Tasking_Error.

So while a precondition works for checking that the given Task_Id is not Null_Task_Id, I don't think it works well for checking if the task is terminated, and I propose rejecting that part of the AI.

Note that 6.1.1(34/5) says that in a call on a protected operation the precondition checks are done before starting the protected action, suggesting that an implementation that implements these tasking operations as protected operations would necessarily suffer from this race condition.

If a precondition is preferred also for the termination check there should be an Implementation Requirement that forbids the race condition, but that seems a strange hack.

By the way, there seems to be a minor error in D.5.1(12.a): it says that Get_Priority raises Program_Error if the task still exists but is terminated, while D.5.1(8) says that Tasking_Error is raised in that case, which seems to be correct (also from what is said in this AI).


 

From: Tucker Taft

Sent: Monday, June 05, 2023 11:53 AM (WG 9 List)

>Changing from a prose rule to a precondition introduces a race

>condition: the task in question might terminate after the precondition

>is checked, but before the operation actually tries to operate on the

>task. In that case the precondition check would pass, but still the

>operation should fail, reasonably by propagating Tasking_Error.

>So while a precondition works for checking that the given Task_Id is not

>Null_Task_Id, I don't think it works well for checking if the task is

>terminated, and I propose rejecting that part of the AI.

Good point.  I agree with your logic.  It is reminiscent of the problem of trying to use a precondition to detect that a Name_Error is going to be raised by an Open file operation.  Clearly the file might be deleted or created in the period between evaluating the preconditions and actually attempting to open the file.  So preconditions are inappropriate for anything that involves independent threads of control.

 

[Editor’s note: Tucker quoted the rest of the note and said “Agreed.”, twice..]


 

From: Randy Brukardt

Sent: Tuesday, June 06, 2023 1:45 AM (WG 9 List)

WG 9 is not the place to work out anything technical, so anything that can't be cast as an editorial review causes the AI to be withdrawn from the WG 9 approval list.

Clearly, that needs to be done with AI22-0058-1/03 -- Preconditions for checking Task_Ids. ...