!standard C.7.3(8/2) 11-02-12 AI05-0202-1/02 !class binding interpretation 10-02-12 !status work item 10-02-12 !status received 09-09-24 !priority Medium !difficulty Easy !qualifier Omission !subject Task_Termination and Exceptions raised during finalization !summary Exceptions raised during finalization of a task result in the Cause of its termination being reported as Unhandled_Exception, with an exception occurrence that identifies Program_Error. !question Suppose a task has a termination handler set up by either Set_Specific_Handler or Set_Dependents_Fallback_Handler. Suppose the task executes the last statement of the task body normally, but an exception occurs during finalization (as part of the "actions specfied in 7.6 for finalization of a master"). For instance, the task may have a local variable with a controlled part, and a user-defined Finalize routine propagates an exception. What is passed as the Cause parameter to the termination handler? Normal, or Unhandled_Exception? I don't think the wording of C.7.3(8/2) gives a clear answer; it says Cause=>Normal if the task is terminating "due to completing the last statement of its body", and that *is* the reason the task is terminating, it's just that some other unhandled exception came up afterwards. In a similar vein, suppose an exception Exc1 is propagated out of the task body, and in the course of finalizing local objects, another exception Exc2 is propagated (by a user-defined Finalize). Now Cause=>Unhandled_Exception is passed to the termination handler, but which exception does the Exception_Occurrence X refer to? Would Exception_Identity(X) be the identity of Exc1, Exc2, or Program_Error? !recommendation (See Summary.) !wording Modify C.7.3(8/2): The type Termination_Handler identifies a protected procedure to be executed by the implementation when a task terminates. Such a protected procedure is called a handler. In all cases T identifies the task that is terminating. If the task terminates due to completing the last statement of its body, or as a result of waiting on a terminate alternative, {and the finalization of the task body master completes normally,} then Cause is set to Normal and X is set to Null_Occurrence. If the task terminates because it is being aborted, then Cause is set to Abnormal and X is set to Null_Occurrence. If the task terminates because of an exception raised by the execution of its task_body, then Cause is set to Unhandled_Exception and X is set to the associated exception occurrence. {If the task completes normally or due to a terminate alternative, but finalization of the task propagates an exception, then Cause is set to Unhandled_Exception and X is an exception occurrence that identifies the Program_Error exception.} !discussion The only exception that can be propagated by a failed Finalize routine is Program_Error. Finalization of a protected object itself cannot propagate an exception (it will propagate Program_Error to any queued callers). Waiting for tasks cannot propagate an exception (but we might wait forever). Nothing else happens during a finalization. To avoid reporting Normal in the case of failed finalization, we specify that failed finalization results in Unhandled_Exception and an occurrence that identifies Program_Error. We don't specify anthing else about the occurrence, as there is no desire to overspecify the implementation and perhaps thereby introduce undesirable distributed overhead on behalf of this very unusual circumstance. --!corrigendum 3.9.3(4/2) !ACATS Test An ACATS C-Test should be created that checks this semantics. !appendix !topic Clarification on parameters passed to Task_Termination handler !reference C.7.3 !from Adam Beneschan 09-11-20 !discussion Suppose a task has a termination handler set up by either Set_Specific_Handler or Set_Dependents_Fallback_Handler. Suppose the task executes the last statement of the task body normally, but an exception occurs during finalization (as part of the "actions specfied in 7.6 for finalization of a master"). For instance, the task may have a local variable with a controlled part, and a user-defined Finalize routine propagates an exception. What is passed as the Cause parameter to the termination handler? Normal, or Unhandled_Exception? I don't think the wording of C.7.3(8/2) is 100% clear; it says Cause=>Normal if the task is terminating "due to completing the last statement of its body", and that *is* the reason the task is terminating, it's just that some other unhandled exception came up afterwards. In a similar vein, suppose an exception Exc1 is propagated out of the task body, and in the course of finalizing local objects, another exception Exc2 is propagated (by a user-defined Finalize). Now Cause=>Unhandled_Exception is passed to the termination handler, but which exception does the Exception_Occurrence X refer to? Would Exception_Identity(X) be the identity of Exc1, Exc2, or Program_Error? **************************************************************** From: Tucker Taft Sent: Sunday, February 13, 2011 3:35 PM Here is a rewrite of AI-202, coming to the opposite conclusion, namely that if a task completes normally, but then fails during finalization, the Cause is set to Unhandled_Exception, and the exception occurrence identifies Program_Error. **************************************************************** From: Bob Duff Sent: Sunday, February 13, 2011 4:08 PM > Here is a rewrite of AI-202, coming to the opposite conclusion, namely > that if a task completes normally, but then fails during finalization, > the Cause is set to Unhandled_Exception, and the exception occurrence > identifies Program_Error. Looks good to me. > Answer: Cause is Unhandled_Exception, and Exception_Identity(X) = > Program_Error'Identity. Minor editorial comment: Add "In both cases, " after "Answer: ". (Because !question contains two questions.) [Editor's note: We don't "answer" !questions unless the answer is two or three words. This clearly doesn't qualify, so it was removed completely.] ****************************************************************