]> Kevux Git Server - fll/commitdiff
Update: implement with pid execution, simplify related rules.
authorKevin Day <thekevinday@gmail.com>
Sat, 17 Apr 2021 23:44:52 +0000 (18:44 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 18 Apr 2021 00:14:29 +0000 (19:14 -0500)
Implement the with pid execution.
This expects the process to be spawned in the background.

After some review, I decided to remove "use" and "create", replacing those with "pid_file".
The reasons are:
- For "use", the spawned service manages the pid file, so it would be overly complicated to try and manage it in addition to the spawned service.
- For "create", if the process is to go into the background, in order to manage it then there would still need to be a running process (this defeats the purpose).

When the termination signal is received, then inform any background process spawned by the controller program to exit, based on the existence of the pid file.

16 files changed:
level_3/controller/c/private-common.c
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-controller.h
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/c/private-thread.c
level_3/controller/data/settings/example/rules/service/sshd.rule
level_3/controller/data/settings/example/rules/utility/sleeper_1.rule
level_3/controller/data/settings/example/rules/utility/sleeper_2.rule
level_3/controller/data/settings/rules/program/terminal.rule
level_3/controller/data/settings/rules/service/dbus.rule
level_3/controller/data/settings/rules/service/logger.rule
level_3/controller/data/settings/rules/service/mouse.rule
level_3/controller/documents/rule.txt
level_3/controller/specifications/rule.txt

index a23e5bb8a29ce9787c8a1ad936bf315aba844587..cd5d5b7ccbce067aa3ca57270db704430af0e33c 100644 (file)
@@ -306,6 +306,8 @@ extern "C" {
     controller_cache_delete_simple(&process->cache);
     controller_rule_delete_simple(&process->rule);
 
+    f_string_dynamic_resize(0, &process->path_pid);
+
     f_macro_array_lengths_t_delete_simple(process->stack)
   }
 #endif // _di_controller_process_delete_simple_
index 7cb9b312ed040461ae14191bfee53845a9c427e6..beecce0f16dc3806461aa4b2c3ca63c26f44a525 100644 (file)
@@ -71,7 +71,7 @@ extern "C" {
   #define controller_string_parameter     "parameter"
   #define controller_string_path          "path"
   #define controller_string_pause         "pause"
-  #define controller_string_pid           "pid"
+  #define controller_string_pid_file      "pid_file"
   #define controller_string_processor     "processor"
   #define controller_string_program       "program"
   #define controller_string_ready         "ready"
@@ -160,7 +160,7 @@ extern "C" {
   #define controller_string_parameter_length     9
   #define controller_string_path_length          4
   #define controller_string_pause_length         5
-  #define controller_string_pid_length           3
+  #define controller_string_pid_file_length      8
   #define controller_string_processor_length     9
   #define controller_string_program_length       7
   #define controller_string_ready_length         5
@@ -250,7 +250,7 @@ extern "C" {
   const static f_string_t controller_string_parameter_s = controller_string_parameter;
   const static f_string_t controller_string_path_s = controller_string_path;
   const static f_string_t controller_string_pause_s = controller_string_pause;
-  const static f_string_t controller_string_pid_s = controller_string_pid;
+  const static f_string_t controller_string_pid_file_s = controller_string_pid_file;
   const static f_string_t controller_string_processor_s = controller_string_processor;
   const static f_string_t controller_string_program_s = controller_string_program;
   const static f_string_t controller_string_ready_s = controller_string_ready;
@@ -487,18 +487,17 @@ extern "C" {
   };
 
   enum {
-    controller_rule_action_type_create = 1,
-    controller_rule_action_type_freeze,
+    controller_rule_action_type_freeze = 1,
     controller_rule_action_type_group,
     controller_rule_action_type_kill,
     controller_rule_action_type_pause,
+    controller_rule_action_type_pid_file,
     controller_rule_action_type_reload,
     controller_rule_action_type_restart,
     controller_rule_action_type_resume,
     controller_rule_action_type_start,
     controller_rule_action_type_stop,
     controller_rule_action_type_thaw,
-    controller_rule_action_type_use,
     controller_rule_action_type_user,
     controller_rule_action_type_with,
   };
@@ -743,6 +742,13 @@ extern "C" {
 #endif // _di_controller_rules_t_
 
 /**
+ * A set of codes representing different with flags.
+ */
+#ifndef _di_controller_with_defines_
+  #define controller_with_full_path 0x1
+#endif // _di_controller_with_defines_
+
+/**
  * A Rule Process.
  *
  * This refers to "process" as in the processing of a single rule for the given Rule ID and does not refer to "process" as in a CPU Process.
@@ -805,6 +811,8 @@ extern "C" {
     controller_cache_t cache;
     f_array_lengths_t stack;
 
+    f_string_dynamic_t path_pid;
+
     controller_rule_t rule;
 
     void *main_data;
@@ -824,6 +832,7 @@ extern "C" {
     f_thread_condition_t_initialize, \
     controller_cache_t_initialize, \
     f_array_lengths_t_initialize, \
+    f_string_dynamic_t_initialize, \
     controller_rule_t_initialize, \
     0, \
     0, \
index 8776cf6836f9a6e5fc5502e1d145872b7a36b502..63469fbf651681a26d26336c7f276ae196cb9273 100644 (file)
@@ -246,6 +246,56 @@ extern "C" {
   }
 #endif // _di_controller_file_pid_delete_
 
+#ifndef _di_controller_file_pid_read_
+  f_status_t controller_file_pid_read(const f_string_static_t path, pid_t *pid) {
+
+    *pid = 0;
+
+    f_status_t status = f_file_exists(path.string);
+    if (F_status_is_error(status)) return status;
+
+    if (status != F_true) {
+      return F_data_not;
+    }
+
+    f_file_t pid_file = f_file_t_initialize;
+
+    status = f_file_stream_open(path.string, f_file_open_mode_read_s, &pid_file);
+    if (F_status_is_error(status)) return status;
+
+    f_string_dynamic_t pid_buffer = f_string_dynamic_t_initialize;
+
+    status = f_file_stream_read(pid_file, 1, &pid_buffer);
+
+    if (F_status_is_error_not(status)) {
+      status = f_file_stream_close(F_true, &pid_file);
+    }
+
+    if (F_status_is_error_not(status)) {
+      f_number_unsigned_t number = 0;
+      f_string_range_t range = f_macro_string_range_t_initialize(pid_buffer.used);
+
+      for (; range.start < pid_buffer.used; ++range.start) {
+        if (!isspace(pid_buffer.string[range.start])) break;
+      } // for
+
+      for (; range.stop > 0; --range.stop) {
+        if (!isspace(pid_buffer.string[range.stop])) break;
+      } // for
+
+      status = fl_conversion_string_to_decimal_unsigned(pid_buffer.string, range, &number);
+
+      if (F_status_is_error_not(status)) {
+        *pid = (pid_t) number;
+      }
+    }
+
+    f_macro_string_dynamic_t_delete_simple(pid_buffer);
+
+    return status;
+  }
+#endif // _di_controller_file_pid_read_
+
 #ifndef _di_controller_find_process_
   f_status_t controller_find_process(const f_string_static_t alias, const controller_processs_t processs, f_array_length_t *at) {
 
index 5d1edfc6e032353b9d39fdd49e4ab482a78006fa..09d5b7efc99c4ce746f8b0bac82a31be535a078e 100644 (file)
@@ -160,12 +160,33 @@ extern "C" {
  *   Errors (with error bit) from: f_file_stream_close().
  *   Errors (with error bit) from: f_file_stream_open().
  *   Errors (with error bit) from: f_file_stream_read().
+ *   Errors (with error bit) from: fl_conversion_string_to_decimal_unsigned()
  */
 #ifndef _di_controller_file_pid_delete_
   f_status_t controller_file_pid_delete(const pid_t pid, const f_string_static_t path) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_file_pid_delete_
 
 /**
+ * Read the PID from a PID file.
+ *
+ * @param path
+ *   The file path to the pid file to create.
+ * @param pid
+ *   The PID to be read.
+ *
+ * @return
+ *   F_none on success.
+ *
+ *   Errors (with error bit) from: f_file_stream_close().
+ *   Errors (with error bit) from: f_file_stream_open().
+ *   Errors (with error bit) from: f_file_stream_read().
+ *   Errors (with error bit) from: fl_conversion_string_to_decimal_unsigned()
+ */
+#ifndef _di_controller_file_pid_read_
+  f_status_t controller_file_pid_read(const f_string_static_t path, pid_t *pid) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_file_pid_read_
+
+/**
  * Find an existing process.
  *
  * Do not confuse this with a process in the context of a PID.
index 9a203c352e2ece8d3bebd53e72b39a2440cede2d..95f5ea797c4e1033d59ce1d66329d34e3fd0ed59 100644 (file)
@@ -134,11 +134,6 @@ extern "C" {
     f_string_static_t buffer = f_string_static_t_initialize;
 
     switch (type) {
-      case controller_rule_action_type_create:
-        buffer.string = controller_string_create_s;
-        buffer.used = controller_string_create_length;
-        break;
-
       case controller_rule_action_type_group:
         buffer.string = controller_string_group_s;
         buffer.used = controller_string_group_length;
@@ -149,6 +144,11 @@ extern "C" {
         buffer.used = controller_string_kill_length;
         break;
 
+      case controller_rule_action_type_pid_file:
+        buffer.string = controller_string_pid_file_s;
+        buffer.used = controller_string_pid_file_length;
+        break;
+
       case controller_rule_action_type_restart:
         buffer.string = controller_string_restart_s;
         buffer.used = controller_string_restart_length;
@@ -169,11 +169,6 @@ extern "C" {
         buffer.used = controller_string_stop_length;
         break;
 
-      case controller_rule_action_type_use:
-        buffer.string = controller_string_use_s;
-        buffer.used = controller_string_use_length;
-        break;
-
       case controller_rule_action_type_user:
         buffer.string = controller_string_user_s;
         buffer.used = controller_string_user_length;
@@ -771,9 +766,8 @@ extern "C" {
     f_array_length_t k = 0;
 
     f_string_dynamic_t *pid_file = 0;
-    uint8_t pid_type = 0;
 
-    bool with_full_path = F_false;
+    uint8_t with = 0;
 
     // child processes should receive all signals and handle the signals as they see fit.
     f_signal_how_t signals = f_signal_how_t_initialize;
@@ -845,7 +839,7 @@ extern "C" {
 
       if (process->rule.items.array[i].type == controller_rule_item_type_setting) continue;
 
-      with_full_path = F_false;
+      with = 0;
 
       for (j = 0; j < process->rule.items.array[i].actions.used; ++j) {
 
@@ -853,13 +847,9 @@ extern "C" {
           for (k = 0; k < process->rule.items.array[i].actions.array[j].parameters.used; ++k) {
 
             if (fl_string_dynamic_compare_string(controller_string_full_path_s, process->rule.items.array[i].actions.array[j].parameters.array[k], controller_string_full_path_length) == F_equal_to) {
-              with_full_path = F_true;
-
-              break;
+              with |= controller_with_full_path;
             }
           } // for
-
-          if (with_full_path) break;
         }
       } // for
 
@@ -875,7 +865,7 @@ extern "C" {
         execute_set.parameter.data = 0;
         execute_set.parameter.option = fl_execute_parameter_option_threadsafe | fl_execute_parameter_option_return;
 
-        if (with_full_path) {
+        if (with & controller_with_full_path) {
           execute_set.parameter.option |= fl_execute_parameter_option_path;
         }
 
@@ -915,11 +905,10 @@ extern "C" {
         }
         else if (process->rule.items.array[i].type == controller_rule_item_type_service) {
           pid_file = 0;
-          pid_type = 0;
 
           for (k = 0; k < process->rule.items.array[i].actions.used; ++k) {
 
-            if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_create && process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_use) {
+            if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_pid_file) {
               continue;
             }
 
@@ -928,11 +917,10 @@ extern "C" {
             }
 
             pid_file = &process->rule.items.array[i].actions.array[k].parameters.array[0];
-            pid_type = process->rule.items.array[i].actions.array[k].type;
           } // for
 
           if (pid_file) {
-            status = controller_rule_execute_pid_with(pid_file, pid_type, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, main, &execute_set, process);
+            status = controller_rule_execute_pid_with(*pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, with, main, &execute_set, process);
 
             if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
 
@@ -956,11 +944,10 @@ extern "C" {
         }
         else if (process->rule.items.array[i].type == controller_rule_item_type_utility) {
           pid_file = 0;
-          pid_type = 0;
 
           for (k = 0; k < process->rule.items.array[i].actions.used; ++k) {
 
-            if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_create && process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_use) {
+            if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_pid_file) {
               continue;
             }
 
@@ -969,13 +956,12 @@ extern "C" {
             }
 
             pid_file = &process->rule.items.array[i].actions.array[k].parameters.array[0];
-            pid_type = process->rule.items.array[i].actions.array[k].type;
           } // for
 
           if (pid_file) {
             execute_set.parameter.data = &process->rule.items.array[i].actions.array[j].parameters.array[0];
 
-            status = controller_rule_execute_pid_with(pid_file, pid_type, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, main, &execute_set, process);
+            status = controller_rule_execute_pid_with(*pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, with, main, &execute_set, process);
 
             if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
 
@@ -1172,6 +1158,9 @@ extern "C" {
       if (!WIFEXITED(result)) {
         status = F_status_set_error(F_failure);
       }
+      else {
+        status = F_none;
+      }
     }
     else {
       if (!main.thread->enabled) {
@@ -1223,7 +1212,7 @@ extern "C" {
 #endif // _di_controller_rule_execute_foreground_
 
 #ifndef _di_controller_rule_execute_pid_with_
-  f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t *pid_file, const uint8_t pid_type, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, const controller_main_t main, controller_execute_set_t * const execute_set, controller_process_t *process) {
+  f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t pid_file, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, const uint8_t with, const controller_main_t main, controller_execute_set_t * const execute_set, controller_process_t *process) {
 
     f_status_t status = F_none;
     f_status_t status_lock = F_none;
@@ -1231,7 +1220,29 @@ extern "C" {
     int result = 0;
     pid_t id_child = 0;
 
-    // @todo check to see if pid file exists.
+    process->path_pid.used = 0;
+
+    status = f_file_exists(pid_file.string);
+
+    if (F_status_is_error(status)) {
+      fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_exists", F_true, pid_file.string, "find", fll_error_file_type_file);
+
+      return status;
+    }
+
+    if (status == F_true) {
+      fll_error_file_print(main.data->error, F_file_found, "f_file_exists", F_true, pid_file.string, "create PID", fll_error_file_type_file);
+
+      return F_status_set_error(F_file_found);
+    }
+
+    status = controller_string_dynamic_append_terminated(pid_file, &process->path_pid);
+
+    if (F_status_is_error(status)) {
+      fll_error_print(main.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
+
+      return status;
+    }
 
     if (options & controller_process_option_simulate) {
 
@@ -1297,7 +1308,7 @@ extern "C" {
         controller_lock_error_critical_print(main.data->error, F_status_set_fine(status_lock), F_true, main.thread);
       }
 
-      // have the parent wait for the child process to finish. @todo do not wait, this is a background execution! instead, wait for pid file or timeout (or perhaps optional create the pid file).
+      // the child process should perform the change into background, therefore it is safe to wait for the child to exit (another process is spawned).
       waitpid(id_child, &result, 0);
 
       if (!main.thread->enabled) {
@@ -1327,7 +1338,7 @@ extern "C" {
         return F_status_set_error(F_lock);
       }
 
-      // remove the pid now that waidpid() has returned. @todo do not clear until forked execution is known to have exited, this is a background execution
+      // remove the pid now that waidpid() has returned.
       process->child = 0;
 
       f_thread_unlock(&process->lock);
@@ -1340,11 +1351,13 @@ extern "C" {
       }
 
       // this must explicitly check for 0 (as opposed to checking (!result)).
+      // @todo expand this to provide user more control over what is or is not an error to designate as a failure.
       if (!WIFEXITED(result)) {
         status = F_status_set_error(F_failure);
       }
-
-      // @fixme needs a custom option to desginate what is an error.
+      else {
+        status = F_none;
+      }
     }
     else {
       if (!main.thread->enabled) {
@@ -1504,10 +1517,7 @@ extern "C" {
         break;
       }
 
-      if (fl_string_dynamic_compare_string(controller_string_create_s, cache->action.name_action, controller_string_create_length) == F_equal_to) {
-        type = controller_rule_action_type_create;
-      }
-      else if (fl_string_dynamic_compare_string(controller_string_group_s, cache->action.name_action, controller_string_group_length) == F_equal_to) {
+      if (fl_string_dynamic_compare_string(controller_string_group_s, cache->action.name_action, controller_string_group_length) == F_equal_to) {
         type = controller_rule_action_type_group;
       }
       else if (fl_string_dynamic_compare_string(controller_string_kill_s, cache->action.name_action, controller_string_kill_length) == F_equal_to) {
@@ -1516,6 +1526,9 @@ extern "C" {
       else if (fl_string_dynamic_compare_string(controller_string_pause_s, cache->action.name_action, controller_string_pause_length) == F_equal_to) {
         type = controller_rule_action_type_pause;
       }
+      else if (fl_string_dynamic_compare_string(controller_string_pid_file_s, cache->action.name_action, controller_string_pid_file_length) == F_equal_to) {
+        type = controller_rule_action_type_pid_file;
+      }
       else if (fl_string_dynamic_compare_string(controller_string_restart_s, cache->action.name_action, controller_string_restart_length) == F_equal_to) {
         type = controller_rule_action_type_restart;
       }
@@ -1531,9 +1544,6 @@ extern "C" {
       else if (fl_string_dynamic_compare_string(controller_string_stop_s, cache->action.name_action, controller_string_stop_length) == F_equal_to) {
         type = controller_rule_action_type_stop;
       }
-      else if (fl_string_dynamic_compare_string(controller_string_use_s, cache->action.name_action, controller_string_use_length) == F_equal_to) {
-        type = controller_rule_action_type_use;
-      }
       else if (fl_string_dynamic_compare_string(controller_string_user_s, cache->action.name_action, controller_string_user_length) == F_equal_to) {
         type = controller_rule_action_type_user;
       }
@@ -1560,7 +1570,7 @@ extern "C" {
       }
 
       if (multiple) {
-        if (type == controller_rule_action_type_create || type == controller_rule_action_type_group || type == controller_rule_action_type_use || type == controller_rule_action_type_user) {
+        if (type == controller_rule_action_type_group || type == controller_rule_action_type_pid_file || type == controller_rule_action_type_user) {
 
           if (main.data->error.verbosity != f_console_verbosity_quiet) {
             f_thread_mutex_lock(&main.thread->lock.print);
index f32b12c5b96c19b095bca76df2578ec342c150dd..2eb8c8762ab4fb113763e45d93427d7faefcd391 100644 (file)
@@ -428,8 +428,6 @@ extern "C" {
  *
  * @param pid_file
  *   The path to the PID file.
- * @param pid_type
- *   The type of the PID file, either "controller_rule_action_type_create" or "controller_rule_action_type_use".
  * @param type
  *   The item type code.
  * @param action
@@ -448,6 +446,8 @@ extern "C" {
  * @param options
  *   A number using bits to represent specific boolean options.
  *   If bit controller_process_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule).
+ * @param with
+ *   The "with" option flags.
  * @param main
  *   The main data.
  * @param execute_set
@@ -457,18 +457,18 @@ extern "C" {
  *
  * @return
  *   F_none on success.
- *   F_busy on successful execute in asynchronous mode (executed process may or may not fail later on).
  *   F_child on child process exiting.
  *   F_signal on (exit) signal received.
  *
  *   F_lock (with error bit) if failed to re-establish read lock on process->lock while returning.
+ *   F_file_found (with error bit) if the PID file already exists.
  *
  *   Errors (with error bit) from: fll_execute_program().
  *
  * @see fll_execute_program()
  */
 #ifndef _di_controller_rule_execute_pid_with_
-  extern f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t *pid_file, const uint8_t pid_type, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, const controller_main_t main, controller_execute_set_t * const execute_set, controller_process_t *process) f_gcc_attribute_visibility_internal;
+  extern f_status_t controller_rule_execute_pid_with(const f_string_dynamic_t pid_file, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, const uint8_t with, const controller_main_t main, controller_execute_set_t * const execute_set, controller_process_t *process) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_execute_pid_with_
 
 /**
index 077d93ddf6c2e534c311157e9886321a5debe5a3..a11f091502849b81c25a829f16a8f175791f7ef9 100644 (file)
@@ -57,6 +57,14 @@ extern "C" {
             continue;
           }
 
+          // if process has a pid file, then it is running in the background, only cleanup if the pid file no longer exists.
+          if (process->path_pid.used && f_file_exists(process->path_pid.string) == F_true) {
+            f_thread_unlock(&process->active);
+            f_thread_unlock(&process->lock);
+
+            continue;
+          }
+
           f_thread_unlock(&process->lock);
 
           // close any still open thread.
@@ -88,6 +96,12 @@ extern "C" {
           controller_cache_delete_simple(&process->cache);
           f_type_array_lengths_resize(0, &process->stack);
 
+          // deallocate the pid file.
+          if (process->path_pid.used) {
+            process->path_pid.used = 0;
+            f_string_dynamic_resize(0, &process->path_pid);
+          }
+
           // deallocate any rules in the space that is declared to be unused.
           if (i >= main->thread->processs.used) {
             controller_rule_delete_simple(&process->rule);
@@ -349,6 +363,7 @@ extern "C" {
     controller_process_t *process = 0;
 
     f_array_length_t i = 0;
+    pid_t pid = 0;
 
     if (main->thread->id_cleanup) {
       f_thread_cancel(main->thread->id_cleanup);
@@ -371,6 +386,14 @@ extern "C" {
       if (process->child > 0) {
         f_signal_send(F_signal_termination, process->child);
       }
+
+      if (process->path_pid.used && f_file_exists(process->path_pid.string) == F_true) {
+        status = controller_file_pid_read(process->path_pid, &pid);
+
+        if (pid) {
+          f_signal_send(F_signal_termination, pid);
+        }
+      }
     } // for
 
     for (i = 0; i < main->thread->processs.used; ++i) {
@@ -401,6 +424,8 @@ extern "C" {
       process = main->thread->processs.array[i];
 
       do {
+        if (!process->id_thread) break;
+
         controller_time(0, controller_thread_exit_process_cancel_wait, &time);
 
         status = f_thread_join_timed(process->id_thread, time, 0);
@@ -410,9 +435,41 @@ extern "C" {
           process->id_thread = 0;
         }
 
-        spent++;
+        ++spent;
 
       } while (status == F_time && spent < controller_thread_exit_process_cancel_total);
+
+      if (process->path_pid.used) {
+        for (; spent < controller_thread_exit_process_cancel_total; ++spent) {
+
+          if (f_file_exists(process->path_pid.string) == F_true) {
+            status = controller_file_pid_read(process->path_pid, &pid);
+
+            if (pid) {
+
+              // a hackish way to determine if the pid exists while waiting.
+              if (getpgid(pid) >= 0) {
+                time.tv_sec = 0;
+                time.tv_nsec = controller_thread_exit_process_cancel_wait;
+
+                nanosleep(&time, 0);
+              }
+              else {
+                f_file_remove(process->path_pid.string);
+                process->path_pid.used = 0;
+
+                break;
+              }
+            }
+            else {
+              break;
+            }
+          }
+          else {
+            break;
+          }
+        } // for
+      }
     } // for
 
     for (i = 0; i < main->thread->processs.size; ++i) {
@@ -436,6 +493,19 @@ extern "C" {
         process->child = 0;
         process->id_thread = 0;
       }
+
+      if (process->path_pid.used) {
+        if (f_file_exists(process->path_pid.string) == F_true) {
+          status = controller_file_pid_read(process->path_pid, &pid);
+
+          if (pid) {
+            f_signal_send(F_signal_kill, pid);
+          }
+
+          f_file_remove(process->path_pid.string);
+          process->path_pid.used = 0;
+        }
+      }
     } // for
   }
 #endif // _di_controller_thread_process_cancel_
index 2961de4c37811f02c400320eaa53d842e400d1d9..5a5f3b6e673b4f81322fd25ff6d0a2acc51153e8 100644 (file)
@@ -9,6 +9,6 @@ setting:
   nice 15
 
 service:
-  use /var/run/sshd.pid
+  pid_file /var/run/sshd.pid
   with full_path
   start sshd
index d68a12c1c36665a9a021b5b87ac1815dd614f9ca..f90ceca7e22ece0bd896d280b589606854715e77 100644 (file)
@@ -1,12 +1,12 @@
 # fss-000d
-# sleeper rule whose program creates its own PID file, sleep for a while, removes PID file, and returns.
+# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
 
 setting:
   name "Sleeper #1"
   nice 10
 
 utility:
-  use /tmp/sleeper_1.pid
+  pid_file /tmp/sleeper_1.pid
   start {
     \#!/bin/bash
 
@@ -16,7 +16,7 @@ utility:
         return 1
       fi
 
-      echo "$$" > /tmp/sleeper_1.pid
+      echo "$BASHPID" > /tmp/sleeper_1.pid
 
       echo "Sleeper 1, now sleeping."
       sleep 20m
@@ -26,5 +26,5 @@ utility:
       return 0
     \}
 
-    main
+    main &
   }
index 7eb1cae6655c92e572bdf8a3e4bfd7224569383e..be70fe105347769fb81ce2a12208c567022e6290 100644 (file)
@@ -1,22 +1,30 @@
 # fss-000d
-# sleeper rule whose program does not create its own PID file, sleeps for a while and returns.
+# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
 
 setting:
   name "Sleeper #2"
   nice 10
 
 utility:
-  create /tmp/sleeper_2.pid
+  pid_file /tmp/sleeper_2.pid
   start {
     \#!/bin/bash
 
     main() {
+      if [[ -f /tmp/sleeper_2.pid ]] ; then
+        echo "Failure: pid file '/tmp/sleeper_1.pid' already exists."
+        return 1
+      fi
+
+      echo "$BASHPID" > /tmp/sleeper_2.pid
+
       echo "Sleeper 2, now sleeping."
       sleep 25m
 
       echo "Sleeper 2, done sleeping."
+      rm -f /tmp/sleeper_2.pid
       return 0
     \}
 
-    main
+    main &
   }
index c4d3b6e0e153f6ea13b7308b847270d37ef03bae..50fbcb38c6ed44d5a5781148965adb73f5212e4b 100644 (file)
@@ -8,21 +8,21 @@ setting:
   capability "all="
 
 service:
-  use /var/run/tty/tty1.pid
+  pid_file /var/run/tty/tty1.pid
 
   start qingy tty1 -d -l -n -t
 
 service:
-  use /var/run/tty/tty2.pid
+  pid_file /var/run/tty/tty2.pid
 
   start qingy tty2 -d -l -n -t
 
 service:
-  use /var/run/tty/tty3.pid
+  pid_file /var/run/tty/tty3.pid
 
   start qingy tty3 -d -l -n -t
 
 service:
-  use /var/run/tty/tty4.pid
+  pid_file /var/run/tty/tty4.pid
 
   start qingy tty4 -d -l -n -t
index ed434be5d76e9d263fc65501c45d591a399d0c2e..d9cdb113cc93f23ee82aac549f39303fd28a0b96 100644 (file)
@@ -9,6 +9,6 @@ setting:
   nice 15
 
 service:
-  use /var/run/dbus/dbus.pid
+  pid_file /var/run/dbus/dbus.pid
 
   start dbus-daemon --system --fork
index 23abe8f77d685eeedaa17141a56bcbd55f58f2b1..3d0f7cde639357eb7cfef1730db93e89edc480b0 100644 (file)
@@ -11,6 +11,6 @@ setting:
 
 service:
   # @todo consider adding support for IKI to make "/var/run/logger/logger.pid" a variable.
-  use /var/run/logger/logger.pid
+  pid_file /var/run/logger/logger.pid
 
   start metalog -B -p /var/run/logger/logger.pid -C /etc/logger.conf
index f2e0061a850daa001ba8266e5539910d13d030d6..06a392c419abd849d1e001a9812a01d7ccaa31e7 100644 (file)
@@ -16,7 +16,7 @@ script:
   }
 
 service:
-  use /var/run/mouse/mouse.pid
+  pid_file /var/run/mouse/mouse.pid
 
   # @todo
   start gpm -m [device] -t [protocol] [options]
index 8726e046f75692ebf7619e1b3a771056e88d6d0a..b0eb33691e24d0d8c59df20c086cbddab91909e4 100644 (file)
@@ -86,9 +86,7 @@ Rule Documentation:
   When "reload", "start", or "stop" Content are not provided, then no respective action is performed.
   Commands are conditionally available depending on the presence of these, such as if "stop" is not provided then "stop" (and "restart") will not be available for the "control" program(s) to use.
 
-  The "create" Content designates that this controller program to create the PID file after successfully starting a Service or Utility.
-  The "use" Content designates that the called program will provide the PID file after successfully starting the Service or Utility.
-  For both "create" and "program" the PID file is expected to only exist on success and the existence thereof designates the success or failure.
+  The "pid_file" Content designates the path to the PID file created by the called program.
 
   The "with" Content designates special flags designating very specific behavior to be applied to any single Rule Type.
   The following flags are supported:
index c8800229eec753c2e8c0171301d3db9fe19b0cde..6cc4e6321b3b0a0dcf08745888cf8bd62b9336df 100644 (file)
@@ -58,8 +58,7 @@ Rule Specification:
     "with": One or more Content representing special options for the Rule Type.
 
   The "service" and "utility" Rule Types allow the following the FSS-0001 (Extended)\:
-    "create": One Content representing the path to a PID file.
-    "use": One Content representing the path to a PID file.
+    "pid_file": One Content representing the path to a PID file.
     "with": One or more Content representing special options for the Rule Type.
 
   The "command" and "service" Rule Types allow the following the FSS-0003 (Extended List)\: