How can I start a process and convert its PID to/from an integer?

Viewed 100

I'm writing a process manager in Ada, for Linux. I'm using GNAT.OS_Lib to spawn processes:

Pid := GNAT.OS_Lib.Non_Blocking_Spawn(
    Program_Name => Program,
    Args => Arguments
);

This gets me back the PID as a Process_Id, an OS_Lib private type. I would like to be able to store this PID in a file as an integer, for compatibility with other, non-Ada code, and then re-load it later from that file and use it from within Ada to kill the process, check its status, etc.

OS_Lib provides a Pid_To_Integer function, but not the inverse.

Perhaps I need a different library? As far as I can tell, there are no current Ada POSIX libraries. Should I write one myself? I only need support for like three POSIX calls. I'm open to all suggestions.

2 Answers

Chasing through the RTS for the definition, g-os_lib.ads says

with System.OS_Lib;

package GNAT.OS_Lib renames System.OS_Lib;

and at the bottom of s-os_lib.ads we find

type Process_Id is new Integer;

so I’d go for Ada.Unchecked_Conversion.

In the end, I wrote my own implementation. Here is an example of how to run execv and fork in Ada.

main.adb

with Ada.Text_IO;
with Interfaces.C.Strings;

procedure Main is
    subtype C_String is Interfaces.C.Strings.chars_ptr;
    Null_String: C_String := Interfaces.C.Strings.Null_Ptr;

    function As_C_String(s: String) return C_String renames Interfaces.C.Strings.New_String;

    type Argument_List is Array(1..2) of C_String;

    function Execute(Program: C_String; Arguments: Argument_List) return Integer
        with Import => True, Convention => C, External_Name => "execv";
    function Fork return Integer
        with Import => True, Convention => C, External_Name => "fork";

    Program: C_String := As_C_String("/bin/sh");
    Args: Argument_List := (Program, Null_String);

    N : Integer;
    Pid: Integer;
begin
    Pid := Fork;
    if Pid = 0
    then
        N := Execute(Program, Args);
    else
        Ada.Text_IO.Put_Line(Pid'Image);
    end if;
end Main;

main.gpr

project Main is

   for Languages use ("ada");

   for Source_Dirs use (".");
   for Main use ("main.adb");
   for Object_Dir use "obj";
   for Exec_Dir use ".";

end Main;

Compiling with gprbuild and it works fine. Run main and you should see an integer in the console, run ps ux and you should see an instance of sh running with that PID.

Related