From ad5e575c1d771ca94501398e7fcb142a26a3538c Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 12 Apr 2021 22:18:47 -0500 Subject: [PATCH] Progress: controller program, implementing failsafe. Minor code cleanup: - Removing no longer valid documentation. - Cleaning up syntax, such as spacing. - Updating documentation comments. - Pass controller_main_t as a pointer in the entry function, updating all uses. - Remove @fixme for considering status handling because I don't plan on bothering with this now. A lot of the controller_print_unlock_flush() calls are using the incorrect stream. Use status_lock as a return in cases where the status that is retuned shouldn't become lost when processing the locks. Otherwise, the errors may never properly bubble to the parent and therefore may never trigger the failsafe. The failsafe is not a rule id, but instead an item id. If and when failsafe support is enabled, trigger it. The currently implemented code only handles synchronous failures. Begin work with adding a "failed" flag so that asynchronous, but required, failures can be detected for the purposes of failsafe execution. --- level_3/controller/c/controller.c | 4 - level_3/controller/c/private-common.c | 1 + level_3/controller/c/private-common.h | 10 +- level_3/controller/c/private-controller.c | 491 +++++++++++---------- level_3/controller/c/private-controller.h | 7 +- level_3/controller/c/private-entry.c | 19 +- level_3/controller/c/private-rule.c | 177 ++++---- level_3/controller/c/private-thread.c | 19 +- .../data/settings/example/entries/test.entry | 2 +- .../data/settings/example/rules/script/fail.rule | 2 +- 10 files changed, 386 insertions(+), 346 deletions(-) diff --git a/level_3/controller/c/controller.c b/level_3/controller/c/controller.c index 2c704a0..0647ff1 100644 --- a/level_3/controller/c/controller.c +++ b/level_3/controller/c/controller.c @@ -376,10 +376,6 @@ extern "C" { return status; } - if (setting.ready == controller_setting_ready_fail) { - // @todo trigger failsafe/fallback execution, if defined. - } - return status; } #endif // _di_controller_main_ diff --git a/level_3/controller/c/private-common.c b/level_3/controller/c/private-common.c index 6eff715..b7aa086 100644 --- a/level_3/controller/c/private-common.c +++ b/level_3/controller/c/private-common.c @@ -165,6 +165,7 @@ extern "C" { void controller_lock_delete_simple(controller_lock_t *lock) { controller_lock_delete_mutex(&lock->print); + controller_lock_delete_rw(&lock->process); controller_lock_delete_rw(&lock->rule); } diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 045e2c7..f90a0ef 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -435,12 +435,10 @@ extern "C" { * A structure for sharing mutexes globally between different threads. * * The print lock is intended to lock any activity printing to stdout/stderr. - * The entry lock is intended to lock any activity on the entrys structure. * The process lock is intended to lock any activity on the processs structure. * The rule lock is intended to lock any activity on the rules structure. * * print: The print mutex lock. - * entry: The entry r/w lock. * process: The process r/w lock. * rule: The rule r/w lock. */ @@ -1002,11 +1000,11 @@ extern "C" { * timeout_start: The timeout to wait relating to starting a process. * timeout_stop: The timeout to wait relating to stopping a process. * failsafe_enabled: TRUE if failsafe execution is enabled, FALSE otherwise. - * failsafe_rule_id: The Rule ID (such as "failsafe/bash") to execute when failsafe execution is enabled. + * failsafe_item_id: The Entry Item ID to execute when failsafe execution is enabled. * path_control: File path to the control socket. * path_pid: File path to the PID file. * path_setting: File path to the setting directory. - * entry: The entry settings. + * entry: The Entry settings. * rules: All rules and their respective settings. */ #ifndef _di_controller_setting_t @@ -1028,7 +1026,7 @@ extern "C" { f_number_unsigned_t timeout_stop; bool failsafe_enabled; - f_array_length_t failsafe_rule_id; + f_array_length_t failsafe_item_id; f_string_dynamic_t path_control; f_string_dynamic_t path_pid; @@ -1095,6 +1093,7 @@ extern "C" { typedef struct { bool enabled; + bool failed; int signal; f_status_t status; @@ -1110,6 +1109,7 @@ extern "C" { #define controller_thread_t_initialize { \ F_true, \ + F_false, \ 0, \ F_none, \ f_thread_id_t_initialize, \ diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index 3052cd9..e9d4fca 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -106,7 +106,7 @@ extern "C" { fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stream_open", F_true, path, "open", fll_error_file_type_file); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else { @@ -118,7 +118,7 @@ extern "C" { fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stream_read", F_true, path, "read", fll_error_file_type_file); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } } @@ -136,7 +136,7 @@ extern "C" { fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stat", F_true, path, "stat", fll_error_file_type_file); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else { @@ -364,7 +364,7 @@ extern "C" { controller_entry_error_print_cache(main.data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } return status; @@ -377,7 +377,7 @@ extern "C" { controller_entry_error_print_cache(main.data->warning, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } status = F_none; @@ -465,7 +465,7 @@ extern "C" { controller_entry_error_print_cache(main.data->warning, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } } @@ -498,7 +498,7 @@ extern "C" { controller_entry_error_print_cache(main.data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status)) { @@ -561,7 +561,7 @@ extern "C" { controller_entry_error_print_cache(main.data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status)) { @@ -617,7 +617,7 @@ extern "C" { #endif // _di_controller_preprocess_entry_ #ifndef _di_controller_process_entry_ - f_status_t controller_process_entry(controller_main_t main, controller_cache_t *cache) { + f_status_t controller_process_entry(const bool failsafe, controller_main_t *main, controller_cache_t *cache) { f_status_t status = F_none; f_array_length_t i = 0; @@ -637,7 +637,7 @@ extern "C" { // an empty stack is used here because each rule here is the first rule run in the rule's scope. const f_array_lengths_t stack = f_array_lengths_t_initialize; - const bool simulate = main.data->parameters[controller_parameter_test].result == f_console_result_found; + const bool simulate = main->data->parameters[controller_parameter_test].result == f_console_result_found; cache->ats.used = 0; cache->stack.used = 0; @@ -647,53 +647,53 @@ extern "C" { cache->action.name_action.used = 0; cache->action.name_item.used = 0; - if (main.setting->ready == controller_setting_ready_yes) { - status = controller_perform_ready(main, cache); + if (main->setting->ready == controller_setting_ready_yes) { + status = controller_perform_ready(*main, cache); if (F_status_is_error(status)) return status; } f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step) if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main->thread); return status; } // utilize the ats cache as an item execution stack (at_i is for item index, and at_j (at_i + 1) is for action index). - cache->ats.array[0] = 0; + cache->ats.array[0] = failsafe ? main->setting->failsafe_item_id : 0; cache->ats.array[1] = 0; cache->ats.used = 2; - cache->action.line_item = main.setting->entry.items.array[0].line; + cache->action.line_item = main->setting->entry.items.array[cache->ats.array[0]].line; cache->action.name_item.used = 0; - status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[0].name, &cache->action.name_item); + status = controller_string_dynamic_append_terminated(main->setting->entry.items.array[cache->ats.array[0]].name, &cache->action.name_item); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main->thread); return status; } if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Processing entry item '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_main_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Processing %sentry item '", (failsafe ? "failsafe " : "")); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, cache->action.name_item.string, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "'.%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } - for (; main.thread->enabled; ) { + for (; main->thread->enabled; ) { - entry_actions = &main.setting->entry.items.array[cache->ats.array[at_i]].actions; + entry_actions = &main->setting->entry.items.array[cache->ats.array[at_i]].actions; - for (; cache->ats.array[at_j] < entry_actions->used && main.thread->enabled; ++cache->ats.array[at_j]) { + for (; cache->ats.array[at_j] < entry_actions->used && main->thread->enabled; ++cache->ats.array[at_j]) { entry_action = &entry_actions->array[cache->ats.array[at_j]]; @@ -703,7 +703,7 @@ extern "C" { status = controller_string_dynamic_append_terminated(controller_entry_action_type_name(entry_action->type), &cache->action.name_action); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main->thread); return status; } @@ -711,115 +711,115 @@ extern "C" { if (F_status_is_error(entry_action->status)) { if (entry_action->type == controller_entry_action_type_rule) { if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "The entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_action.string, main.data->context.set.title.after->string); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "The entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, cache->action.name_action.string, main->data->context.set.title.after->string); if (entry_action->parameters.used) { - fprintf(main.data->output.stream, f_string_space_s); - fprintf(main.data->output.stream, "%s", main.data->context.set.notable.before->string); - controller_entry_action_parameters_print(main.data->output.stream, entry_actions->array[cache->ats.array[at_j]]); - fprintf(main.data->output.stream, "%s", main.data->context.set.notable.after->string); + fprintf(main->data->output.stream, f_string_space_s); + fprintf(main->data->output.stream, "%s", main->data->context.set.notable.before->string); + controller_entry_action_parameters_print(main->data->output.stream, entry_actions->array[cache->ats.array[at_j]]); + fprintf(main->data->output.stream, "%s", main->data->context.set.notable.after->string); } - fprintf(main.data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", entry_action->code & controller_entry_rule_code_require ? "required" : "optional", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); + fprintf(main->data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", entry_action->code & controller_entry_rule_code_require ? "required" : "optional", main->data->error.context.before->string, main->data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } else if (entry_action->code & controller_entry_rule_code_require) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->error.to.stream, "%s%sThe entry item action '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s); - fprintf(main.data->error.to.stream, "%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, cache->action.name_action.string); + fprintf(main->data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->error.to.stream, "%s%sThe entry item action '", main->data->error.context.before->string, main->data->error.prefix ? main->data->error.prefix : f_string_empty_s); + fprintf(main->data->error.to.stream, "%s%s%s", main->data->error.context.after->string, main->data->error.notable.before->string, cache->action.name_action.string); if (entry_action->parameters.used) { - fprintf(main.data->error.to.stream, f_string_space_s); - controller_entry_action_parameters_print(main.data->error.to.stream, entry_actions->array[cache->ats.array[at_j]]); + fprintf(main->data->error.to.stream, f_string_space_s); + controller_entry_action_parameters_print(main->data->error.to.stream, entry_actions->array[cache->ats.array[at_j]]); } - fprintf(main.data->error.to.stream, "%s%s' is ", main.data->error.notable.after->string, main.data->error.context.before->string); - fprintf(main.data->error.to.stream, "%s%srequired%s", main.data->error.context.after->string, main.data->error.notable.before->string, main.data->error.notable.after->string); - fprintf(main.data->error.to.stream, "%s and is in a ", main.data->error.context.before->string); - fprintf(main.data->error.to.stream, "%s%sfailed%s", main.data->error.context.after->string, main.data->error.notable.before->string, main.data->error.notable.after->string); - fprintf(main.data->error.to.stream, "%s state, skipping execution.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); + fprintf(main->data->error.to.stream, "%s%s' is ", main->data->error.notable.after->string, main->data->error.context.before->string); + fprintf(main->data->error.to.stream, "%s%srequired%s", main->data->error.context.after->string, main->data->error.notable.before->string, main->data->error.notable.after->string); + fprintf(main->data->error.to.stream, "%s and is in a ", main->data->error.context.before->string); + fprintf(main->data->error.to.stream, "%s%sfailed%s", main->data->error.context.after->string, main->data->error.notable.before->string, main->data->error.notable.after->string); + fprintf(main->data->error.to.stream, "%s state, skipping execution.%s%c", main->data->error.context.before->string, main->data->error.context.after->string, f_string_eol_s[0]); - controller_entry_error_print_cache(main.data->error, cache->action); + controller_entry_error_print_cache(main->data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->error.to.stream, &main->thread->lock.print); } return F_status_is_error(F_require); } - else if (main.data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&main.thread->lock.print); + else if (main->data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->warning.to.stream, "%s%sThe entry item action '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s); - fprintf(main.data->warning.to.stream, "%s%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, cache->action.name_action.string); + fprintf(main->data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->warning.to.stream, "%s%sThe entry item action '", main->data->warning.context.before->string, main->data->warning.prefix ? main->data->warning.prefix : f_string_empty_s); + fprintf(main->data->warning.to.stream, "%s%s%s", main->data->warning.context.after->string, main->data->warning.notable.before->string, cache->action.name_action.string); if (entry_action->parameters.used) { - fprintf(main.data->warning.to.stream, f_string_space_s); - controller_entry_action_parameters_print(main.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]); + fprintf(main->data->warning.to.stream, f_string_space_s); + controller_entry_action_parameters_print(main->data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]); } - fprintf(main.data->warning.to.stream, "%s%s' is ", main.data->warning.notable.after->string, main.data->warning.context.before->string); - fprintf(main.data->warning.to.stream, "%s%srequired%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string); - fprintf(main.data->warning.to.stream, "%s and is in a ", main.data->warning.context.before->string); - fprintf(main.data->warning.to.stream, "%s%sfailed%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string); - fprintf(main.data->warning.to.stream, "%s state, skipping execution.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]); + fprintf(main->data->warning.to.stream, "%s%s' is ", main->data->warning.notable.after->string, main->data->warning.context.before->string); + fprintf(main->data->warning.to.stream, "%s%srequired%s", main->data->warning.context.after->string, main->data->warning.notable.before->string, main->data->warning.notable.after->string); + fprintf(main->data->warning.to.stream, "%s and is in a ", main->data->warning.context.before->string); + fprintf(main->data->warning.to.stream, "%s%sfailed%s", main->data->warning.context.after->string, main->data->warning.notable.before->string, main->data->warning.notable.after->string); + fprintf(main->data->warning.to.stream, "%s state, skipping execution.%s%c", main->data->warning.context.before->string, main->data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print_cache(main.data->warning, cache->action); + controller_entry_error_print_cache(main->data->warning, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->warning.to.stream, &main->thread->lock.print); } } else { if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "The entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_action.string, main.data->context.set.title.after->string); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "The entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, cache->action.name_action.string, main->data->context.set.title.after->string); if (entry_action->parameters.used) { - fprintf(main.data->output.stream, f_string_space_s); - fprintf(main.data->output.stream, "%s", main.data->context.set.notable.before->string); - controller_entry_action_parameters_print(main.data->output.stream, entry_actions->array[cache->ats.array[at_j]]); - fprintf(main.data->output.stream, "%s", main.data->context.set.notable.after->string); + fprintf(main->data->output.stream, f_string_space_s); + fprintf(main->data->output.stream, "%s", main->data->context.set.notable.before->string); + controller_entry_action_parameters_print(main->data->output.stream, entry_actions->array[cache->ats.array[at_j]]); + fprintf(main->data->output.stream, "%s", main->data->context.set.notable.after->string); } - fprintf(main.data->output.stream, "' is in a %sfailed%s state, skipping.%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); + fprintf(main->data->output.stream, "' is in a %sfailed%s state, skipping.%c", main->data->error.context.before->string, main->data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } - else if (main.data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&main.thread->lock.print); + else if (main->data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->warning.to.stream, "%s%sThe entry item action '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s); - fprintf(main.data->warning.to.stream, "%s%s", main.data->warning.notable.before->string, cache->action.name_action.string); + fprintf(main->data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->warning.to.stream, "%s%sThe entry item action '", main->data->warning.context.before->string, main->data->warning.prefix ? main->data->warning.prefix : f_string_empty_s); + fprintf(main->data->warning.to.stream, "%s%s", main->data->warning.notable.before->string, cache->action.name_action.string); if (entry_action->parameters.used) { - fprintf(main.data->warning.to.stream, f_string_space_s); - controller_entry_action_parameters_print(main.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]); + fprintf(main->data->warning.to.stream, f_string_space_s); + controller_entry_action_parameters_print(main->data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]); } - fprintf(main.data->warning.to.stream, "%s' is in a ", main.data->warning.notable.after->string); - fprintf(main.data->warning.to.stream, "%s%sfailed%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string); - fprintf(main.data->warning.to.stream, "%s state, skipping.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]); + fprintf(main->data->warning.to.stream, "%s' is in a ", main->data->warning.notable.after->string); + fprintf(main->data->warning.to.stream, "%s%sfailed%s", main->data->warning.context.after->string, main->data->warning.notable.before->string, main->data->warning.notable.after->string); + fprintf(main->data->warning.to.stream, "%s state, skipping.%s%c", main->data->warning.context.before->string, main->data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print_cache(main.data->warning, cache->action); + controller_entry_error_print_cache(main->data->warning, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->warning.to.stream, &main->thread->lock.print); } } @@ -828,57 +828,58 @@ extern "C" { if (entry_action->type == controller_entry_action_type_ready) { - if (main.setting->ready == controller_setting_ready_wait) { + if (main->setting->ready == controller_setting_ready_wait) { if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Processing entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_ready_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Processing entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, controller_string_ready_s, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "'.%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } else { - controller_perform_ready(main, cache); + controller_perform_ready(*main, cache); if (F_status_is_error(status)) return status; } - main.setting->ready = controller_setting_ready_yes; + main->setting->ready = controller_setting_ready_yes; } else if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Ignoring entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_ready_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "', state already is ready.%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Ignoring entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, controller_string_ready_s, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "', state already is ready.%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } } else if (entry_action->type == controller_entry_action_type_item) { - if (entry_action->number == 0 || entry_action->number >= main.setting->entry.items.used) { + // @todo also prevent failsafe item from being recursively called, when failsafe == F_true. + if (entry_action->number == 0 || entry_action->number >= main->setting->entry.items.used) { // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors. - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->error.to.stream, "%s%sInvalid entry item index ", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s); - fprintf(main.data->error.to.stream, "%s%s%llu%s", main.data->error.context.after->string, main.data->error.notable.before->string, entry_action->number, main.data->error.notable.after->string); - fprintf(main.data->error.to.stream, "%s detected.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); + fprintf(main->data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->error.to.stream, "%s%sInvalid entry item index ", main->data->error.context.before->string, main->data->error.prefix ? main->data->error.prefix : f_string_empty_s); + fprintf(main->data->error.to.stream, "%s%s%llu%s", main->data->error.context.after->string, main->data->error.notable.before->string, entry_action->number, main->data->error.notable.after->string); + fprintf(main->data->error.to.stream, "%s detected.%s%c", main->data->error.context.before->string, main->data->error.context.after->string, f_string_eol_s[0]); - controller_entry_error_print_cache(main.data->error, cache->action); + controller_entry_error_print_cache(main->data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->error.to.stream, &main->thread->lock.print); } return F_status_is_error(F_critical); @@ -887,7 +888,7 @@ extern "C" { f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step) if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main->thread); return status; } @@ -905,26 +906,26 @@ extern "C" { cache->action.line_action = 0; cache->action.name_item.used = 0; - cache->action.line_item = main.setting->entry.items.array[cache->ats.array[at_i]].line; + cache->action.line_item = main->setting->entry.items.array[cache->ats.array[at_i]].line; - status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); + status = controller_string_dynamic_append_terminated(main->setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main->thread); return status; } if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Processing entry item '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_item.string, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Processing entry item '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, cache->action.name_item.string, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "'.%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } @@ -933,24 +934,24 @@ extern "C" { } else if (entry_action->type == controller_entry_action_type_consider || entry_action->type == controller_entry_action_type_rule) { - status = controller_lock_write(main.thread, &main.thread->lock.rule); + status = controller_lock_write(main->thread, &main->thread->lock.rule); if (status == F_signal) { break; } - if (!main.thread->enabled) { - f_thread_unlock(&main.thread->lock.rule); + if (!main->thread->enabled) { + f_thread_unlock(&main->thread->lock.rule); break; } - status = controller_rules_increase(&main.setting->rules); + status = controller_rules_increase(&main->setting->rules); - f_thread_unlock(&main.thread->lock.rule); + f_thread_unlock(&main->thread->lock.rule); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, main->thread); return status; } @@ -965,26 +966,26 @@ extern "C" { id_rule_name[entry_action->parameters.array[0].used] = f_path_separator_s[0]; id_rule_name[id_rule_length] = 0; - f_thread_lock_read(&main.thread->lock.rule); + f_thread_lock_read(&main->thread->lock.rule); - status = controller_rule_find(alias_rule, main.setting->rules, &at); + status = controller_rule_find(alias_rule, main->setting->rules, &at); - f_thread_unlock(&main.thread->lock.rule); + f_thread_unlock(&main->thread->lock.rule); if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "%s entry item rule '", entry_action->type == controller_entry_action_type_rule ? "Processing" : "Considering"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, alias_rule.string, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%s entry item rule '", entry_action->type == controller_entry_action_type_rule ? "Processing" : "Considering"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, alias_rule.string, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "'.%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } - if (!main.thread->enabled) break; + if (!main->thread->enabled) break; // the rule is not yet loaded, ensure that it is loaded. if (status != F_true) { @@ -1005,19 +1006,19 @@ extern "C" { memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used); memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used); - status = controller_lock_write(main.thread, &main.thread->lock.rule); + status = controller_lock_write(main->thread, &main->thread->lock.rule); if (status == F_signal) { break; } - if (!main.thread->enabled) { - f_thread_unlock(&main.thread->lock.rule); + if (!main->thread->enabled) { + f_thread_unlock(&main->thread->lock.rule); break; } - status = controller_rule_read(alias_rule, main, cache, &main.setting->rules.array[main.setting->rules.used]); + status = controller_rule_read(alias_rule, *main, cache, &main->setting->rules.array[main->setting->rules.used]); // restore cache. memcpy(cache->action.name_action.string, cache_name_action, cache_name_action_used); @@ -1035,75 +1036,75 @@ extern "C" { cache->action.line_action = cache_line_action; cache->action.line_item = cache_line_item; - if (!main.thread->enabled) { - f_thread_unlock(&main.thread->lock.rule); + if (!main->thread->enabled) { + f_thread_unlock(&main->thread->lock.rule); break; } if (F_status_is_error(status)) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - controller_entry_error_print_cache(main.data->error, cache->action); + controller_entry_error_print_cache(main->data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } if (!simulate) { - f_thread_unlock(&main.thread->lock.rule); + f_thread_unlock(&main->thread->lock.rule); break; } } else { - main.setting->rules.used++; + main->setting->rules.used++; } - f_thread_unlock(&main.thread->lock.rule); + f_thread_unlock(&main->thread->lock.rule); // ensure that a process exists for the added rule. if (F_status_is_error_not(status)) { - f_thread_lock_read(&main.thread->lock.process); + f_thread_lock_read(&main->thread->lock.process); - if (controller_find_process(alias_rule, main.thread->processs, 0) == F_false) { + if (controller_find_process(alias_rule, main->thread->processs, 0) == F_false) { - f_thread_unlock(&main.thread->lock.process); + f_thread_unlock(&main->thread->lock.process); - status = controller_lock_write(main.thread, &main.thread->lock.process); + status = controller_lock_write(main->thread, &main->thread->lock.process); if (status == F_signal) { break; } - if (!main.thread->enabled) { - f_thread_unlock(&main.thread->lock.process); + if (!main->thread->enabled) { + f_thread_unlock(&main->thread->lock.process); break; } - status = controller_processs_increase(&main.thread->processs); + status = controller_processs_increase(&main->thread->processs); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_processs_increase", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_processs_increase", F_true, main->thread); } - else if (main.thread->processs.array[main.thread->processs.used]) { + else if (main->thread->processs.array[main->thread->processs.used]) { // only copy the rule alias, as that is all that is needed at this point (the entire rule gets copied prior to executing/processing). - controller_process_t *process = main.thread->processs.array[main.thread->processs.used]; + controller_process_t *process = main->thread->processs.array[main->thread->processs.used]; - status = controller_lock_write(main.thread, &process->lock); + status = controller_lock_write(main->thread, &process->lock); if (status == F_signal) { - f_thread_unlock(&main.thread->lock.process); + f_thread_unlock(&main->thread->lock.process); break; } - if (!main.thread->enabled) { + if (!main->thread->enabled) { f_thread_unlock(&process->lock); - f_thread_unlock(&main.thread->lock.process); + f_thread_unlock(&main->thread->lock.process); break; } @@ -1113,16 +1114,16 @@ extern "C" { status = f_string_dynamic_append(alias_rule, &process->rule.alias); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, main->thread); } else { status = f_string_dynamic_terminate_after(&process->rule.alias); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true, main->thread); } else { - process->id = main.thread->processs.used++; + process->id = main->thread->processs.used++; } } @@ -1130,7 +1131,7 @@ extern "C" { } } - f_thread_unlock(&main.thread->lock.process); + f_thread_unlock(&main->thread->lock.process); } } @@ -1154,22 +1155,26 @@ extern "C" { rule_options |= controller_rule_option_wait; } - if (main.data->parameters[controller_parameter_validate].result == f_console_result_found) { + if (main->data->parameters[controller_parameter_validate].result == f_console_result_found) { rule_options |= controller_rule_option_validate; } if (entry_action->code & controller_entry_rule_code_asynchronous) { - if (main.data->parameters[controller_parameter_validate].result != f_console_result_found) { + if (main->data->parameters[controller_parameter_validate].result != f_console_result_found) { process_options |= controller_process_option_asynchronous; rule_options |= controller_rule_option_asynchronous; } } - status = controller_rule_process_begin(process_options, alias_rule, controller_rule_action_type_start, rule_options, stack, main, *cache); + status = controller_rule_process_begin(process_options, alias_rule, controller_rule_action_type_start, rule_options, stack, *main, *cache); - if (F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal || !main.thread->enabled) { + if (F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal || !main->thread->enabled) { break; } + + if (F_status_is_error(status) && !simulate && (entry_action->code & controller_entry_rule_code_require)) { + return F_status_set_error(F_require); + } } } else if (entry_action->type == controller_entry_action_type_timeout) { @@ -1187,75 +1192,89 @@ extern "C" { code = controller_string_stop_s; } - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Processing entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_timeout_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "' setting '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.important.before->string, code, main.data->context.set.important.after->string); - fprintf(main.data->output.stream, "' to '"); - fprintf(main.data->output.stream, "%s%llu%s", main.data->context.set.important.before->string, entry_action->number, main.data->context.set.important.after->string); - fprintf(main.data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Processing entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, controller_string_timeout_s, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "' setting '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.important.before->string, code, main->data->context.set.important.after->string); + fprintf(main->data->output.stream, "' to '"); + fprintf(main->data->output.stream, "%s%llu%s", main->data->context.set.important.before->string, entry_action->number, main->data->context.set.important.after->string); + fprintf(main->data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } if (entry_action->code == controller_entry_timeout_code_kill) { - main.setting->timeout_kill = entry_action->number; + main->setting->timeout_kill = entry_action->number; } else if (entry_action->code == controller_entry_timeout_code_start) { - main.setting->timeout_start = entry_action->number; + main->setting->timeout_start = entry_action->number; } else if (entry_action->code == controller_entry_timeout_code_stop) { - main.setting->timeout_stop = entry_action->number; + main->setting->timeout_stop = entry_action->number; } } else if (entry_action->type == controller_entry_action_type_failsafe) { - if (entry_action->number == 0 || entry_action->number >= main.setting->entry.items.used) { + if (failsafe) { + if (main->data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&main->thread->lock.print); - // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors. - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + fprintf(main->data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->warning.to.stream, "%s%sFailsafe may not be specified when running in failsafe, ignoring.%s%c", main->data->warning.context.before->string, main->data->warning.prefix ? main->data->warning.prefix : f_string_empty_s, main->data->warning.context.after->string, f_string_eol_s[0]); - fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->error.to.stream, "%s%sInvalid entry item index ", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s); - fprintf(main.data->error.to.stream, "%s%s%llu%s", main.data->error.context.after->string, main.data->error.notable.before->string, entry_action->number, main.data->error.notable.after->string); - fprintf(main.data->error.to.stream, "%s detected.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); + controller_entry_error_print_cache(main->data->warning, cache->action); - controller_entry_error_print_cache(main.data->error, cache->action); - - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->warning.to.stream, &main->thread->lock.print); } - - return F_status_is_error(F_critical); } else { - main.setting->failsafe_enabled = F_true; - main.setting->failsafe_rule_id = entry_action->number; + if (entry_action->number == 0 || entry_action->number >= main->setting->entry.items.used) { - if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors. + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); + + fprintf(main->data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->error.to.stream, "%s%sInvalid entry item index ", main->data->error.context.before->string, main->data->error.prefix ? main->data->error.prefix : f_string_empty_s); + fprintf(main->data->error.to.stream, "%s%s%llu%s", main->data->error.context.after->string, main->data->error.notable.before->string, entry_action->number, main->data->error.notable.after->string); + fprintf(main->data->error.to.stream, "%s detected.%s%c", main->data->error.context.before->string, main->data->error.context.after->string, f_string_eol_s[0]); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Processing entry item action '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_failsafe_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "' setting value to '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.important.before->string, main.setting->entry.items.array[main.setting->failsafe_rule_id].name.string, main.data->context.set.important.after->string); - fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]); + controller_entry_error_print_cache(main->data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->error.to.stream, &main->thread->lock.print); + } + + return F_status_is_error(F_critical); + } + else { + main->setting->failsafe_enabled = F_true; + main->setting->failsafe_item_id = entry_action->number; + + if (simulate) { + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); + + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Processing entry item action '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, controller_string_failsafe_s, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "' setting value to '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.important.before->string, main->setting->entry.items.array[main->setting->failsafe_item_id].name.string, main->data->context.set.important.after->string); + fprintf(main->data->output.stream, "'.%c", f_string_eol_s[0]); + + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); + } } } } } } // for - if (!main.thread->enabled) { + if (!main->thread->enabled) { status = F_signal; } @@ -1265,7 +1284,7 @@ extern "C" { cache->action.name_action.used = 0; if (F_status_is_error(status)) { - if (F_status_set_fine(status) == F_memory_not) { + if (F_status_set_fine(status) == F_memory_not || F_status_set_fine(status) == F_require) { break; } } @@ -1282,20 +1301,20 @@ extern "C" { cache->ats.used -= 2; cache->ats.array[at_j]++; - cache->action.line_item = main.setting->entry.items.array[cache->ats.array[at_i]].line; + cache->action.line_item = main->setting->entry.items.array[cache->ats.array[at_i]].line; cache->action.name_item.used = 0; - status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); + status = controller_string_dynamic_append_terminated(main->setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); if (F_status_is_error(status)) { - controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread); + controller_entry_error_print(main->data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main->thread); break; } } } // for - if (!main.thread->enabled) { + if (!main->thread->enabled) { return F_signal; } @@ -1303,16 +1322,20 @@ extern "C" { return status; } + // @todo wait for all asynchronous processes to complete. + // then, check to see if any "required" rule failed. + // if failed, then return F_status_set_error(F_require). + if (simulate) { - if (main.data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&main.thread->lock.print); + if (main->data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&main->thread->lock.print); - fprintf(main.data->output.stream, "%c", f_string_eol_s[0]); - fprintf(main.data->output.stream, "Done processing entry item '"); - fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_main_s, main.data->context.set.title.after->string); - fprintf(main.data->output.stream, "'.%c%c", f_string_eol_s[0], f_string_eol_s[0]); + fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); + fprintf(main->data->output.stream, "Done processing entry item '"); + fprintf(main->data->output.stream, "%s%s%s", main->data->context.set.title.before->string, controller_string_main_s, main->data->context.set.title.after->string); + fprintf(main->data->output.stream, "'.%c%c", f_string_eol_s[0], f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } } @@ -1347,11 +1370,11 @@ extern "C" { return F_status_set_error(status); } - if (status == F_failure) { - return F_status_set_error(F_failure); + if (status == F_valid_not) { + return F_status_set_error(F_valid_not); } - return F_status_set_error(F_valid_not); + return F_status_set_error(F_failure); } #endif // _di_controller_status_simplify_error_ diff --git a/level_3/controller/c/private-controller.h b/level_3/controller/c/private-controller.h index 8149c96..0788661 100644 --- a/level_3/controller/c/private-controller.h +++ b/level_3/controller/c/private-controller.h @@ -289,6 +289,9 @@ extern "C" { /** * Process (execute) all items for the loaded entry. * + * @param failsafe + * If TRUE, operate in failsafe mode (starts at designated failsafe Item). + * If FALSE, operate in normal mode (starts at "main" Item). * @param main * The main data. * @param cache @@ -296,6 +299,8 @@ extern "C" { * * @return * F_none on success. + * + * F_require (with error bit) if a required entry item failed. * F_critical (with error bit) on any critical error. * * Errors (with error bit) from: f_macro_array_lengths_t_increase_by(). @@ -307,7 +312,7 @@ extern "C" { * @see controller_string_dynamic_append_terminated() */ #ifndef _di_controller_process_entry_ - extern f_status_t controller_process_entry(controller_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal; + extern f_status_t controller_process_entry(const bool failsafe, controller_main_t *main, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_process_entry_ /** diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c index 1b6a604..4f98dd1 100644 --- a/level_3/controller/c/private-entry.c +++ b/level_3/controller/c/private-entry.c @@ -673,7 +673,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]); fprintf(main.data->error.to.stream, "%s%sThe entry file is empty.%s%c", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_data_not); @@ -762,7 +762,7 @@ extern "C" { controller_entry_error_print_cache(main.data->warning, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } code |= 0x2; @@ -811,7 +811,7 @@ extern "C" { controller_entry_error_print_cache(main.data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (F_status_set_fine(status) == F_memory_not) { break; @@ -832,7 +832,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_main_s, main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' was not found.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_found_not); @@ -896,15 +896,12 @@ extern "C" { controller_entry_error_print_cache(main.data->error, cache->action); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } action->number = 0; action->status = controller_status_simplify_error(F_found_not); - // @fixme review how main.setting->entry.status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). - //main.setting->entry.status = controller_status_simplify_error(F_found_not); - cache->action.name_action.used = 0; cache->action.name_item.used = 0; } @@ -914,12 +911,6 @@ extern "C" { } } // for } // for - - // the error is already fully printed and the entry status is already assigned, so immediately exit. - if (missing & 0x2) { - // @fixme review how main.setting->entry.status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). - //return main.setting->entry.status; - } } } } diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 11f76ce..70e6bb2 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -426,7 +426,7 @@ extern "C" { controller_rule_error_print_cache(main.data->warning, cache->action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } } @@ -913,7 +913,7 @@ extern "C" { controller_rule_error_print_cache(main.data->warning, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } if (success == F_false) { @@ -955,6 +955,8 @@ extern "C" { f_status_t controller_rule_execute_foreground(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 status = F_none; + f_status_t status_lock = F_none; + int result = 0; pid_t id_child = 0; @@ -996,10 +998,10 @@ extern "C" { f_thread_unlock(&process->lock); - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { - return status; + if (status_lock == F_signal) { + return status_lock; } if (!main.thread->enabled) { @@ -1023,10 +1025,10 @@ extern "C" { return F_signal; } - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { - return status; + if (status_lock == F_signal) { + return status_lock; } if (!main.thread->enabled) { @@ -1086,7 +1088,7 @@ extern "C" { controller_error_print(main.data->error, F_status_set_fine(status), "fll_execute_program", F_true, main.thread); } - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); status = F_status_set_error(status); } @@ -1099,6 +1101,8 @@ extern "C" { f_status_t controller_rule_execute_pid_with(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 status = F_none; + f_status_t status_lock = F_none; + int result = 0; pid_t id_child = 0; @@ -1149,10 +1153,10 @@ extern "C" { f_thread_unlock(&process->lock); - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { - return status; + if (status_lock == F_signal) { + return status_lock; } if (!main.thread->enabled) { @@ -1176,10 +1180,10 @@ extern "C" { return F_signal; } - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { - return status; + if (status_lock == F_signal) { + return status_lock; } if (!main.thread->enabled) { @@ -1239,7 +1243,7 @@ extern "C" { controller_error_print(main.data->error, F_status_set_fine(status), "fll_execute_program", F_true, main.thread); } - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); return F_status_set_error(status); } @@ -1405,7 +1409,7 @@ extern "C" { controller_rule_error_print_cache(main.data->warning, cache->action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } continue; @@ -1424,7 +1428,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_supported_not); @@ -1626,13 +1630,14 @@ extern "C" { controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } return F_status_set_error(F_parameter); } f_status_t status = F_none; + f_status_t status_lock = F_none; process->cache.action.name_action.used = 0; process->cache.action.name_item.used = 0; @@ -1752,7 +1757,7 @@ extern "C" { controller_rule_item_error_print_need_want_wish(main.data->error, strings[i], dynamics[i]->array[j].string, "was not found"); controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); status = F_status_set_error(F_found_not); @@ -1773,7 +1778,7 @@ extern "C" { controller_rule_item_error_print_need_want_wish(main.data->warning, strings[i], dynamics[i]->array[j].string, "was not found"); controller_rule_error_print_cache(main.data->warning, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } } } @@ -1839,7 +1844,7 @@ extern "C" { controller_rule_item_error_print_need_want_wish(main.data->error, strings[i], alias_other_buffer, "failed during execution"); controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (!(process_other->options & controller_rule_option_simulate) || F_status_set_fine(status) == F_memory_not) { f_thread_unlock(&process_other->active); @@ -1854,7 +1859,7 @@ extern "C" { controller_rule_item_error_print_need_want_wish(main.data->warning, strings[i], alias_other_buffer, "failed during execution"); controller_rule_error_print_cache(main.data->warning, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } } } @@ -1882,7 +1887,7 @@ extern "C" { status = F_status_set_error(F_found_not); controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (!(process_other->options & controller_rule_option_simulate)) { f_thread_unlock(&main.thread->lock.rule); @@ -1901,7 +1906,7 @@ extern "C" { controller_rule_item_error_print_need_want_wish(main.data->warning, strings[i], alias_other_buffer, "is in a failed state"); controller_rule_error_print_cache(main.data->warning, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } } } @@ -1975,7 +1980,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_parameter); @@ -2003,12 +2008,12 @@ extern "C" { f_thread_unlock(&process->lock); - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { + if (status_lock == F_signal) { f_thread_lock_read(&process->lock); - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2025,13 +2030,13 @@ extern "C" { process->rule.status = status; } - status = controller_lock_write(main.thread, &main.thread->lock.rule); + status_lock = controller_lock_write(main.thread, &main.thread->lock.rule); - if (status == F_signal) { + if (status_lock == F_signal) { f_thread_unlock(&process->lock); f_thread_lock_read(&process->lock); - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2105,7 +2110,7 @@ extern "C" { controller_rule_item_error_print_rule_not_loaded(main.data->error, alias_rule.string); controller_rule_error_print_cache(main.data->error, cache.action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } return status; @@ -2285,6 +2290,8 @@ extern "C" { } f_status_t status = F_none; + f_status_t status_lock = F_none; + f_array_length_t id_rule = 0; const f_array_length_t used_original_stack = process->stack.used; @@ -2295,14 +2302,14 @@ extern "C" { f_thread_unlock(&process->lock); - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { + if (status_lock == F_signal) { if (options & controller_process_option_asynchronous) { f_thread_unlock(&process->active); } - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2341,7 +2348,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, process->cache.action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } // never continue on circular recursion errors even in simulate mode. @@ -2370,14 +2377,14 @@ extern "C" { else { f_thread_unlock(&process->lock); - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { + if (status_lock == F_signal) { if (options & controller_process_option_asynchronous) { f_thread_unlock(&process->active); } - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2401,14 +2408,14 @@ extern "C" { if (F_status_is_error(status)) { f_thread_unlock(&main.thread->lock.rule); - status = controller_lock_write(main.thread, &main.thread->lock.rule); + status_lock = controller_lock_write(main.thread, &main.thread->lock.rule); - if (status == F_signal) { + if (status_lock == F_signal) { if (options & controller_process_option_asynchronous) { f_thread_unlock(&process->active); } - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2436,14 +2443,14 @@ extern "C" { else { f_thread_unlock(&main.thread->lock.rule); - status = controller_lock_write(main.thread, &main.thread->lock.rule); + status_lock = controller_lock_write(main.thread, &main.thread->lock.rule); - if (status == F_signal) { + if (status_lock == F_signal) { if (options & controller_process_option_asynchronous) { f_thread_unlock(&process->active); } - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2470,7 +2477,7 @@ extern "C" { controller_rule_item_error_print_rule_not_loaded(main.data->error, process->rule.alias.string); controller_rule_error_print_cache(main.data->error, process->cache.action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } @@ -2488,14 +2495,14 @@ extern "C" { return status; } - status = controller_lock_write(main.thread, &process->lock); + status_lock = controller_lock_write(main.thread, &process->lock); - if (status == F_signal) { + if (status_lock == F_signal) { if (options & controller_process_option_asynchronous) { f_thread_unlock(&process->active); } - return status; + return status_lock; } if (!main.thread->enabled) { @@ -2934,7 +2941,7 @@ extern "C" { controller_rule_error_print_cache(main.data->warning, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } continue; @@ -2955,7 +2962,7 @@ extern "C" { controller_rule_error_print_cache(main.data->warning, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->warning.to.stream, &main.thread->lock.print); } continue; @@ -3018,7 +3025,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3074,7 +3081,7 @@ extern "C" { f_print_dynamic_partial(main.data->error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); fprintf(main.data->error.to.stream, "%s%s', the number is too large for this system.%s%c", main.data->error.notable.after->string, main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } else { f_thread_mutex_lock(&main.thread->lock.print); @@ -3085,7 +3092,7 @@ extern "C" { f_print_dynamic_partial(main.data->error.to.stream, cache->buffer_item, cache->content_actions.array[i].array[j]); fprintf(main.data->error.to.stream, "%s%s', only whole numbers are allowed for an affinity value.%s%c", main.data->error.notable.after->string, main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } // get the current line number within the settings item. @@ -3140,7 +3147,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3265,7 +3272,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3299,7 +3306,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3386,7 +3393,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3463,7 +3470,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_true); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3491,7 +3498,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_valid_not); @@ -3566,7 +3573,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } status = F_status_set_error(F_valid_not); @@ -3630,7 +3637,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3690,7 +3697,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3703,7 +3710,7 @@ extern "C" { // this function should only return F_complete_not_utf on error. controller_rule_error_print(main.data->error, cache->action, F_complete_not_utf, "controller_validate_has_graph", F_true, F_false, main.thread); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (F_status_is_error_not(status_return)) { status_return = status; @@ -3782,7 +3789,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3834,7 +3841,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3887,7 +3894,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3932,7 +3939,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -3960,7 +3967,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (F_status_set_fine(status) == F_memory_not) { status_return = status; @@ -3987,7 +3994,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); if (F_status_set_fine(status) == F_memory_not) { status_return = status; @@ -4015,7 +4022,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); status_return = status; break; @@ -4035,7 +4042,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -4076,7 +4083,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -4116,7 +4123,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because no user was found by that name.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else if (status == F_number_too_large) { @@ -4130,7 +4137,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because the given ID is too large.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else if (status == F_number) { @@ -4144,7 +4151,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because the given ID is not a valid supported number.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else { @@ -4188,7 +4195,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -4245,7 +4252,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because no group was found by that name.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else if (status == F_number_too_large) { @@ -4259,7 +4266,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because the given ID is too large.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else if (status == F_number) { @@ -4273,7 +4280,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s' because the given ID is not a valid supported number.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } } else { @@ -4395,7 +4402,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -4447,7 +4454,7 @@ extern "C" { controller_rule_error_print_cache(main.data->error, cache->action, F_false); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } if (F_status_is_error_not(status_return)) { @@ -4554,7 +4561,7 @@ extern "C" { fprintf(main.data->error.to.stream, "%s", main.data->error.notable.after->string); fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]); - controller_print_unlock_flush(main.data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(main.data->error.to.stream, &main.thread->lock.print); } setting_values->array[setting_values->used].used = 0; @@ -4603,7 +4610,7 @@ extern "C" { controller_rule_error_print_cache(data->error, cache->action, F_true); } - controller_print_unlock_flush(data->output.stream, &main.thread->lock.print); + controller_print_unlock_flush(data->error.to.stream, &main.thread->lock.print); return; } diff --git a/level_3/controller/c/private-thread.c b/level_3/controller/c/private-thread.c index c9bce23..349faf9 100644 --- a/level_3/controller/c/private-thread.c +++ b/level_3/controller/c/private-thread.c @@ -486,10 +486,27 @@ extern "C" { *status = F_status_set_error(F_available_not); } else { - *status = controller_process_entry(*entry->main, cache); + *status = controller_process_entry(F_false, entry->main, cache); if (F_status_is_error(*status)) { entry->setting->ready = controller_setting_ready_fail; + + if (F_status_set_fine(*status) == F_require && entry->main->setting->failsafe_enabled) { + const f_status_t status_failsafe = controller_process_entry(F_true, entry->main, cache); + + if (F_status_is_error(status_failsafe)) { + if (data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&entry->main->thread->lock.print); + + fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data->error.to.stream, "%s%sFailed while processing requested failsafe item '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); + fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, entry->main->setting->entry.items.array[entry->main->setting->failsafe_enabled].name.string, data->error.notable.after->string); + fprintf(data->error.to.stream, "%s'.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + + controller_print_unlock_flush(data->error.to.stream, &entry->main->thread->lock.print); + } + } + } } else if (*status == F_signal || *status == F_child) { entry->setting->ready = controller_setting_ready_abort; diff --git a/level_3/controller/data/settings/example/entries/test.entry b/level_3/controller/data/settings/example/entries/test.entry index 2efd908..6576bd6 100644 --- a/level_3/controller/data/settings/example/entries/test.entry +++ b/level_3/controller/data/settings/example/entries/test.entry @@ -21,7 +21,7 @@ first: #rule script python last: - rule script fail + rule script fail require wait boom: rule maintenance explode diff --git a/level_3/controller/data/settings/example/rules/script/fail.rule b/level_3/controller/data/settings/example/rules/script/fail.rule index 059a7f7..560bd78 100644 --- a/level_3/controller/data/settings/example/rules/script/fail.rule +++ b/level_3/controller/data/settings/example/rules/script/fail.rule @@ -8,7 +8,7 @@ script: start { \#!/bin/bash my_function() { - echo "Hello this is the last script." + echo "Hello this is the last script, it should trigger failure." return 1; \} -- 1.8.3.1