comp.lang.ada
 help / color / mirror / Atom feed
From: Jere <jhb.chat@gmail.com>
Subject: Tracing a race condition
Date: Sat, 2 Feb 2019 12:01:49 -0800 (PST)
Date: 2019-02-02T12:01:49-08:00	[thread overview]
Message-ID: <fd938d32-7169-474f-b39e-006d785b07ef@googlegroups.com> (raw)

I was running a rather large code base which on rare occasion
throws a PROGRAM_ERROR "finalize/adjust raised exception".  After
working on it some time, I narrowed it down to a call to Release
in the Object package of Dmitry's simple components.  This narrows
the problem down to at least a couple of options (maybe more):

1.  An object that a task has an access to goes out of scope early
2.  A potential race condition in the Release procedure

I am still trying to trace through the code (not mine, so learning
how it works) to verify the status of #1.  I did take a look at #2 as
well though.  Here is the Entity type and the Release procedure:

***************************
   type Entity is new Ada.Finalization.Limited_Controlled with record
      Use_Count : Natural := 0; -- Reference count
   end record;
   type Entity_Ptr is access all Entity'Class;
***************************

***************************
   procedure Release (Ptr : in out Entity_Ptr) is
      procedure Free is new
         Ada.Unchecked_Deallocation (Entity'Class, Entity_Ptr);
   begin
      if Ptr /= null then
         declare
            Object : Entity'Class renames Ptr.all;
         begin
            Decrement_Count (Object);
            if Object.Use_Count > 0 then
               return;
            end if;
         end;
         Free (Ptr);
      end if;
   end Release;
***************************

Source: http://www.dmitry-kazakov.de/ada/components_4_38.tgz

Decrement_Count simply calls a protected procedure to update
the Use_Count field of the Object.


I think what is happening is Task A calls a series of code
that eventually causes a call to Release on an object and 
so does Task B.  When that happens, there is a small chance
of the following situation:

Task A:  Decrement_Count(Object);  -- Use_Count goes down to 1
Task A gives up its time slot
Task B resumes
Task B:  Decrement_Count(Object);  -- Use_Count goes down to 0
Task B:  if Object.Use_Count > 0 then -- skips this since 0
...
Task B:  Free(Ptr);  -- This free is logically wrong (early)
...
Task B gives up its time slot
Task A resumes
Task A:  if Object.Use_Count > 0 then -- skips this since 0
...
Task A:  Free(Ptr);  -- This free causes the exception (I think)

That doesn't mean that the #1 scenario isn't also a problem, but
I am still looking at it to verify.  In the mean time, is this
a potential race condition in the Release procedure?


             reply	other threads:[~2019-02-02 20:01 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-02 20:01 Jere [this message]
2019-02-02 20:52 ` Tracing a race condition Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox