comp.lang.ada
 help / color / mirror / Atom feed
* Freeing access-to-task objects
@ 2022-09-30 10:16 Emmanuel Briot
  2022-10-01 11:40 ` J-P. Rosen
  0 siblings, 1 reply; 11+ messages in thread
From: Emmanuel Briot @ 2022-09-30 10:16 UTC (permalink / raw)


Please find a new blog post at:

https://deepbluecap.com/freeing-task-access-objects/

Abstract:
Freeing Ada tasks could result in accessing freed memory. This post describes the proper way of freeing access-to-task objects.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-09-30 10:16 Freeing access-to-task objects Emmanuel Briot
@ 2022-10-01 11:40 ` J-P. Rosen
  2022-10-01 11:58   ` Dmitry A. Kazakov
  2022-10-01 14:01   ` Jeffrey R.Carter
  0 siblings, 2 replies; 11+ messages in thread
From: J-P. Rosen @ 2022-10-01 11:40 UTC (permalink / raw)


Le 30/09/2022 à 12:16, Emmanuel Briot a écrit :
> Please find a new blog post at:
> 
> https://deepbluecap.com/freeing-task-access-objects/
> 
> Abstract:
> Freeing Ada tasks could result in accessing freed memory. This post describes the proper way of freeing access-to-task objects.

I don't like an active loop to wait for task termination. There are 
other ways:
1) declare the access type in a block, which is then the master of the 
tasks. When you exit the block, the tasks are terminated.
2) declare in the tasks an entry which is never accepted, then call this 
entry from the main. When the task terminates, it raises tasking_error 
in the (unserved) callers - you can free the task from the exception 
handler.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-01 11:40 ` J-P. Rosen
@ 2022-10-01 11:58   ` Dmitry A. Kazakov
  2022-10-01 21:26     ` Björn Lundin
  2022-10-01 14:01   ` Jeffrey R.Carter
  1 sibling, 1 reply; 11+ messages in thread
From: Dmitry A. Kazakov @ 2022-10-01 11:58 UTC (permalink / raw)


On 2022-10-01 13:40, J-P. Rosen wrote:
> Le 30/09/2022 à 12:16, Emmanuel Briot a écrit :
>> Please find a new blog post at:
>>
>> https://deepbluecap.com/freeing-task-access-objects/
>>
>> Abstract:
>> Freeing Ada tasks could result in accessing freed memory. This post 
>> describes the proper way of freeing access-to-task objects.
> 
> I don't like an active loop to wait for task termination.

IMO, it is the best method.

> There are 
> other ways:
> 1) declare the access type in a block, which is then the master of the 
> tasks. When you exit the block, the tasks are terminated.

That is usually not possible, or if possible, then the task object 
itself can be in the block and no access type needed at all.

Almost all cases when access to task is used is due to language design 
flaw not allowing either usable aggregation of task objects or 
inheritance involving tasks.

> 2) declare in the tasks an entry which is never accepted, then call this 
> entry from the main. When the task terminates, it raises tasking_error 
> in the (unserved) callers - you can free the task from the exception 
> handler.

This is uglier than a loop. However I must admit that it should have 
advantage in terms of performance, both CPU load and latency. A 
disadvantage is that you cannot wait for several tasks that way.

In a production code there is a timeout which limits the overall waiting 
time and sometimes multiple tasks are awaited to terminate.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-01 11:40 ` J-P. Rosen
  2022-10-01 11:58   ` Dmitry A. Kazakov
@ 2022-10-01 14:01   ` Jeffrey R.Carter
  2022-10-01 14:45     ` Emmanuel Briot
  2022-10-09 16:10     ` Stephen Leake
  1 sibling, 2 replies; 11+ messages in thread
From: Jeffrey R.Carter @ 2022-10-01 14:01 UTC (permalink / raw)


On 2022-10-01 13:40, J-P. Rosen wrote:
> 
> 1) declare the access type in a block, which is then the master of the tasks. 
> When you exit the block, the tasks are terminated.

When you exit the block, the access type doesn't exist, so you can't free anything.

-- 
Jeff Carter
"Sir Lancelot saves Sir Gallahad from almost certain temptation."
Monty Python & the Holy Grail
69

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-01 14:01   ` Jeffrey R.Carter
@ 2022-10-01 14:45     ` Emmanuel Briot
  2022-10-09 16:10     ` Stephen Leake
  1 sibling, 0 replies; 11+ messages in thread
