]> Kevux Git Server - fll/commitdiff
Progress: controller program.
authorKevin Day <thekevinday@gmail.com>
Fri, 22 Jan 2021 05:21:30 +0000 (23:21 -0600)
committerKevin Day <thekevinday@gmail.com>
Fri, 22 Jan 2021 05:21:30 +0000 (23:21 -0600)
Wrap all print functions that print while any threading is in used with a mutex lock.

Add controller_execute_set_t to shorten the execute function arguments.

Add missing f_gcc_attribute_visibility_internal.

The controller_rule_read() inside of entry does not need to be read locked.
This operation happens before any threads are started.

Replace simulate argument with options argument for execute functions.

Add more verbose output in the simulation for the execute operations.

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-rule.c
level_3/controller/c/private-rule.h
level_3/controller/c/private-thread.c

index c1f869d313025311c18b4546c0635dda03b43092..7488944509d1abf570681cd3b1dbdd20832375ce 100644 (file)
@@ -76,6 +76,19 @@ extern "C" {
   }
 #endif // _di_controller_rules_increase_
 
+#ifndef _di_controller_error_print_locked_
+  void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
+
+    if (error.verbosity != f_console_verbosity_quiet) {
+      f_thread_mutex_lock(&thread->mutex->print);
+
+      fll_error_print(error, status, function, fallback);
+
+      f_thread_mutex_unlock(&thread->mutex->print);
+    }
+  }
+#endif // _di_controller_error_print_locked_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 69940b3d271c21c1fbdb82f55381bdc846d943b5..6085c7b94c1e2af4922ccc8f3cc2562a88707818 100644 (file)
@@ -972,6 +972,21 @@ extern "C" {
     controller_asynchronouss_resize(0, &thread.asynchronouss);
 #endif // _di_controller_thread_t_
 
+#ifndef _di_controller_execute_set_t_
+  typedef struct {
+    fl_execute_parameter_t parameter;
+    fl_execute_as_t as;
+  } controller_execute_set_t;
+
+  #define controller_execute_set_t_initialize { fl_execute_parameter_t_initialize, fl_execute_as_t_initialize }
+
+  #define controller_macro_execute_set_t_initialize(option, environment, signals, data, as) { fl_macro_execute_parameter_t_initialize(option, environment, signals, data), as }
+
+  #define controller_macro_execute_set_t_clear(set) \
+    fl_macro_execute_parameter_t_clear(set.parameter) \
+    fl_macro_execute_as_t_clear(set.as)
+#endif // _di_controller_execute_set_t_
+
 /**
  * Resize the asynchronouss array to a larger size.
  *
@@ -1011,7 +1026,7 @@ extern "C" {
  *   F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_controller_asynchronouss_increase_
-  extern f_status_t controller_asynchronouss_increase(controller_asynchronouss_t *asynchronouss);
+  extern f_status_t controller_asynchronouss_increase(controller_asynchronouss_t *asynchronouss) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_asynchronouss_increase_
 
 /**
@@ -1029,10 +1044,32 @@ extern "C" {
  *   F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_controller_asynchronouss_resize_
-  extern f_status_t controller_asynchronouss_resize(const f_array_length_t length, controller_asynchronouss_t *asynchronouss);
+  extern f_status_t controller_asynchronouss_resize(const f_array_length_t length, controller_asynchronouss_t *asynchronouss) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_asynchronouss_resize_
 
 /**
+ * Print the error, locking the print mutex during the print.
+ *
+ * @param print
+ *   Designates how printing is to be performed.
+ * @param status
+ *   The status code to process.
+ *   Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
+ * @param function
+ *   The name of the function where the error happened.
+ *   Set to 0 to disable.
+ * @param fallback
+ *   Set to F_true to print the fallback error message for unknown errors.
+ * @param thread
+ *   The thread data.
+ *
+ * @see fll_error_print()
+ */
+#ifndef _di_controller_error_print_locked_
+  extern void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_error_print_locked_
+
+/**
  * Increase the size of the rules array, but only if necessary.
  *
  * @param rules
index b3a51392776367181acd73103379195c6776f322..02ba77e5254c190fe932f8326d64f074349049d5 100644 (file)
@@ -877,12 +877,8 @@ extern "C" {
             memcpy(cache_name_item, thread->cache_action->name_item.string, thread->cache_action->name_item.used);
             memcpy(cache_name_file, thread->cache_action->name_file.string, thread->cache_action->name_file.used);
 
-            f_thread_mutex_lock(&thread->mutex->rule);
-
             status = controller_rule_read(*data, *setting, rule_id, thread, cache, &setting->rules.array[setting->rules.used]);
 
-            f_thread_mutex_unlock(&thread->mutex->rule);
-
             // restore cache.
             memcpy(thread->cache_action->name_action.string, cache_name_action, cache_name_action_used);
             memcpy(thread->cache_action->name_item.string, cache_name_item, cache_name_item_used);
index 6b22013aaae32362721a94d49ad045ff30611683..2516ed3c7c255df21c93cd5f819a376b0b14231a 100644 (file)
@@ -433,6 +433,19 @@ extern "C" {
   }
 #endif // _di_controller_rule_error_print_
 
+#ifndef _di_controller_rule_error_print_
+  void controller_rule_error_print_locked(const fll_error_print_t output, const controller_cache_action_t cache, const bool item, controller_thread_t *thread) {
+
+    if (output.verbosity != f_console_verbosity_quiet) {
+      f_thread_mutex_lock(&thread->mutex->print);
+
+      controller_rule_error_print(output, cache, item);
+
+      f_thread_mutex_unlock(&thread->mutex->print);
+    }
+  }
+#endif // _di_controller_rule_error_print_
+
 #ifndef _di_controller_rule_error_print_execute_
   void controller_rule_error_print_execute(const fll_error_print_t output, const bool script_is, const f_string_t name, const int code, const f_status_t status) {
 
@@ -497,7 +510,7 @@ extern "C" {
 #endif // _di_controller_rule_error_print_need_want_wish_
 
 #ifndef _di_controller_rule_execute_
-  f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const bool simulate, controller_thread_t *thread) {
+  f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const uint8_t options, controller_thread_t *thread) {
     f_status_t status = F_none;
     f_status_t success = F_false;
 
@@ -517,26 +530,26 @@ extern "C" {
     f_string_maps_t environment = f_string_maps_t_initialize;
 
     const f_string_dynamics_t arguments_none = f_string_dynamics_t_initialize;
-    fl_execute_parameter_t parameter = fl_macro_execute_parameter_t_initialize(fl_execute_parameter_option_threadsafe, &environment, &signals, 0);
-    fl_execute_as_t as = fl_execute_as_t_initialize;
+
+    controller_execute_set_t execute_set = controller_macro_execute_set_t_initialize(0, &environment, &signals, 0, fl_execute_as_t_initialize);
 
     if (rule->affinity.used) {
-      as.affinity = &rule->affinity;
+      execute_set.as.affinity = &rule->affinity;
     }
 
     if (rule->capability) {
-      as.capability = rule->capability;
+      execute_set.as.capability = rule->capability;
     }
 
     if (rule->has & controller_rule_has_control_group) {
-      as.control_group = &rule->control_group;
+      execute_set.as.control_group = &rule->control_group;
 
       // make sure all required cgroup directories exist.
       if (rule->status == F_known_not) {
         status = fll_control_group_prepare(rule->control_group);
 
         if (F_status_is_error(status)) {
-          fll_error_print(thread->data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true);
+          controller_error_print_locked(thread->data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread);
 
           rule->status = F_status_set_error(F_failure);
           return status;
@@ -545,33 +558,33 @@ extern "C" {
     }
 
     if (rule->has & controller_rule_has_group) {
-      as.id_group = &rule->group;
+      execute_set.as.id_group = &rule->group;
 
       if (rule->groups.used) {
-        as.id_groups = &rule->groups;
+        execute_set.as.id_groups = &rule->groups;
       }
     }
 
     if (rule->limits.used) {
-      as.limits = &rule->limits;
+      execute_set.as.limits = &rule->limits;
     }
 
     if (rule->has & controller_rule_has_scheduler) {
-      as.scheduler = &rule->scheduler;
+      execute_set.as.scheduler = &rule->scheduler;
     }
 
     if (rule->has & controller_rule_has_nice) {
-      as.nice = &rule->nice;
+      execute_set.as.nice = &rule->nice;
     }
 
     if (rule->has & controller_rule_has_user) {
-      as.id_user = &rule->user;
+      execute_set.as.id_user = &rule->user;
     }
 
     status = fl_environment_load_names(rule->environment, &environment);
 
     if (F_status_is_error(status)) {
-      fll_error_print(thread->data->error, F_status_set_fine(status), "fl_environment_load_names", F_true);
+      controller_error_print_locked(thread->data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread);
 
       rule->status = F_status_set_error(F_failure);
       return status;
@@ -599,16 +612,16 @@ extern "C" {
 
         action = &item->actions.array[j];
 
-        parameter.data = 0;
-        parameter.option = 0;
+        execute_set.parameter.data = 0;
+        execute_set.parameter.option = fl_execute_parameter_option_threadsafe;
 
         if (item->type == controller_rule_item_type_command) {
 
           if (strchr(action->parameters.array[0].string, f_path_separator_s[0])) {
-            parameter.option |= fl_execute_parameter_option_path;
+            execute_set.parameter.option |= fl_execute_parameter_option_path;
           }
 
-          status = controller_rule_execute_foreground(item->type, *action, simulate, 0, action->parameters, 0, &parameter, &as, thread->data);
+          status = controller_rule_execute_foreground(index, item->type, *action, 0, action->parameters, options, &execute_set, thread);
 
           if (status == F_child) {
             break;
@@ -617,19 +630,19 @@ extern "C" {
           if (F_status_is_error(status)) {
             action->status = F_status_set_error(F_failure);
 
-            if (!simulate) break;
+            if (!(options & controller_rule_option_simulate)) break;
           }
 
           success = F_true;
         }
         else if (item->type == controller_rule_item_type_script) {
-          parameter.data = &action->parameters.array[0];
+          execute_set.parameter.data = &action->parameters.array[0];
 
           if (rule->script.used && strchr(rule->script.string, f_path_separator_s[0])) {
-            parameter.option |= fl_execute_parameter_option_path;
+            execute_set.parameter.option |= fl_execute_parameter_option_path;
           }
 
-          status = controller_rule_execute_foreground(item->type, *action, simulate, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, 0, &parameter, &as, thread->data);
+          status = controller_rule_execute_foreground(index, item->type, *action, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, options, &execute_set, thread);
 
           if (status == F_child) {
             break;
@@ -638,7 +651,7 @@ extern "C" {
           if (F_status_is_error(status)) {
             action->status = F_status_set_error(F_failure);
 
-            if (!simulate) break;
+            if (!(options & controller_rule_option_simulate)) break;
           }
 
           success = F_true;
@@ -646,15 +659,15 @@ extern "C" {
         else if (item->type == controller_rule_item_type_service) {
 
           if (strchr(action->parameters.array[0].string, f_path_separator_s[0])) {
-            parameter.option |= fl_execute_parameter_option_path;
+            execute_set.parameter.option |= fl_execute_parameter_option_path;
           }
 
-          status = controller_rule_execute_pid_with(item->type, *action, simulate, 0, action->parameters, 0, &parameter, &as, thread->data);
+          status = controller_rule_execute_pid_with(index, item->type, *action, 0, action->parameters, options, &execute_set, thread);
 
           if (F_status_is_error(status)) {
             action->status = F_status_set_error(F_failure);
 
-            if (!simulate) break;
+            if (!(options & controller_rule_option_simulate)) break;
           }
 
           success = F_true;
@@ -662,10 +675,14 @@ extern "C" {
         else {
 
           if (thread->data->warning.verbosity == f_console_verbosity_debug) {
+            f_thread_mutex_lock(&thread->mutex->print);
+
             fprintf(thread->data->warning.to.stream, "%c", f_string_eol_s[0]);
             fprintf(thread->data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", thread->data->warning.context.before->string, thread->data->warning.prefix ? thread->data->warning.prefix : f_string_empty_s, thread->data->warning.context.after->string, f_string_eol_s[0]);
 
             controller_rule_error_print(thread->data->warning, *thread->cache_action, F_true);
+
+            f_thread_mutex_unlock(&thread->mutex->print);
           }
 
           action->status = F_ignore;
@@ -680,7 +697,7 @@ extern "C" {
         if (status == F_child || status == F_signal) break;
       } // for
 
-      if (status == F_child || status == F_signal || F_status_is_error(status) && !simulate) break;
+      if (status == F_child || status == F_signal || F_status_is_error(status) && !(options & controller_rule_option_simulate)) break;
     } // for
 
     f_macro_string_maps_t_delete_simple(environment);
@@ -704,7 +721,7 @@ extern "C" {
 #endif // _di_controller_rule_execute_
 
 #ifndef _di_controller_rule_execute_pid_with_
-  f_status_t controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) {
+  f_status_t controller_rule_execute_pid_with(const f_array_length_t index, 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, controller_execute_set_t * const execute_set, controller_thread_t *thread) {
 
     f_status_t status = F_none;
     int result = 0;
@@ -716,19 +733,25 @@ extern "C" {
     //       otherwise this needs to call an asynchronous execute process.
     //       until then, this controller_rule_execute_pid_with() function is not correct and only represents a process that forks to the background.
 
-    if (simulate) {
+    if (options & controller_rule_option_simulate) {
 
-      if (data->error.verbosity != f_console_verbosity_quiet) {
-        fprintf(data->output.stream, "%c", f_string_eol_s[0]);
-        fprintf(data->output.stream, "Simulating execution of '");
-        fprintf(data->output.stream, "%s%s%s", data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, data->context.reset.string);
-        fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string);
+      if (thread->data->error.verbosity != f_console_verbosity_quiet) {
+        f_thread_mutex_lock(&thread->mutex->print);
+
+        fprintf(thread->data->output.stream, "%c", f_string_eol_s[0]);
+        fprintf(thread->data->output.stream, "Simulating execution of '");
+        fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "' with the arguments: '%s", thread->data->context.important.string);
 
         for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) {
-          fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
+          fprintf(thread->data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
         } // for
 
-        fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]);
+        fprintf(thread->data->output.stream, "%s' from '", thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.notable.string, thread->setting->rules.array[index].name.used ? thread->setting->rules.array[index].name.string : f_string_empty_s, thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "%s'.%c", thread->data->context.reset.string, f_string_eol_s[0]);
+
+        f_thread_mutex_unlock(&thread->mutex->print);
       }
 
       // sleep for less than a second to better show simulation of synchronous vs asynchronous.
@@ -736,12 +759,12 @@ extern "C" {
 
       const f_string_static_t simulated_program = f_macro_string_static_t_initialize(f_string_empty_s, 0);
       const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
-      fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(parameter->option, parameter->environment, parameter->signals, &simulated_program);
+      fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.environment, execute_set->parameter.signals, &simulated_program);
 
-      status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, as, &result);
+      status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, &result);
     }
     else {
-      status = fll_execute_program(program, arguments, parameter, as, &result);
+      status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, &result);
     }
 
     if (F_status_is_error(status)) {
@@ -756,7 +779,7 @@ extern "C" {
     }
 
     if (status == F_child) {
-      data->child = result;
+      thread->data->child = result;
 
       return F_child;
     }
@@ -768,48 +791,58 @@ extern "C" {
     if (F_status_is_error(status)) {
       status = F_status_set_fine(status);
 
+      f_thread_mutex_lock(&thread->mutex->print);
+
       if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
-        controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status);
+        controller_rule_error_print_execute(thread->data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status);
       }
       else if (status == F_file_found_not) {
-        controller_rule_error_print_execute_not_found(data->error, F_false, program);
+        controller_rule_error_print_execute_not_found(thread->data->error, F_false, program);
       }
       else {
-        fll_error_print(data->error, status, "fll_execute_program", F_true);
+        fll_error_print(thread->data->error, status, "fll_execute_program", F_true);
       }
 
-      data->child = 0;
+      f_thread_mutex_unlock(&thread->mutex->print);
+
+      thread->data->child = 0;
 
       return F_status_set_error(status);
     }
 
     // @todo wait for pid file or timeout.
 
-    data->child = 0;
+    thread->data->child = 0;
 
     return status;
   }
 #endif // _di_controller_rule_execute_pid_with_
 
 #ifndef _di_controller_rule_execute_foreground_
-  f_status_t controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) {
+  f_status_t controller_rule_execute_foreground(const f_array_length_t index, 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, controller_execute_set_t * const execute_set, controller_thread_t *thread) {
 
     f_status_t status = F_none;
     int result = 0;
 
-    if (simulate) {
+    if (options & controller_rule_option_simulate) {
 
-      if (data->error.verbosity != f_console_verbosity_quiet) {
-        fprintf(data->output.stream, "%c", f_string_eol_s[0]);
-        fprintf(data->output.stream, "Simulating execution of '");
-        fprintf(data->output.stream, "%s%s%s", data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, data->context.reset.string);
-        fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string);
+      if (thread->data->error.verbosity != f_console_verbosity_quiet) {
+        f_thread_mutex_lock(&thread->mutex->print);
+
+        fprintf(thread->data->output.stream, "%c", f_string_eol_s[0]);
+        fprintf(thread->data->output.stream, "Simulating execution of '");
+        fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "' with the arguments: '%s", thread->data->context.important.string);
 
         for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) {
-          fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
+          fprintf(thread->data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
         } // for
 
-        fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]);
+        fprintf(thread->data->output.stream, "%s' from '", thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.notable.string, thread->setting->rules.array[index].name.used ? thread->setting->rules.array[index].name.string : f_string_empty_s, thread->data->context.reset.string);
+        fprintf(thread->data->output.stream, "%s'.%c", thread->data->context.reset.string, f_string_eol_s[0]);
+
+        f_thread_mutex_unlock(&thread->mutex->print);
       }
 
       // sleep for less than a second to better show simulation of synchronous vs asynchronous.
@@ -817,12 +850,12 @@ extern "C" {
 
       const f_string_static_t simulated_program = f_macro_string_static_t_initialize(f_string_empty_s, 0);
       const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
-      fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(parameter->option, parameter->environment, parameter->signals, &simulated_program);
+      fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.environment, execute_set->parameter.signals, &simulated_program);
 
-      status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, as, &result);
+      status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, &execute_set->as, &result);
     }
     else {
-      status = fll_execute_program(program, arguments, parameter, as, &result);
+      status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, &result);
     }
 
     if (F_status_is_error(status)) {
@@ -837,7 +870,7 @@ extern "C" {
     }
 
     if (status == F_child) {
-      data->child = result;
+      thread->data->child = result;
 
       return F_child;
     }
@@ -849,20 +882,24 @@ extern "C" {
     if (F_status_is_error(status)) {
       status = F_status_set_fine(status);
 
+      f_thread_mutex_lock(&thread->mutex->print);
+
       if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) {
-        controller_rule_error_print_execute(data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status);
+        controller_rule_error_print_execute(thread->data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status);
       }
       else if (status == F_file_found_not) {
-        controller_rule_error_print_execute_not_found(data->error, F_false, program);
+        controller_rule_error_print_execute_not_found(thread->data->error, F_false, program);
       }
       else {
-        fll_error_print(data->error, status, "fll_execute_program", F_true);
+        fll_error_print(thread->data->error, status, "fll_execute_program", F_true);
       }
 
+      f_thread_mutex_unlock(&thread->mutex->print);
+
       status = F_status_set_error(status);
     }
 
-    data->child = 0;
+    thread->data->child = 0;
 
     return status;
   }
@@ -1303,21 +1340,29 @@ extern "C" {
       default:
 
         if (thread->data->error.verbosity != f_console_verbosity_quiet) {
+          f_thread_mutex_lock(&thread->mutex->print);
+
           fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]);
           fprintf(thread->data->error.to.stream, "%s%sUnsupported action type '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s);
           fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, controller_rule_action_type_name(action), thread->data->error.notable.after->string);
           fprintf(thread->data->error.to.stream, "%s' while attempting to execute rule.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]);
 
           controller_rule_error_print(thread->data->error, *thread->cache_action, F_true);
+
+          f_thread_mutex_unlock(&thread->mutex->print);
         }
 
         return F_status_set_error(F_parameter);
     }
 
     if (index >= thread->setting->rules.used) {
+      f_thread_mutex_lock(&thread->mutex->print);
+
       fll_error_print(thread->data->error, F_parameter, "controller_rule_process", F_true);
       controller_rule_error_print(thread->data->error, *thread->cache_action, F_true);
 
+      f_thread_mutex_unlock(&thread->mutex->print);
+
       return F_status_set_error(F_parameter);
     }
 
@@ -1326,9 +1371,13 @@ extern "C" {
     f_macro_array_lengths_t_increase_by(status, (*thread->stack), controller_default_allocation_step)
 
     if (F_status_is_error(status)) {
+      f_thread_mutex_lock(&thread->mutex->print);
+
       fll_error_print(thread->data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true);
       controller_rule_error_print(thread->data->error, *thread->cache_action, F_true);
 
+      f_thread_mutex_unlock(&thread->mutex->print);
+
       return status;
     }
 
@@ -1584,7 +1633,7 @@ extern "C" {
       }
 
       if (F_status_is_error_not(status)) {
-        status = controller_rule_execute(index, action, options & controller_rule_option_simulate, thread);
+        status = controller_rule_execute(index, action, options, thread);
 
         if (F_status_is_error(status)) {
           controller_rule_error_print(thread->data->error, *thread->cache_action, F_true);
index 470744e1dd58f5fe05db08181e07ab9baadaec62..7730b4c3b85bb53570ffad0ca1dc57caccefa4e4 100644 (file)
@@ -153,6 +153,27 @@ extern "C" {
 #endif // _di_controller_rule_error_print_
 
 /**
+ * Print additional error/warning information in addition to existing error.
+ *
+ * This is explicitly intended to be used in addition to the error message.
+ *
+ * @param output
+ *   The error or warning output structure.
+ * @param cache
+ *   A structure for containing and caching relevant data.
+ * @param item
+ *   If TRUE, then this error is associated with an item.
+ *   If FALSE, then this error is associated with a rule setting.
+ * @param thread
+ *   The thread data.
+ *
+ * @see controller_rule_error_print()
+ */
+#ifndef _di_controller_rule_error_print_
+  extern void controller_rule_error_print_locked(const fll_error_print_t output, const controller_cache_action_t cache, const bool item, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_error_print_
+
+/**
  * Print an error or warning message related to the failed execution of some program or script.
  *
  * @param output
@@ -218,9 +239,9 @@ extern "C" {
  *   - controller_rule_action_type_resume
  *   - controller_rule_action_type_start
  *   - controller_rule_action_type_stop
- * @param simulate
- *   If TRUE, then run a simulated action (outputing result and executing an empty script).
- *   If FALSE, perform the real execution.
+ * @param options
+ *   A number using bits to represent specific boolean options.
+ *   If bit controller_rule_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 thread
  *   The thread data.
  *
@@ -234,7 +255,7 @@ extern "C" {
  *   On failure, the individual status for the rule is set to an appropriate error status.
  */
 #ifndef _di_controller_rule_execute_
-  extern f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const bool simulate, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+  extern f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const uint8_t options, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_execute_
 
 /**
@@ -243,6 +264,8 @@ extern "C" {
  * When this is synchronous, this will wait for the PID file to be generated before continuing.
  * When this is asynchronous, this will continue on adding the rule id and action to the asynchronous list.
  *
+ * @param index
+ *   The index location in the rules running this action.
  * @param type
  *   The item type code.
  * @param action
@@ -254,23 +277,17 @@ extern "C" {
  *   - controller_rule_action_type_restart
  *   - controller_rule_action_type_start
  *   - controller_rule_action_type_stop
- * @param simulate
- *   If TRUE, then run a simulated action (outputing result and executing an empty script).
- *   If FALSE, perform the real execution.
  * @param program
  *   The program to use (such as "bash").
  * @param arguments
  *   The arguments to pass to the program.
  * @param options
- *   The controller execute options (and not fl_execute_parameter_t.option).
- *   This is for designating asynchronous and other controller specific execution options.
- *   @todo this is not yet implemented.
- * @param parameter
- *   The execute parameter settings.
- * @param as
- *   The execute as settings.
- * @param data
- *   The program data.
+ *   A number using bits to represent specific boolean options.
+ *   If bit controller_rule_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 execute_set
+ *   The execute parameter and as settings.
+ * @param thread
+ *   The thread data.
  *
  * @return
  *   F_none on success.
@@ -283,12 +300,14 @@ extern "C" {
  * @see fll_execute_program()
  */
 #ifndef _di_controller_rule_execute_pid_with_
-  extern f_status_t controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal;
+  extern f_status_t controller_rule_execute_pid_with(const f_array_length_t index, 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, controller_execute_set_t * const execute_set, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_execute_pid_with_
 
 /**
  * Perform an execution of the given rule in the foreground.
  *
+ * @param index
+ *   The index location in the rules running this action.
  * @param type
  *   The item type code.
  * @param action
@@ -300,23 +319,17 @@ extern "C" {
  *   - controller_rule_action_type_restart
  *   - controller_rule_action_type_start
  *   - controller_rule_action_type_stop
- * @param simulate
- *   If TRUE, then run a simulated action (outputing result and executing an empty script).
- *   If FALSE, perform the real execution.
  * @param program
  *   The program to use (such as "bash").
  * @param arguments
  *   The arguments to pass to the program.
  * @param options
- *   The controller execute options (and not fl_execute_parameter_t.option).
- *   This is for designating asynchronous and other controller specific execution options.
- *   @todo this is not yet implemented.
- * @param parameter
- *   The execute parameter settings.
- * @param as
- *   The execute as settings.
- * @param data
- *   The program data.
+ *   A number using bits to represent specific boolean options.
+ *   If bit controller_rule_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 execute_set
+ *   The execute parameter and as settings.
+ * @param thread
+ *   The thread data.
  *
  * @return
  *   F_none on success.
@@ -328,7 +341,7 @@ extern "C" {
  * @see fll_execute_program()
  */
 #ifndef _di_controller_rule_execute_foreground_
-  extern f_status_t controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal;
+  extern f_status_t controller_rule_execute_foreground(const f_array_length_t index, 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, controller_execute_set_t * const execute_set, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_execute_foreground_
 
 /**
index 0973ae5624e9244f86a31dc00dfb59f097b8d006..dd6f98ea242ba8614d84aa66b5969f3ce51986a0 100644 (file)
@@ -142,7 +142,7 @@ extern "C" {
 
     if (F_status_is_error(status)) {
       if (thread->data->error.verbosity != f_console_verbosity_quiet) {
-        fll_error_print(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true);
+        controller_error_print_locked(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true, thread);
       }
     }
     else {
@@ -151,10 +151,14 @@ extern "C" {
 
         if (f_file_exists(thread->setting->path_pid.string) == F_true) {
           if (thread->data->error.verbosity != f_console_verbosity_quiet) {
+            f_thread_mutex_lock(&thread->mutex->print);
+
             fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]);
             fprintf(thread->data->error.to.stream, "%s%sThe pid file '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s);
             fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, thread->setting->path_pid.string, thread->data->error.notable.after->string);
             fprintf(thread->data->error.to.stream, "%s' must not already exist.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]);
+
+            f_thread_mutex_unlock(&thread->mutex->print);
           }
 
           thread->setting->ready = controller_setting_ready_abort;
@@ -178,10 +182,14 @@ extern "C" {
 
             if (f_file_exists(thread->setting->path_pid.string) == F_true) {
               if (thread->data->error.verbosity != f_console_verbosity_quiet) {
+                f_thread_mutex_lock(&thread->mutex->print);
+
                 fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]);
                 fprintf(thread->data->error.to.stream, "%s%sThe pid file '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s);
                 fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, thread->setting->path_pid.string, thread->data->error.notable.after->string);
                 fprintf(thread->data->error.to.stream, "%s' must not already exist.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]);
+
+                f_thread_mutex_unlock(&thread->mutex->print);
               }
 
               thread->setting->ready = controller_setting_ready_fail;
@@ -224,7 +232,7 @@ extern "C" {
 
       if (F_status_is_error(status)) {
         if (thread->data->error.verbosity != f_console_verbosity_quiet) {
-          fll_error_print(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true);
+          controller_error_print_locked(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true, thread);
         }
       }
     }