Signals in Ada

Here’s the translation of the Go code to Ada, formatted in Markdown suitable for Hugo:

Our program demonstrates how to handle Unix signals in Ada. For example, we might want a server to gracefully shutdown when it receives a SIGTERM, or a command-line tool to stop processing input if it receives a SIGINT. Here’s how to handle signals in Ada using tasks and protected objects.

with Ada.Text_IO;
with Ada.Interrupts.Names;
with Ada.Synchronous_Task_Control;

procedure Signals is
   use Ada.Text_IO;
   use Ada.Synchronous_Task_Control;

   Done : Suspension_Object;

   protected Signal_Handler is
      procedure Handle;
      pragma Interrupt_Handler (Handle);
      pragma Attach_Handler (Handle, Ada.Interrupts.Names.SIGINT);
      pragma Attach_Handler (Handle, Ada.Interrupts.Names.SIGTERM);
   end Signal_Handler;

   protected body Signal_Handler is
      procedure Handle is
      begin
         Put_Line ("Received signal");
         Set_True (Done);
      end Handle;
   end Signal_Handler;

   task Signal_Waiter;

   task body Signal_Waiter is
   begin
      Put_Line ("Awaiting signal");
      Suspend_Until_True (Done);
      Put_Line ("Exiting");
   end Signal_Waiter;

begin
   null;
end Signals;

Ada signal handling works by attaching interrupt handlers to protected procedures. We’ll create a protected object to handle the signals.

The Signal_Handler protected object is defined with a Handle procedure that is marked as an interrupt handler and attached to both SIGINT and SIGTERM.

We create a Suspension_Object named Done to coordinate between the signal handler and the main program flow.

The Signal_Waiter task demonstrates a more realistic scenario of graceful shutdown. It waits for the Done suspension object to be set to true, which happens when a signal is received.

In the Handle procedure, we print a message indicating that a signal was received and set the Done suspension object to true.

The Signal_Waiter task prints “Awaiting signal”, then suspends until Done is set to true. When it resumes, it prints “Exiting”.

When we run this program, it will block waiting for a signal. By typing ctrl-C (which the terminal shows as ^C) we can send a SIGINT signal, causing the program to print “Received signal” and then “Exiting”.

$ gnatmake signals.adb
$ ./signals
Awaiting signal
^C
Received signal
Exiting

This example demonstrates how Ada can handle Unix signals using its built-in tasking and synchronization mechanisms, providing a robust way to manage program termination and other signal-driven events.