From 102078870773a68b3c3ba9e9224499b433d43008 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 26 Apr 2021 23:09:09 -0500 Subject: [PATCH] Regression: Entry error after failure or during validation is not propogating. When an Entry fails and successfully executes a failsafe, the failure is not propagated. The failsafe is meant to bail out and not continue onward, so after a successful or failed failsafe, return F_failure (with error bit as appropriate). When passing --validate without --test, the program is not exiting as it should. This is because the state is not being handled just like the status is not being handled. When joining threads, be sure to reset the identifiers. Remove now extra Exit processing block. This is now handled fully by the cancellation function. Restore the thread enabled state after operating failsafe. Get rid of simulate variable, instead use the console parameter directly. This saves memory by a trivial amount. --- level_3/controller/c/private-controller.c | 40 ++++++++++---------- level_3/controller/c/private-rule.c | 6 +-- level_3/controller/c/private-thread.c | 61 ++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index 0121219..7ead049 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -710,8 +710,6 @@ 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; - cache->ats.used = 0; cache->stack.used = 0; @@ -749,7 +747,7 @@ extern "C" { return status; } - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -783,7 +781,7 @@ extern "C" { if (F_status_is_error(entry_action->status)) { if (controller_entry_action_type_is_rule(entry_action->type)) { - if (simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -853,7 +851,7 @@ extern "C" { } } else { - if (simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -900,7 +898,7 @@ extern "C" { if (entry_action->type == controller_entry_action_type_ready) { if (entry_action->code & controller_entry_rule_code_wait) { - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -919,7 +917,7 @@ extern "C" { } if (main->setting->ready == controller_setting_ready_wait) { - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -932,7 +930,7 @@ extern "C" { } } - if (!simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_none) { status = controller_perform_ready(is_entry, *main, cache); if (F_status_is_error(status)) return status; @@ -940,7 +938,7 @@ extern "C" { main->setting->ready = controller_setting_ready_yes; } - else if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + else if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -1004,7 +1002,7 @@ extern "C" { return status; } - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -1061,7 +1059,7 @@ extern "C" { f_thread_unlock(&main->thread->lock.rule); - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -1139,7 +1137,7 @@ extern "C" { controller_print_unlock_flush(main->data->output.stream, &main->thread->lock.print); } - if (!simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_none) { f_thread_unlock(&main->thread->lock.rule); break; @@ -1156,7 +1154,7 @@ extern "C" { options_force = 0; options_process = 0; - if (simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found) { options_process |= controller_process_option_simulate; } @@ -1173,7 +1171,7 @@ extern "C" { } 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_none) { options_force |= controller_process_option_asynchronous; } @@ -1186,13 +1184,13 @@ extern "C" { break; } - if (F_status_is_error(status) && !simulate && (entry_action->code & controller_entry_rule_code_require)) { + if (F_status_is_error(status) && main->data->parameters[controller_parameter_test].result == f_console_result_none && (entry_action->code & controller_entry_rule_code_require)) { return F_status_set_error(F_require); } } } else if (entry_action->type == controller_entry_action_type_execute) { - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -1214,7 +1212,7 @@ extern "C" { } } - if (simulate) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found) { return F_execute; } @@ -1266,7 +1264,7 @@ extern "C" { } else if (entry_action->type == controller_entry_action_type_timeout) { - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { f_string_t code = ""; if (entry_action->code == controller_entry_timeout_code_kill) { @@ -1342,7 +1340,7 @@ extern "C" { main->setting->failsafe_enabled = F_true; main->setting->failsafe_item_id = entry_action->number; - if (simulate || main->data->error.verbosity == f_console_verbosity_verbose) { + if (main->data->parameters[controller_parameter_test].result == f_console_result_found || main->data->error.verbosity == f_console_verbosity_verbose) { if (main->data->error.verbosity != f_console_verbosity_quiet) { f_thread_mutex_lock(&main->thread->lock.print); @@ -1409,7 +1407,7 @@ extern "C" { return status_lock; } - // check to see if any requied processes failed, but do not do this if already operating in failsafe. + // check to see if any required processes failed, but do not do this if already operating in failsafe. if (F_status_is_error_not(status) && !failsafe && main->data->parameters[controller_parameter_validate].result == f_console_result_none) { const f_status_t status_wait = controller_rule_wait_all(is_entry, *main, F_true, 0); @@ -1422,7 +1420,7 @@ extern "C" { } } - if ((simulate && main->data->error.verbosity != f_console_verbosity_quiet) || main->data->error.verbosity == f_console_verbosity_verbose) { + if ((main->data->parameters[controller_parameter_test].result == f_console_result_found && main->data->error.verbosity != f_console_verbosity_quiet) || main->data->error.verbosity == f_console_verbosity_verbose) { f_thread_mutex_lock(&main->thread->lock.print); fprintf(main->data->output.stream, "%c", f_string_eol_s[0]); diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index aca7756..32eb0fd 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -1917,7 +1917,7 @@ extern "C" { return status; } - if ((process->options & controller_process_option_simulate) && main.data->parameters[controller_parameter_validate].result == f_console_result_found) { + if ((process->options & controller_process_option_simulate) && (process->options & controller_process_option_validate)) { controller_rule_validate(process->rule, process->action, process->options, main, &process->cache); } @@ -2129,7 +2129,7 @@ extern "C" { options_process |= controller_process_option_simulate; } - if (main.data->parameters[controller_parameter_validate].result == f_console_result_found) { + if (process->options & controller_process_option_validate) { options_process |= controller_process_option_validate; } @@ -2252,7 +2252,7 @@ extern "C" { return F_signal; } - if ((process->options & controller_process_option_wait) && F_status_is_error_not(status) && main.data->parameters[controller_parameter_validate].result == f_console_result_none) { + if ((process->options & controller_process_option_wait) && F_status_is_error_not(status) && (process->options & controller_process_option_validate)) { status_lock = controller_rule_wait_all_process_type(process->type, main, F_false, process); diff --git a/level_3/controller/c/private-thread.c b/level_3/controller/c/private-thread.c index 2e16238..bc6ee79 100644 --- a/level_3/controller/c/private-thread.c +++ b/level_3/controller/c/private-thread.c @@ -234,12 +234,13 @@ extern "C" { controller_thread_join(&thread.id_entry); status = thread.status; + thread.id_entry = 0; } } } // only make the rule and control threads available once any/all pre-processing and are completed. - if (F_status_is_error_not(status) && status != F_signal && status != F_child && thread.enabled == controller_thread_enabled) { + if (F_status_is_error_not(status) && status != F_signal && status != F_failure && status != F_child && thread.enabled == controller_thread_enabled) { if (data->parameters[controller_parameter_validate].result == f_console_result_none) { @@ -280,30 +281,12 @@ extern "C" { return F_child; } - if (F_status_is_error(status) || status == F_signal || !(data->parameters[controller_parameter_validate].result == f_console_result_none || data->parameters[controller_parameter_test].result == f_console_result_found)) { + if (F_status_is_error_not(status) && status != F_signal && status != F_failure && data->parameters[controller_parameter_validate].result == f_console_result_none && controller_thread_is_enabled(F_true, &thread)) { - if (main.data->parameters[controller_parameter_validate].result == f_console_result_found) { - const controller_main_entry_t entry = controller_macro_main_entry_t_initialize(&main, main.setting); - - status = f_thread_create(0, &thread.id_entry, &controller_thread_exit, (void *) &entry); - - if (F_status_is_error(status)) { - if (data->error.verbosity != f_console_verbosity_quiet) { - controller_error_print(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread); - } - } - else { - controller_thread_join(&thread.id_entry); - - status = thread.status; - } - } - } - else { - if (data->parameters[controller_parameter_validate].result == f_console_result_none && setting->mode == controller_setting_mode_service) { + if (setting->mode == controller_setting_mode_service) { controller_thread_join(&thread.id_signal); } - else if (data->parameters[controller_parameter_validate].result == f_console_result_none && setting->mode == controller_setting_mode_program) { + else if (setting->mode == controller_setting_mode_program) { controller_rule_wait_all(F_true, main, F_false, 0); } } @@ -732,6 +715,8 @@ extern "C" { if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && entry->main->setting->failsafe_enabled) { + const uint8_t original_enabled = entry->main->thread->enabled; + // restore operating mode so that the failsafe can execute. *status = f_thread_mutex_lock(&entry->main->thread->lock.alert); @@ -759,6 +744,21 @@ extern "C" { controller_print_unlock_flush(data->error.to.stream, &entry->main->thread->lock.print); } + + *status = F_status_set_error(F_failure); + } + else { + + // restore operating mode to value prior to failsafe mode. + *status = f_thread_mutex_lock(&entry->main->thread->lock.alert); + + if (F_status_is_error_not(*status)) { + entry->main->thread->enabled = original_enabled; + + f_thread_mutex_unlock(&entry->main->thread->lock.alert); + } + + *status = F_failure; } } } @@ -824,6 +824,8 @@ extern "C" { if ((F_status_set_fine(*status) == F_execute || F_status_set_fine(*status) == F_require) && entry->main->setting->failsafe_enabled) { + const uint8_t original_enabled = entry->main->thread->enabled; + // restore operating mode so that the failsafe can execute. if (F_status_set_fine(*status) == F_execute) { *status = f_thread_mutex_lock(&entry->main->thread->lock.alert); @@ -853,6 +855,21 @@ extern "C" { controller_print_unlock_flush(data->error.to.stream, &entry->main->thread->lock.print); } + + *status = F_status_set_error(F_failure); + } + else { + + // restore operating mode to value prior to failsafe mode. + *status = f_thread_mutex_lock(&entry->main->thread->lock.alert); + + if (F_status_is_error_not(*status)) { + entry->main->thread->enabled = original_enabled; + + f_thread_mutex_unlock(&entry->main->thread->lock.alert); + } + + *status = F_failure; } } } -- 1.8.3.1