Ada Shutdown Hook - PullRequest
       13

Ada Shutdown Hook

12 голосов
/ 19 мая 2011

Есть несколько вызовов 'cleanup', которые я хочу вызывать, когда приложение Ada закрывается / уничтожается.

Например, если бы я был в Java, я бы сделал что-то подобное, чтобы добиться эффекта от чего-товызывается при выключении:

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

Есть ли что-то похожее в Аде или другой способ добиться этого?

Ответы [ 6 ]

11 голосов
/ 19 мая 2011

Поскольку основная программа Ada рассматривается как задача, вы можете использовать пакет Ada.Task_Termination для управления очисткой после выполнения.Об этом написано в Обосновании Ada 2005 , и ниже я приведу краткое демонстрационное руководство, которое основано на примере.

Вы должны предоставить процедуру завершения на уровне библиотеки,так вот пакет для этого:

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;

Основная программа (она настроена на нормальное завершение, как было опубликовано, раскомментируйте последние две строки и запустите, чтобы увидетьэффект прекращения, вызванного необработанным исключением):

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;
8 голосов
/ 19 мая 2011

Вы можете создать объект Controlled (или Limited_Controlled) для главной процедуры, который вызывает необходимые вещи в своем методе Finalization.

Помните, что вы не можете получить доступ ни к каким локальным переменным основной процедурыпоэтому поместите все необходимое в контролируемый объект.

пример:

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;
3 голосов
/ 19 мая 2011

Если это контролируемое отключение, инициированное пользователем, или потому, что программа просто выполняет то, что делает, то вы можете просто добавить последний вызов к процедуре очистки.

Если программа завершается из-засигнал прерывания, такой как пользователь, отправляющий сигнал SIGINT, или выключение системы, затем вы можете перехватить эти сигналы и поместить вашу процедуру очистки в зарегистрированный обратный вызов.

Я написал короткий пример о том, как перехватитьпрерывает с помощью Ады.Он доступен на github и в вики-статье .

Другой вариант - использование пакета Florist POSIX из libre.adacore.com .Возможно, в пакете posix-сигналов есть что-то полезное.

2 голосов
/ 19 мая 2011

Похоже, должен быть способ сделать это в чистой Аде, но я не смог его найти.

Одной из идей было бы использование Interfaces.C и вызов atexit () с функцией обратного вызова, которая выполняет очистку. Я не пробовал, но не могу придумать причину, по которой это не сработает.

Дополнительная информация об обратных вызовах Ada от C

2 голосов
/ 19 мая 2011

Вы можете вызвать исключение , которое может быть одним , определенным языком или одним , определенным в вашей программе .Ваш обработчик исключений затем будет выполнен.

Вы также можете использовать Ada.Command_Line.Set_Exit_Status для возврата кода в вызывающую среду.

Добавление: Вытакже может обрабатывать внешние прерывания , как показано здесь .

1 голос
/ 19 мая 2011

Если программе разрешено корректно завершать работу, то вы можете использовать стандартные языковые средства, такие как управляемые типы, для обеспечения поведения при выключении.

Если программе не разрешено корректно завершать работу из-за ОС, то не существует определенного для языка способа сделать это на любом языке . Вам придется использовать какой-то вызов ОС для этого.

Обратите внимание, что пример, который вы показали, был не вызовом Java, а вызовом JVM . JVM = виртуальная машина Java ... по сути, ОС Java. Вы можете сделать точно такой же вызов от Ada, если ваш код Ada работает на JVM. Если вы работаете под Windows, вам придется делать это с помощью системных вызовов Win32. Вы можете сделать это из Ады, но, очевидно, точные вызовы не определены в языке.

...