Ada 关闭挂钩

发布于 2024-11-08 00:31:03 字数 257 浏览 2 评论 0原文

当 Ada 应用程序关闭/终止时,我希望调用一些“清理”调用。

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

隔岸观火 2024-11-15 00:31:03

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

您必须提供一个库级受保护的终止过程,因此这里有一个包:

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;

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;
彡翼 2024-11-15 00:31:03

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

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;
败给现实 2024-11-15 00:31:03

您可以提出异常,这可以是由语言定义的或一个 在您的程序中定义。然后您的异常处理程序将执行。

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

附录:您还可以处理外部中断,如此处所示。

You can raise an exception, which can be one defined by the language or one defined in your program. Your exception handler would then execute.

You can also use Ada.Command_Line.Set_Exit_Status to return a code to the invoking environment.

Addendum: You can also handle external interrupts, as shown here.

煮茶煮酒煮时光 2024-11-15 00:31:03

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

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

我写了一个关于如何使用 Ada 捕获中断的简短示例。它可在 github 上获取,并作为 wiki 文章

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

If it's a controlled shutdown initiated by the user or because the program is simply done doing what it does, then you can simply add a final call to a cleanup procedure.

If the program is terminated due to an interrupt signal, such as a user sending a SIGINT signal, or the system shutting down, then you can catch those signals and put your cleanup procedure in the registered callback.

I wrote a short example on how to catch interrupts using Ada. It's available at github and as a wiki article.

Another option is using the Florist POSIX package from libre.adacore.com. Perhaps there's something of use in the posix-signals package.

仅此而已 2024-11-15 00:31:03

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

一种想法是使用 Interfaces.C 并调用 atexit()执行清理操作的回调函数。我没有尝试过,但我想不出它不起作用的任何原因。

有关来自 C 的 Ada 回调的更多信息

Seems like there should be a way to do this in pure Ada, but I couldn't find one.

One idea would be to use Interfaces.C and call atexit() with a callback function that does the cleanup. I haven't tried it, but I can't think of any reason it wouldn't work.

More info on Ada callbacks from C

荆棘i 2024-11-15 00:31:03

如果允许程序正常关闭,那么您可以使用标准语言工具(例如受控类型)来提供“关闭时”行为。

如果操作系统不允许程序正常关闭,则在任何语言中都没有语言定义的方法来执行此操作。您将必须使用某种操作系统调用来完成此操作。

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

If the program is allowed to shut down nicely, then you can use standard language facilities like controlled types to provide your "on shutdown" behavior.

If the program isn't allowed to shut down nicely by the OS, then there is no language-defined way to do it in any language. You will have to use some kind of OS call to do it.

Note that the example you showed was not a Java call, but a JVM call. JVM = Java Virtual Machine...essentially the Java OS. You could make the exact same call from Ada, assuming your Ada code is running on the JVM. If you are running under Windows instead you'd have to do it with Win32 system calls. You can make those from Ada, but obviously the exact calls aren't portably defined in the language.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文