madmats@elma.epfl.ch (Mats Weber) (03/31/89)
> Date: 29 Mar 89 09:16:26 GMT > From: mcvax!hp4nl!uva!mel!hm@uunet.uu.net (HansM) > Subject: Two questions > > We are trying to understand Ada tasking and there are two things we fail to > understand: > > 1. When an exception is raised and not handled in a task body, the task > is terminated and the exception is not further propagated, without > notice (11.4.1.8). Why is this? This is because the execution of the task is independent of its creator. If the exception were propagated to the task's creator, the exception handler in the creator could get exceptions from all tasks he has created. For example, if task A creates A.B, A.C and A.D and A.B raises Exception_B and A.C raises exception Exception_C, how would the handler in A deal with them ? The Ada rules on exceptions state that only one exception may be active in any thread of execution. > Is there a way to invoke the kind of traceback that occurs when an > exception is propagated out of the main program? This is system dependant. Some systems notify you when an unhandled exception terminates a task, others don't. If you want to be shure, add handlers to your tasks that notify you when they terminate as the result of an exception (be careful with Text_IO being called by multiple tasks, use semaphores). > 2. When a task has completed its execution, termination is delayed until all > dependent tasks have terminated (9.4.6). As a result, our program > fills up all memory with completed tasks unable to terminate. Why is > this? Can something be done about it (without altering task dependency)? Termination of tasks is a high level concept used in the LRM and has nothing to do with memory use and reclamation. I know some systems implement memory deallocation for tasks very poorly. A good workaround is to reuse your tasks as described in another reply. The reason why a task's termination is delayed until all dependent tasks have terminated can be seen in the following example: procedure Main_Program is task T1; task T3; task body T1 is task T2; Local : Integer; task body T2 is begin ... Some_Action(Local); ... end T2; begin ... end T1; task body T3 is ...; begin ... end Main_Program; If T1 completes before T2 terminates, it must wait for it because T2 may use local items declared in T1. For the same reason, the main program must wait for T1 and T3 to terminate. On the other hand, the termination of T1 and T3 is independent. Mats Weber Swiss Federal Institute of Technology EPFL DI LITh 1015 Lausanne Switzerland e-mail : madmats@elma.epfl.ch
rjh@cs.purdue.EDU (Bob Hathaway) (04/01/89)
In article <890331161111.20401e9f@elcc.epfl.ch> madmats@elma.epfl.ch (Mats Weber) writes: >> 1. When an exception is raised and not handled in a task body, the task >> is terminated and the exception is not further propagated, without >> notice (11.4.1.8). Why is this? > >This is because the execution of the task is independent of its creator. According to section 9.4.1: "Each task depends on at least one master.". >If the exception were propagated to the task's creator, the exception >handler in the creator could get exceptions from all tasks he has created. >For example, if task A creates A.B, A.C and A.D and A.B raises Exception_B >and A.C raises exception Exception_C, how would the handler in A deal with >them ? >The Ada rules on exceptions state that only one exception may be active in >any thread of execution. According to section 9.3.3, if any child task does not have a handler for a raised exception, the exception TASKING_ERROR is propagated to the master upon conclusion of the activation of all sibling tasks and is propagated to the master only once for any number of concluded child tasks. What is being asserted above? Bob Hathaway rjh@purdue.edu
madmats@elma.epfl.ch (Mats Weber) (04/03/89)
Bob Hathaway (rjh@purdue.edu) writes : >>This is because the execution of the task is independent of its creator. > According to section 9.4.1: "Each task depends on at least one master.". True, but the dependence on a master is for task termination. What I meant by "the execution of the task is independent of its creator" was that the task and its creator are two different threads of execution. >>If the exception were propagated to the task's creator, the exception >>handler in the creator could get exceptions from all tasks he has created. >>For example, if task A creates A.B, A.C and A.D and A.B raises Exception_B >>and A.C raises exception Exception_C, how would the handler in A deal with >>them ? >>The Ada rules on exceptions state that only one exception may be active in >>any thread of execution. >According to section 9.3.3, if any child task does not have a handler for >a raised exception, the exception TASKING_ERROR is propagated to the master >upon conclusion of the activation of all sibling tasks and is propagated >to the master only once for any number of concluded child tasks. What is >being asserted above? TASKING_ERROR is propagated to the master if an exception is raised during the activation (that is, the elaboration of the declarative part) of any child task, not otherwise. - Handlers in the child task do not apply to exceptions raised in its declarative part, just like in other blocks. - If an exception is raised in the child task after completion of its activation (that is, after the reserved word begin of the child task), then this exception is not propagated outside the child task even if the child task does not handle it (the exception gets lost, unnoticed, and the child task becomes completed). - What is being asserted above is what Scott Simpson (trwarcadia!simpson@oberon.usc.edu) says more clearly in his message, i.e. that if the language design would have incorporated exception propagation from already activated children tasks to their direct master, there would be asynchronous communication between the tasks. Moreover, if a given master has two or more child tasks, then several exceptions might be raised simultaneously in the master's thread of execution. - The master waits for the completion of the activation of all its children before he (the master) begins executing its own sequence of statements. This waiting makes it possible for Tasking_Error to be raised at a well defined point in the master (just before its first statement). Mats Weber Swiss Federal Institute of Technology EPFL DI LITh 1015 Lausanne Switzerland e-mail : madmats@elma.epfl.ch
NCOHEN@IBM.COM (Norman Cohen) (04/03/89)
Ref: INFO-ADA Digest Volume 89 Issue 96 (Sat, Apr 1, 1989) Item #5 Bob Hathaway writes: >According to section 9.3.3, if any child task does not have a handler >for a raised exception, the exception TASKING_ERROR is propagated to the >master upon conclusion of the activation of all sibling tasks and is >propagated to the master only once for any number of concluded child >tasks. What is being asserted above? Paragraph 9.3(3) refers to exceptions arising during the ACTIVATION of a task. Activation is defined in 9.3(1) as follows: The initial part of this execution [of a task body] is called the _activation_ of the task object, and also that of the designated task; it consists of of the elaboration of the declarative part, if any, of the task body. To understand the rules given in paragraphs 9.3(2) and 9.3(3), consider the following example: declare A, B : Some_Task_Type; C : array (1 .. 10) of Some_Task_Type; begin -- (*) S; end; (Some_Task_Type is some task type.) Twelve task objects (A, B and C(1) through C(10)) are declared in the declarative part of the block statement. The following events occur: 1. After the task executing the block statement reaches the point marked (*), the task pauses, and twelve new tasks are now created to be designated by the twelve declared task objects. 2. Each of these twelve new tasks asynchronously executes the declarative part of the Some_Task_Type task body (or dies trying). 3. THE TWELVE NEW TASKS AND THE TASK EXECUTING THE BLOCK STATEMENT ALL SYNCHRONIZE. If one or more of the twelve new tasks died trying to elaborate its declarative part (i.e., raised an exception), TASKING_ERROR is raised (once) in the block statement, at point (*). Otherwise, after synchronizing, the twelve new tasks and the task executing the block statement begin asynchronous execution (with execution of the block statement resuming at point (*)). If any of the twelve new tasks raises an unhandled exception AFTER this synchronization point, no exception is propagated to the task executing the block statement. Norman Cohen