/src/yolk-process_control.adb

http://github.com/ThomasLocke/yolk · Ada · 192 lines · 96 code · 36 blank · 60 comment · 6 complexity · ce521a621df777d876aca68da8856196 MD5 · raw file

  1. -------------------------------------------------------------------------------
  2. -- --
  3. -- Copyright (C) 2010-, Thomas ¸cke --
  4. -- --
  5. -- This library is free software; you can redistribute it and/or modify --
  6. -- it under terms of the GNU General Public License as published by the --
  7. -- Free Software Foundation; either version 3, or (at your option) any --
  8. -- later version. This library is distributed in the hope that it will be --
  9. -- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
  10. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
  11. -- --
  12. -- As a special exception under Section 7 of GPL version 3, you are --
  13. -- granted additional permissions described in the GCC Runtime Library --
  14. -- Exception, version 3.1, as published by the Free Software Foundation. --
  15. -- --
  16. -- You should have received a copy of the GNU General Public License and --
  17. -- a copy of the GCC Runtime Library Exception along with this program; --
  18. -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
  19. -- <http://www.gnu.org/licenses/>. --
  20. -- --
  21. -------------------------------------------------------------------------------
  22. with Ada.Directories;
  23. with Ada.Interrupts.Names;
  24. with Ada.Strings.Fixed;
  25. with Ada.Text_IO;
  26. with POSIX.Process_Identification;
  27. package body Yolk.Process_Control is
  28. use Ada.Directories;
  29. type Controller_State is (Running, Shutdown, Stopped);
  30. PID : constant String := PID_File;
  31. -- Path to the PID file. If this is empty, then no PID file is written.
  32. Wait_Called : Boolean := False;
  33. -- Is set to True when Wait has been called. This is used to test if we've
  34. -- already called Wait earlier, and if so, ignore the call.
  35. procedure Create_PID_File;
  36. procedure Delete_PID_File;
  37. -- Create and delete the PID file.
  38. ------------------
  39. -- Controller --
  40. ------------------
  41. protected Controller is
  42. entry Check;
  43. -- If Controller_State is Shutdown the Wait procedure completes. If PID
  44. -- is non-empty then Delete_PID_File is called.
  45. procedure Handle_Kill;
  46. -- Set Controller.State to Shutdown.
  47. pragma Attach_Handler (Handle_Kill, Ada.Interrupts.Names.SIGINT);
  48. pragma Attach_Handler (Handle_Kill, Ada.Interrupts.Names.SIGTERM);
  49. pragma Attach_Handler (Handle_Kill, Ada.Interrupts.Names.SIGPWR);
  50. -- Handles the SIGINT, SIGTERM and SIGPWR signals. These signalhandlers
  51. -- change the Controller.State to Shutdown.
  52. entry Start;
  53. -- Called by Wait. Set Controller.State to Running and calls
  54. -- Create_PID_File if PID is non-empty.
  55. private
  56. State : Controller_State := Stopped;
  57. end Controller;
  58. ----------------------
  59. -- Create_PID_File --
  60. ----------------------
  61. procedure Create_PID_File
  62. is
  63. use Ada.Strings;
  64. use Ada.Text_IO;
  65. use POSIX.Process_Identification;
  66. File : File_Type;
  67. begin
  68. if Exists (PID) then
  69. raise PID_File_Exists with PID;
  70. end if;
  71. Create (File => File,
  72. Name => PID);
  73. Put (File => File,
  74. Item => Fixed.Trim (Image (Get_Process_ID), Both));
  75. Close (File);
  76. exception
  77. when Ada.Text_IO.Name_Error |
  78. Ada.Text_IO.Use_Error |
  79. Ada.Text_IO.Device_Error =>
  80. raise Cannot_Create_PID_File with PID;
  81. end Create_PID_File;
  82. -----------------------
  83. -- Delete_PID_File --
  84. -----------------------
  85. procedure Delete_PID_File
  86. is
  87. use Ada.Text_IO;
  88. begin
  89. if Exists (PID) then
  90. Delete_File (PID);
  91. end if;
  92. exception
  93. when Ada.Text_IO.Name_Error |
  94. Ada.Text_IO.Use_Error |
  95. Ada.Text_IO.Device_Error =>
  96. raise Cannot_Delete_PID_File with PID;
  97. end Delete_PID_File;
  98. ------------
  99. -- Stop --
  100. ------------
  101. procedure Stop
  102. is
  103. begin
  104. Controller.Handle_Kill;
  105. end Stop;
  106. ------------
  107. -- Wait --
  108. ------------
  109. procedure Wait
  110. is
  111. begin
  112. if not Wait_Called then
  113. Wait_Called := True;
  114. Controller.Start;
  115. Controller.Check;
  116. -- We'll hang here until Controller.State is Shutdown.
  117. Wait_Called := False;
  118. end if;
  119. end Wait;
  120. ------------------
  121. -- Controller --
  122. ------------------
  123. protected body Controller is
  124. -------------
  125. -- Check --
  126. -------------
  127. entry Check when State = Shutdown
  128. is
  129. begin
  130. if PID /= "" then
  131. Delete_PID_File;
  132. end if;
  133. State := Stopped;
  134. end Check;
  135. -------------
  136. -- Start --
  137. -------------
  138. entry Start when State = Stopped
  139. is
  140. begin
  141. State := Running;
  142. if PID /= "" then
  143. Create_PID_File;
  144. end if;
  145. end Start;
  146. -------------------
  147. -- Handle_Kill --
  148. -------------------
  149. procedure Handle_Kill is
  150. begin
  151. if State /= Shutdown then
  152. State := Shutdown;
  153. end if;
  154. end Handle_Kill;
  155. end Controller;
  156. end Yolk.Process_Control;