Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ada Shutdown Hook

Tags:

ada

There are some ‘cleanup’ calls that I want called when an Ada application is shutdown/killed.

For instance if I was in java, I would do something like this to achieve the effect of having something called at shutdown:

Runtime.getRuntime().addShutdownHook(new Thread(){
       public void run(){
            method();
       }
});

Is there anything similar in Ada or another way to achieve this?

like image 892
mainstringargs Avatar asked May 19 '11 00:05

mainstringargs


People also ask

What is the shutdown hook?

Shutdown Hooks are a special construct that allows developers to plug in a piece of code to be executed when the JVM is shutting down. This comes in handy in cases where we need to do special clean up operations in case the VM is shutting down.

How do I shut down JVM?

The JVM shuts down when: user presses ctrl+c on the command prompt.


2 Answers

Since an Ada main program is treated as a task, you can use the Ada.Task_Termination package to manage post-execution cleanup. There's a writeup on this in the Ada 2005 Rationale, and what follows is a quick demo I put together that builds on the example.

You have to provide a library level protected termination procedure, so here's a package for that:

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

package Main_Program_Finalization is

   protected Shutdown_Handler is

      procedure Termination_Finalizer 
        (Cause : in Ada.Task_Termination.Cause_Of_Termination;
         T     : in Ada.Task_Identification.Task_Id;
         X     : in Ada.Exceptions.Exception_Occurrence);
   end Shutdown_Handler;

end Main_Program_Finalization;

Body:

with Text_IO; use Text_IO;

package body Main_Program_Finalization is

   protected body Shutdown_Handler is

      procedure Termination_Finalizer
        (Cause : in Ada.Task_Termination.Cause_Of_Termination;
         T     : in Ada.Task_Identification.Task_Id;
         X     : in Ada.Exceptions.Exception_Occurrence)
      is
         use Ada.Task_Termination;
         use Ada.Task_Identification;
         use Ada.Exceptions;
      begin
         New_Line;
         Put_Line("Shutdown information:");
         New_Line;
         case Cause is
         when Normal =>
            Put_Line("Normal, boring termination");
         when Abnormal =>
            Put_Line("Something nasty happened to task ");
            Put_Line(Image(T));
         when Unhandled_Exception =>
            Put_Line("Unhandled exception occurred in task ");
            Put_Line(Image(T));
            Put_Line(Exception_Information(X));
         end case;
      end Termination_Finalizer;

   end Shutdown_Handler;

end Main_Program_Finalization;

Main program (it's set up for a normal termination as posted, uncomment the last two lines and run it to see the effect of an unhandled-exception triggered termination):

with Main_Program_Finalization;
with Ada.Task_Identification;
with Ada.Task_Termination;
with Text_IO; use Text_IO;

procedure task_term is

   use Ada;

   Task_ID : Task_Identification.Task_Id
     := Task_Identification.Current_Task;

begin
   Put_Line("Main Task ID: " & Task_Identification.Image(Task_ID));

   Put_Line("Setting termination finalizer");
   Task_Termination.Set_Specific_Handler
     (Task_ID, 
      Main_Program_Finalization.Shutdown_Handler.Termination_Finalizer'Access);
   Put_Line("Go off and do things now...");
   delay 1.0;
   Put_Line("Done with mainline processing, the shutdown handler should now execute");

--     Put_Line("Raise an unhandled exception and see what the shutdown handler does");
--     raise Constraint_Error;
end Task_Term;
like image 103
Marc C Avatar answered Jan 04 '23 12:01

Marc C


You could create a Controlled (or Limited_Controlled) object to the main procedure, which calls the necessary stuff in its Finalization method.

Be aware that you can't access any local variables of the main procedure, so put anything necessary into the controlled object.

example:

with Ada.Text_IO;
with Ada.Finalization;
procedure Main is
   type Cleaner is new Ada.Finalization.Limited_Controlled with record
      Some_Interesting_Data : Integer;
   end record;
   overriding procedure Finalize (X : in out Cleaner) is
   begin
      Ada.Text_IO.Put_Line ("Cleaning..." & Integer'Image (X.Some_Interesting_Data));
   end Finalize;
   The_Cleaner : Cleaner;
begin
   Ada.Text_IO.Put_Line ("Main Procedure.");
   The_Cleaner.Some_Interesting_Data := 42;
   Ada.Text_IO.Put_Line ("Finished.");
end Main;
like image 35
Rommudoh Avatar answered Jan 04 '23 11:01

Rommudoh