From: Emmanuel Briot @ 2022-10-01 14:45 UTC (permalink / raw)


I did not mention it in the blog, but we also like running with the restriction No_Task_Hierarchy (which generates slightly more efficient code, at least in older versions of GNAT if I understand correctly the reasons we have it). So the declare block approach doesn't work, this is one of the big reasons for using access-to-task, too.

Waiting for exceptions is one possibility, though I dislike it because this is using exceptions for what is the normal flow of the program. They also make debugging more complicated.

The active loop is not the best solution, but it isn't very costly in practice. The task terminates fairly soon (depending on the load on the machine), and we could possibly use a delay like 1.0 if we basically want the active loop.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-01 11:58   ` Dmitry A. Kazakov
@ 2022-10-01 21:26     ` Björn Lundin
  0 siblings, 0 replies; 11+ messages in thread
From: Björn Lundin @ 2022-10-01 21:26 UTC (permalink / raw)


On 2022-10-01 13:58, Dmitry A. Kazakov wrote:
> On 2022-10-01 13:40, J-P. Rosen wrote:
>> Le 30/09/2022 à 12:16, Emmanuel Briot a écrit :
>>> Please find a new blog post at:
>>>
>>> https://deepbluecap.com/freeing-task-access-objects/
>>>
>>> Abstract:
>>> Freeing Ada tasks could result in accessing freed memory. This post 
>>> describes the proper way of freeing access-to-task objects.
>>
>> I don't like an active loop to wait for task termination.
> 
> IMO, it is the best method.
> 

I agree, in practice it works very well, at least for our system.
When ported to GNAT in 2003 I used this pattern.

We use it in IPC, where main makes a blocking call to a PO,
looking for incoming messages. The PO is protecting a list,
and main blocks on list_count = 0.

Another task (receive task) in the IPC body blocks on a read call from a 
named pipe.
When a message arrives in the pipe, this task is putting it into the 
PO's list.

Main then unblocks, since list_count >0, gets the message and treats it,

But since the receiver task is blocking as well, it is difficult to make
that call timeout. Sometimes we want main to actually block until a 
message arrives, but sometimes we'd like to timeout after a minute or so.

Main can call the receive procedure with or without a timeout.

If time is used in the call, a third task is started - with new - with a 
timeout time, and a 'stop' entry. This timer task just delays timeout 
time, and writes a timeout message to the pipe when expired - thus 
releasing the blocking task, and also releasing main since a timeout 
message was put in PO's list and list_count becomes > 0.

If a message is put by another process in the pipe, the receiving task 
calls stop on the timer task, removes any timeout messages in the list 
if we had a race, and puts the message in the list.

Here we also loop over the timer task until terminated.

Worked very well for many years in many installations

We do send messages frequently. in bursts up to 100 msgs/s
but average is less likely than 10 msgs/s


1_000_000 msgs/day is not unusual, so memleaks here is a problem


-- 
/Björn

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-01 14:01   ` Jeffrey R.Carter
  2022-10-01 14:45     ` Emmanuel Briot
@ 2022-10-09 16:10     ` Stephen Leake
  2022-10-09 19:42       ` Jeffrey R.Carter
  2022-10-10 20:23       ` AdaMagica
  1 sibling, 2 replies; 11+ messages in thread
From: Stephen Leake @ 2022-10-09 16:10 UTC (permalink / raw)


"Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> writes:

> On 2022-10-01 13:40, J-P. Rosen wrote:
>> 1) declare the access type in a block, which is then the master of
>> the tasks. When you exit the block, the tasks are terminated.
>
> When you exit the block, the access type doesn't exist, so you can't
> free anything.

But Ada frees all objects allocated using the locally declared access
type when the block is exited.

-- 
-- Stephe

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-09 16:10     ` Stephen Leake
@ 2022-10-09 19:42       ` Jeffrey R.Carter
  2022-10-10  8:13         ` Simon Wright
  2022-10-10 20:23       ` AdaMagica
  1 sibling, 1 reply; 11+ messages in thread
From: Jeffrey R.Carter @ 2022-10-09 19:42 UTC (permalink / raw)


