https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124225

            Bug ID: 124225
           Summary: Missing race condition protection for
                    Search_Fall_Back_Handler
           Product: gcc
           Version: 15.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: liam at liampwll dot com
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

Created attachment 63777
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63777&action=edit
fix

Search_Fall_Back_Handler recursively searches parents of a task to find a
fallback termination handler but it does not hold the lock for the tasks it
searches.

I came across this while debugging a different fallback handler issue and I
don't have any real code where this is broken, but it seems like an easy fix.

This was previously protected by an atomic which was seemingly mistakenly
removed without noticing Search_Fall_Back_Handler
(g:85a40c43fb6f09054f535bae43e8622c971bcc48), but an atomic there was always
broken anyway as demonstrated by the below program on x64 (where the variable
is implicitly atomic).

This patch here probably have the potential to deadlock some very weird code,
but you'd have to be explicitly trying to break the compiler to encounter that.

Reproducer below, this should print 10001 (beware this creates 10001 tasks):


pragma Ada_2022;

with Ada.Exceptions;
with Ada.Task_Identification;
with Ada.Task_Termination;
with Ada.Text_IO;

procedure Example is
   protected type Fallback_Hit_Counter_Type is
      procedure Handler
        (Cause : Ada.Task_Termination.Cause_Of_Termination;
         T     : Ada.Task_Identification.Task_Id;
         X     : Ada.Exceptions.Exception_Occurrence);
   private
      Count : Natural := 0;
   end Fallback_Hit_Counter_Type;

   protected body Fallback_Hit_Counter_Type is
      procedure Handler
        (Cause : Ada.Task_Termination.Cause_Of_Termination;
         T     : Ada.Task_Identification.Task_Id;
         X     : Ada.Exceptions.Exception_Occurrence) is
      begin
         Count := Count + 1;
         Ada.Text_IO.Put_Line (Count'Image);
      end Handler;
   end Fallback_Hit_Counter_Type;

   Fallback_Hit_Counter : access Fallback_Hit_Counter_Type :=
     new Fallback_Hit_Counter_Type;

   task T;

   task body T is
      task type T2;

      task body T2 is
      begin
         delay 1.0;
      end T2;

      Tasks : array (1 .. 10_000) of T2;
   begin
      for I in 1 .. 100_000_000 loop
         Ada.Task_Termination.Set_Dependents_Fallback_Handler (null);
         Ada.Task_Termination.Set_Dependents_Fallback_Handler
           (Fallback_Hit_Counter.all.Handler'Access);
      end loop;
   end T;
begin
   Ada.Task_Termination.Set_Dependents_Fallback_Handler
     (Fallback_Hit_Counter.all.Handler'Access);
end Example;

Reply via email to