public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "jhb.chat at gmail dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug ada/114710] New: Temporary object finalized too late
Date: Sat, 13 Apr 2024 17:09:31 +0000	[thread overview]
Message-ID: <bug-114710-4@http.gcc.gnu.org/bugzilla/> (raw)

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

            Bug ID: 114710
           Summary: Temporary object finalized too late
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jhb.chat at gmail dot com
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

Created attachment 57940
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57940&action=edit
temporrary finalized too late

Version:  GCC/GNAT version 13.2.0, Win10 msys2 and Godbolt

Godbolt indicates this is a long standing functionality (all the way down to
8.2, which is the last I could check there).

When making a scoped lock / scoped mutex, I found that temporary variables
generated by a function were not being finalized after they were no longer
used.  This lead to a deadlock situation with the scope lock / scoped mutex. 
There doesn't appear to be any reason to hold onto the object returned by the
Lock function in this example. The call to the Lock function returns a
temporary object that is never saved and should be finalized immediately

In the example below, you can see the finalization happen after the body of
main completes instead of before by commenting out the v2 declaration (to
remove the deadlock).

Example:
-------------------------------------------------------
with Ada.Finalization;
with Ada.Text_IO; use Ada.Text_IO;

procedure Example is

    package Deadlocker is

        protected type Mutex is
            entry Lock;
            procedure Unlock;
        private
            Locked : Boolean := False;
        end Mutex;

        type Instance
            (Element : not null access Integer) 
        is 
            new Ada.Finalization.Limited_Controlled
        with record
            M : not null access Mutex;
        end record;

        overriding procedure Finalize(Self : in out Instance);

        type Object is tagged limited record
            Locker : aliased Mutex;
            Item : aliased Integer;
        end record;

        function Lock
            (Self : aliased in out Object) 
             return Instance'Class;

    end Deadlocker;

    package body Deadlocker is
        protected body Mutex is
            entry Lock when not Locked is
            begin
                Locked := True;
                Put_Line("Locked!");
            end Lock;

            procedure Unlock is
            begin
                Locked := False;
                Put_Line("Unlocked!");
            end Unlock;
        end Mutex;

        function Lock
            (Self : aliased in out Object) 
            return Instance'Class
        is begin
            return Result : Instance := Instance'
                (Ada.Finalization.Limited_Controlled with
                 Element => Self.Item'Access, 
                 M       => Self.Locker'Access)
            do 
                Put_Line("Locking...");
                Result.M.Lock;
            end return;
        end Lock;

        procedure Finalize(Self : in out Instance) is
        begin
            Put_Line("Unlocking...");
            Self.M.Unlock;
        end Finalize;
    end Deadlocker;

    Test : Deadlocker.Object;
    v1 : constant Integer := Test.Lock.Element.all; -- Should release lock
after
    v2 : constant Integer := Test.Lock.Element.all; -- Should release lock
after
begin
    Put_Line("In main body");
end Example;
-------------------------------------------------------

Output:
-------------------------------------------------------
Program returned: 143
Program stdout

Locking...
Locked!
Locking...

Program stderr


Killed - processing time exceeded
Program terminated with signal: SIGKILL
-------------------------------------------------------


Expected Output:
-------------------------------------------------------
Program returned: 0
Program stdout

Locking...
Locked!
Unlocking...
Unlocked!
Locking...
Locked!
Unlocking...
Unlocked!
In main body
-------------------------------------------------------

             reply	other threads:[~2024-04-13 17:09 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-13 17:09 jhb.chat at gmail dot com [this message]
2024-04-20 15:49 ` [Bug ada/114710] temporary " ebotcazou at gcc dot gnu.org
2024-04-21  7:29 ` ebotcazou at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-114710-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).