On 2022-10-09 18:10, Stephen Leake wrote:
> "Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> writes:
> 
>> On 2022-10-01 13:40, J-P. Rosen wrote:
>>> 1) declare the access type in a block, which is then the master of
>>> the tasks. When you exit the block, the tasks are terminated.
>>
>> When you exit the block, the access type doesn't exist, so you can't
>> free anything.
> 
> But Ada frees all objects allocated using the locally declared access
> type when the block is exited.

This is only required if the access type has Storage_Size specified (ARM 
13.11/18.4 http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11.html#I5208).

-- 
Jeff Carter
"I was hobbling along, minding my own business, all of a
sudden, up he comes, cures me! One minute I'm a leper with
a trade, next minute my livelihood's gone! Not so much as a
'by your leave!' You're cured, mate. Bloody do-gooder!"
Monty Python's Life of Brian
76


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-09 19:42       ` Jeffrey R.Carter
@ 2022-10-10  8:13         ` Simon Wright
  2022-10-10 16:35           ` Jeffrey R.Carter
  0 siblings, 1 reply; 11+ messages in thread
From: Simon Wright @ 2022-10-10  8:13 UTC (permalink / raw)


"Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> writes:

> This is only required if the access type has Storage_Size specified
> (ARM 13.11/18.4
> http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11.html#I5208).

I think you meant ARM 13.11(18/4),
http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11.html#p18
(note simpler way of referencing a para in a link, works for rm12 or
later).

Given this,

   declare
      type T_P is access T with Storage_Size => 1024;
      P : T_P;
   begin
      P := new T;
   end;

would you expect P to be deallocated as the block is left? because it
isn't with GCC 12.1.0, x86_64-apple-darwin.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-10  8:13         ` Simon Wright
@ 2022-10-10 16:35           ` Jeffrey R.Carter
  0 siblings, 0 replies; 11+ messages in thread
From: Jeffrey R.Carter @ 2022-10-10 16:35 UTC (permalink / raw)


On 2022-10-10 10:13, Simon Wright wrote:
> "Jeffrey R.Carter" <spam.jrcarter.not@spam.acm.org.not> writes:
> 
>> http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11.html#I5208).
> 
> I think you meant ARM 13.11(18/4),
> http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11.html#p18
> (note simpler way of referencing a para in a link, works for rm12 or
> later).

I used the link from the index.

>     declare
>        type T_P is access T with Storage_Size => 1024;
>        P : T_P;
>     begin
>        P := new T;
>     end;
> 
> would you expect P to be deallocated as the block is left? because it
> isn't with GCC 12.1.0, x86_64-apple-darwin.

Technically, it says the storage for the implementation-defined storage pool 
associated with T_P is reclaimed, not that anything is deallocated. Still, 
sounds like a compiler error.

-- 
Jeff Carter
"Help! Help! I'm being repressed!"
Monty Python & the Holy Grail
67


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Freeing access-to-task objects
  2022-10-09 16:10     ` Stephen Leake
  2022-10-09 19:42       ` Jeffrey R.Carter
@ 2022-10-10 20:23       ` AdaMagica
  1 sibling, 0 replies; 11+ messages in thread
From: AdaMagica @ 2022-10-10 20:23 UTC (permalink / raw)


Stephen Leake schrieb am Sonntag, 9. Oktober 2022 um 18:10:15 UTC+2:
> But Ada frees all objects allocated using the locally declared access 
> type when the block is exited. 

Finalizing and Deallocation are often confused. If the scope of the access is left, all still existing objects allocated are finalized in some order. As others have said, storage is reclaimed only if Storage_Size is given.

Finalization does not deallocate; but Deallocation does finalization.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-10-10 20:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-30 10:16 Freeing access-to-task objects Emmanuel Briot
2022-10-01 11:40 ` J-P. Rosen
2022-10-01 11:58   ` Dmitry A. Kazakov
2022-10-01 21:26     ` Björn Lundin
2022-10-01 14:01   ` Jeffrey R.Carter
2022-10-01 14:45     ` Emmanuel Briot
2022-10-09 16:10     ` Stephen Leake
2022-10-09 19:42       ` Jeffrey R.Carter
2022-10-10  8:13         ` Simon Wright
2022-10-10 16:35           ` Jeffrey R.Carter
2022-10-10 20:23       ` AdaMagica

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