Patchwork [Ada] Fix race condition in freeing tasks

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 5, 2012, 2:21 p.m.
Message ID <20121005142149.GA5858@adacore.com>
Download mbox | patch
Permalink /patch/189489/
State New
Headers show

Comments

Arnaud Charlet - Oct. 5, 2012, 2:21 p.m.
This patch fixes a subtle race condition where the master task and the child
task may free the child task concurrently.  Found by code reading.

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-10-05  Arnaud Charlet  <charlet@adacore.com>

	* s-tassta.adb: Update comments.
	(Vulnerable_Complete_Master): If Free_On_Termination is set, do
	nothing, and let the task free itself if not already done.

Patch

Index: s-tassta.adb
===================================================================
--- s-tassta.adb	(revision 192066)
+++ s-tassta.adb	(working copy)
@@ -1905,7 +1905,16 @@ 
       C := All_Tasks_List;
       P := null;
       while C /= null loop
-         if C.Common.Parent = Self_ID and then C.Master_of_Task >= CM then
+         --  If Free_On_Termination is set, do nothing here, and let
+         --  the task free itself if not already done, otherwise we
+         --  risk a race condition where Vulnerable_Free_Task is called
+         --  in the loop below, while the task calls Free_Task itself,
+         --  in Terminate_Task.
+
+         if C.Common.Parent = Self_ID
+           and then C.Master_of_Task >= CM
+           and then not C.Free_On_Termination
+         then
             if P /= null then
                P.Common.All_Tasks_Link := C.Common.All_Tasks_Link;
             else
@@ -2088,9 +2097,7 @@ 
    --  is called from Expunge_Unactivated_Tasks.
 
    --  For tasks created by elaboration of task object declarations it is
-   --  called from the finalization code of the Task_Wrapper procedure. It is
-   --  also called from Ada.Unchecked_Deallocation, for objects that are or
-   --  contain tasks.
+   --  called from the finalization code of the Task_Wrapper procedure.
 
    procedure Vulnerable_Free_Task (T : Task_Id) is
    begin