An Ada 2012 library for posix_spawn()
to spawn processes without a fork()
.
See the paper A fork() in the road why fork()
should not be used.
The package Spoon
provides the function Spawn
which can either
return a Result
or a Process
.
Calling the function which returns a Result
will spawn a process,
wait for it to exit, and return the exit result.
The exit result contains the exit status, signal that caused the
process to crash or terminate, or the error code if the process
could not be spawned.
The function which returns a Process
does not wait and returns immediately.
An object of the type Process
provides the function Wait_For_Exit
, which
waits for the process to exit and then return a Result
.
Additionally, a Process
or its process group can be terminated with the
procedures Terminate_Process
and Terminate_Group
.
To capture the standard output and error, provide a pointer to an object
implementing the protected interface Output_Capturer
.
The package Spoon.Output
provides the protected type Text_Capturer
, which
can return an unbounded string.
The parameter Attributes
of the function Spawn
can be used to reset
the effective user and group if the parent process is a setuid binary,
or to let the spawned process have its own process group
(so that Terminate_Group
can be called).
with Ada.Text_IO;
with Spoon.Output;
procedure Example is
use all type Spoon.Exit_State;
use type Spoon.Exit_Status;
Arg_1 : aliased Spoon.Argument := Spoon.To_Argument ("2");
Result : constant Spoon.Result :=
Spoon.Spawn ("/bin/sleep", (1 => Arg_1'Unchecked_Access));
begin
Ada.Text_IO.Put (Result.State'Image & " ");
case Result.State is
when Exited =>
if Result.Exit_Status = Spoon.Success then
Ada.Text_IO.Put_Line ("OK");
else
Ada.Text_IO.Put_Line ("with status" & Result.Exit_Status'Image);
end if;
when Crashed | Terminated =>
Ada.Text_IO.Put_Line ("with signal" & Result.Signal'Image);
when Error =>
Ada.Text_IO.Put_Line ("with error" & Result.Error_Code'Image);
end case;
declare
Text : aliased Spoon.Output.Text_Capturer;
Process : constant Spoon.Process :=
Spoon.Spawn ("whoami", Output => Text'Access, Kind => Spoon.Name);
use Spoon.Output;
begin
if Process.Wait_For_Exit.State = Exited then
Ada.Text_IO.Put_Line ("OK: '" & (+Text.Get (Spoon.Standard_Output)) & "'");
else
Ada.Text_IO.Put_Line ("not OK");
end if;
end;
end Example;
In order to build the library, you need to have:
-
An Ada 2012 compiler
-
Alire package manager
The Ada code is licensed under the Apache License 2.0. The first line of each Ada file should contain an SPDX license identifier tag that refers to this license:
SPDX-License-Identifier: Apache-2.0