阿达关机钩

时间:2011-05-19 00:11:19

标签: ada

当Ada应用程序关闭/终止时,我想调用一些'清理'调用。

例如,如果我在java中,我会做这样的事情来实现在关机时调用某些东西的效果:

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

Ada还有其他方法可以达到此目的吗?

6 个答案:

答案 0 :(得分:11)

由于Ada主程序被视为任务,因此您可以使用Ada.Task_Termination包来管理执行后清理。在Ada 2005 Rationale中有一个关于此的文章,接下来是我在一个示例的基础上编写的快速演示。

你必须提供一个库级保护终止程序,所以这是一个包:

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;

体:

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;

答案 1 :(得分:8)

您可以为主过程创建一个受控(或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;

答案 2 :(得分:3)

如果它是由用户启动的受控关闭,或者因为程序只是完成它所做的事情,那么你可以简单地添加一个最终调用清理程序。

如果由于中断信号(例如用户发送SIGINT信号)或系统关闭而终止程序,则可以捕获这些信号并将清理程序放入已注册的回调中。

我写了一个关于如何使用Ada捕获中断的简短示例。它位于githubwiki article

另一种选择是使用libre.adacore.com中的Florist POSIX包。也许在posix-signals包中有一些用处。

答案 3 :(得分:2)

您可raise an exception,可以是一个defined by the language或一个defined in your program。然后,您的exception handler将会执行。

您还可以使用Ada.Command_Line.Set_Exit_Status将代码返回到调用环境。

附录:您还可以处理外部interrupts,如图here所示。

答案 4 :(得分:2)

似乎应该有一种方法在纯Ada中做到这一点,但我找不到。

一个想法是使用Interfaces.C并使用执行清理的回调函数调用atexit()。我没有尝试过,但我想不出有什么理由不行。

More info on Ada callbacks from C

答案 5 :(得分:1)

如果允许程序很好地关闭,那么您可以使用受控类型等标准语言工具来提供“关闭时”行为。

如果操作系统不允许该程序很好地关闭,那么没有语言定义的方式来用任何语言。您将不得不使用某种OS调用来执行此操作。

请注意,您展示的示例不是Java调用,而是JVM调用。 JVM = Java虚拟机......本质上是Java OS。假设您的Ada代码在JVM上运行,您可以从Ada进行完全相同的调用。如果您在Windows下运行,则必须使用Win32系统调用。你可以从Ada制作那些,但很明显,确切的调用在语言中没有可移植的定义。