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?
next 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